]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: add interface to check the presence of subvolumegroups/subvolumes
authorNeeraj Pratap Singh <neesingh@redhat.com>
Fri, 24 Jun 2022 06:22:38 +0000 (11:52 +0530)
committerNeeraj Pratap Singh <neesingh@redhat.com>
Fri, 5 Aug 2022 06:36:55 +0000 (12:06 +0530)
Fixes: https://tracker.ceph.com/issues/55821
Signed-off-by: Neeraj Pratap Singh <neesingh@redhat.com>
(cherry picked from commit 4eff1bb534561a92fd5b1184526526c5f15f9cac)

src/pybind/mgr/volumes/fs/fs_util.py
src/pybind/mgr/volumes/fs/operations/group.py
src/pybind/mgr/volumes/fs/vol_spec.py
src/pybind/mgr/volumes/fs/volume.py
src/pybind/mgr/volumes/module.py

index 05a6e52caf54cd1f7378a664526f139d8bd5a453..be0a06acdd8997d2d7de06dffe653038e6d58c39 100644 (file)
@@ -88,6 +88,28 @@ def listdir(fs, dirpath, filter_entries=None):
         raise VolumeException(-e.args[0], e.args[1])
     return dirs
 
+
+def has_subdir(fs, dirpath, filter_entries=None):
+    """
+    Check the presence of directory (only dirs) for a given path
+    """
+    res = False
+    if filter_entries is None:
+        filter_entries = [b".", b".."]
+    else:
+        filter_entries.extend([b".", b".."])
+    try:
+        with fs.opendir(dirpath) as dir_handle:
+            d = fs.readdir(dir_handle)
+            while d:
+                if (d.d_name not in filter_entries) and d.is_dir():
+                    res = True
+                    break
+                d = fs.readdir(dir_handle)
+    except cephfs.Error as e:
+        raise VolumeException(-e.args[0], e.args[1])
+    return res
+
 def is_inherited_snap(snapname):
     """
     Returns True if the snapname is inherited else False
index d23f3a44a7f80334b00be8fba339236838d7a8af..dac744a306cfe93f18e1ec73b5e8a132a1e6deb5 100644 (file)
@@ -8,7 +8,7 @@ import cephfs
 from .snapshot_util import mksnap, rmsnap
 from .pin_util import pin
 from .template import GroupTemplate
-from ..fs_util import listdir, listsnaps, get_ancestor_xattr, create_base_dir
+from ..fs_util import listdir, listsnaps, get_ancestor_xattr, create_base_dir, has_subdir
 from ..exception import VolumeException
 
 log = logging.getLogger(__name__)
@@ -64,6 +64,15 @@ class Group(GroupTemplate):
                 return []
             raise
 
+    def has_subvolumes(self):
+        try:
+            return has_subdir(self.fs, self.path)
+        except VolumeException as ve:
+            # listing a default group when it's not yet created
+            if ve.errno == -errno.ENOENT and self.is_default_group():
+                return False
+            raise
+
     def pin(self, pin_type, pin_setting):
         return pin(self.fs, self.path, pin_type, pin_setting)
 
index 422359e03c9ea7a1e6ce49d888ec8568d4b659de..a3ba1308bca0be3de099d200428304f1ec71c3bb 100644 (file)
@@ -1,3 +1,9 @@
+from .operations.index import Index
+from .operations.group import Group
+from .operations.trash import Trash
+from .operations.versions.subvolume_base import SubvolumeBase
+
+
 class VolSpec(object):
     """
     specification of a "volume" -- base directory and various prefixes.
@@ -9,6 +15,8 @@ class VolSpec(object):
     DEFAULT_NS_PREFIX = "fsvolumens_"
     # default mode for subvol prefix and group
     DEFAULT_MODE = 0o755
+    # internal directories
+    INTERNAL_DIRS = [Group.NO_GROUP_NAME, Index.GROUP_NAME, Trash.GROUP_NAME, SubvolumeBase.LEGACY_CONF_DIR]
 
     def __init__(self, snapshot_prefix, subvolume_prefix=None, pool_ns_prefix=None):
         self.snapshot_prefix = snapshot_prefix
index cd127fc5efbced73f897425b8614971a2f164d18..faa969c52a724a2e0f708f67b7bc9e2cec7aa30f 100644 (file)
@@ -1,13 +1,14 @@
 import json
 import errno
 import logging
+import os
 from typing import TYPE_CHECKING
 
 import cephfs
 
 from mgr_util import CephfsClient
 
-from .fs_util import listdir
+from .fs_util import listdir, has_subdir
 
 from .operations.volume import create_volume, \
     delete_volume, rename_volume, list_volumes, open_volume, get_pool_names
@@ -466,6 +467,28 @@ class VolumeClient(CephfsClient["Module"]):
             ret = self.volume_exception_to_retval(ve)
         return ret
 
+    def subvolume_exists(self, **kwargs):
+        volname = kwargs['vol_name']
+        groupname = kwargs['group_name']
+        ret = 0, "", ""
+        volume_exists = False
+
+        try:
+            with open_volume(self, volname) as fs_handle:
+                volume_exists = True
+                with open_group(fs_handle, self.volspec, groupname) as group:
+                    res = group.has_subvolumes()
+                    if res:
+                        ret = 0, "subvolume exists", ""
+                    else:
+                        ret = 0, "no subvolume exists", ""
+        except VolumeException as ve:
+            if volume_exists and ve.errno == -errno.ENOENT:
+                ret = 0, "no subvolume exists", ""
+            else:
+                ret = self.volume_exception_to_retval(ve)
+        return ret
+
     ### subvolume snapshot
 
     def create_subvolume_snapshot(self, **kwargs):
@@ -864,6 +887,27 @@ class VolumeClient(CephfsClient["Module"]):
             ret = self.volume_exception_to_retval(ve)
         return ret
 
+    def subvolume_group_exists(self, **kwargs):
+        volname = kwargs['vol_name']
+        ret = 0, "", ""
+        volume_exists = False
+
+        try:
+            with open_volume(self, volname) as fs_handle:
+                volume_exists = True
+                res = has_subdir(fs_handle, self.volspec.base_dir, filter_entries=[
+                                 dir.encode('utf-8') for dir in self.volspec.INTERNAL_DIRS])
+                if res:
+                    ret = 0, "subvolumegroup exists", ""
+                else:
+                    ret = 0, "no subvolumegroup exists", ""
+        except VolumeException as ve:
+            if volume_exists and ve.errno == -errno.ENOENT:
+                ret = 0, "no subvolumegroup exists", ""
+            else:
+                ret = self.volume_exception_to_retval(ve)
+        return ret
+
     ### group snapshot
 
     def create_subvolume_group_snapshot(self, **kwargs):
index 560d85a78bf9ffef4b6d2d1d91869be16548e97a..7f2e3993cdb0ae1b47bd75d3922385dbba573cae 100644 (file)
@@ -111,6 +111,12 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
             'desc': "Resize a CephFS subvolume group",
             'perm': 'rw'
         },
+        {
+            'cmd': 'fs subvolumegroup exist '
+                   'name=vol_name,type=CephString ',
+            'desc': "Check a volume for the existence of subvolumegroup",
+            'perm': 'r'
+        },
         {
             'cmd': 'fs subvolume ls '
                    'name=vol_name,type=CephString '
@@ -210,6 +216,14 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                     "and optionally, in a specific subvolume group",
             'perm': 'r'
         },
+        {
+            'cmd': 'fs subvolume exist '
+                   'name=vol_name,type=CephString '
+                   'name=group_name,type=CephString,req=false ',
+            'desc': "Check a volume for the existence of a subvolume, "
+                    "optionally in a specified subvolume group",
+            'perm': 'r'
+        },
         {
             'cmd': 'fs subvolume metadata set '
                    'name=vol_name,type=CephString '
@@ -567,6 +581,10 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
     def _cmd_fs_subvolumegroup_ls(self, inbuf, cmd):
         return self.vc.list_subvolume_groups(vol_name=cmd['vol_name'])
 
+    @mgr_cmd_wrap
+    def _cmd_fs_subvolumegroup_exist(self, inbuf, cmd):
+        return self.vc.subvolume_group_exists(vol_name=cmd['vol_name'])
+
     @mgr_cmd_wrap
     def _cmd_fs_subvolume_create(self, inbuf, cmd):
         """
@@ -657,6 +675,11 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                                       sub_name=cmd['sub_name'],
                                       group_name=cmd.get('group_name', None))
 
+    @mgr_cmd_wrap
+    def _cmd_fs_subvolume_exist(self, inbuf, cmd):
+        return self.vc.subvolume_exists(vol_name=cmd['vol_name'],
+                                        group_name=cmd.get('group_name', None))
+    
     @mgr_cmd_wrap
     def _cmd_fs_subvolume_metadata_set(self, inbuf, cmd):
         return self.vc.set_user_metadata(vol_name=cmd['vol_name'],