]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
pybind/mgr/volumes: add getter and setter APIs for snapdir_visibility
authorDhairya Parmar <dparmar@redhat.com>
Fri, 25 Jul 2025 14:45:06 +0000 (20:15 +0530)
committerDhairya Parmar <dparmar@redhat.com>
Mon, 29 Sep 2025 08:40:53 +0000 (14:10 +0530)
Conflicts:
fscrypt changes exist downstream 01a4d2a0356e5f66b7260dad7de70a5fa9cc3aa7 but not upstream,
so it led to a conflict, kept both the changes in the branch.

Fixes: https://tracker.ceph.com/issues/71740
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
(cherry picked from commit 7a33e22c7d572ec8f48cd6973aa9da4737b6582b)
Resolves: https://jsw.ibm.com/browse/ISCE-1465

src/pybind/mgr/volumes/fs/operations/template.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
src/pybind/mgr/volumes/fs/volume.py
src/pybind/mgr/volumes/module.py

index 428a484786fc231220d2e06f788aba74f20c77e9..32b8e16126423fbbae8dcb461198a9821d0194ea 100644 (file)
@@ -76,6 +76,7 @@ class SubvolumeOpType(Enum):
     ENCTAG_GET            = 'enctag-get'
     ENCTAG_SET            = 'enctag-set'
     ENCTAG_CLEAR          = 'enctag-clear'
+    SNAPSHOT_VISIBILITY   = 'snapshot-visibility'
 
 class SubvolumeTemplate(object):
     VERSION = None # type: int
index f8b8ce14c47f1f33e3658bee8afa523d37782177..943e106c00c7c8785295d8cb6498a9c474d0e46f 100644 (file)
@@ -655,3 +655,62 @@ class SubvolumeBase(object):
                       f"subvolume={self.subvol_name} group={self.group_name} "
                       f"reason={me.args[1]}, errno:{-me.args[0]}, {os.strerror(-me.args[0])}")
             raise VolumeException(-me.args[0], me.args[1])
+
+    def snapshot_visibility_set(self, value):
+        if value not in ("true", "false"):
+            raise VolumeException(-errno.EINVAL, "snapshot visibility value invalid")
+
+        subvol_root_path = os.path.dirname(self.path)
+        subvol_v2_path = self.path
+        snaps_visibility_vxattr = "ceph.dir.subvolume.snaps.visible"
+        subvolume_size = 0
+        try:
+            self.fs.setxattr(subvol_root_path, snaps_visibility_vxattr,
+                             str(value).encode('utf-8'), 0)
+        except cephfs.Error as e:
+            raise VolumeException(-e.args[0], e.args[1])
+
+        # in case of a sized subvolume, a new srnode will be assigned to the
+        # volumes/<group-name>/<subvolume-name>/<uuid>/ path when applying
+        # ceph.quota.max_bytes which would assign it with the default value
+        # of is_snapdir_visible flag and right now the child snaprealm
+        # changes are not being compiled and sent to the client by MDS, so until
+        # that gets addressed, as a quick fix apply the vxattr on subvol root
+        # and the uuid path. Once the child snaprealm fix is in place, apply
+        # the vxattr only to subvolume root.
+        try:
+            subvolume_size = self.fs.getxattr(
+                subvol_v2_path, "ceph.quota.max_bytes").decode('utf-8')
+        except cephfs.NoData:
+            # should be non-sized subvol v2 path
+            pass
+        if int(subvolume_size) > 0:
+            try:
+                self.fs.setxattr(subvol_v2_path, snaps_visibility_vxattr,
+                                 str(value).encode('utf-8'), 0)
+            except cephfs.Error as e:
+                raise VolumeException(-e.args[0], e.args[1])
+
+            try:
+                 subvol_v2_path_snapshot_visibility = self.fs.getxattr(subvol_v2_path,
+                                        snaps_visibility_vxattr).decode('utf-8')
+                 if bool(subvol_v2_path_snapshot_visibility) != bool(value):
+                     raise VolumeException(-errno.EINVAL, "could not set "
+                                           f"{snaps_visibility_vxattr} to {value} "
+                                           f"on subvolume v2 path {subvol_v2_path}")
+            except cephfs.Error as e:
+                raise VolumeException(-e.args[0], e.args[1])
+
+        try:
+            return self.fs.getxattr(subvol_root_path,
+                                    snaps_visibility_vxattr).decode('utf-8')
+        except cephfs.Error as e:
+            raise VolumeException(-e.args[0], e.args[1])
+
+    def snapshot_visibility_get(self):
+        subvol_parent_path = os.path.dirname(self.path)
+        try:
+            return self.fs.getxattr(subvol_parent_path,
+                                    "ceph.dir.subvolume.snaps.visible").decode('utf-8')
+        except cephfs.Error as e:
+            raise VolumeException(-e.args[0], e.args[1])
index 4de3982e2a97fb8f0659c24e1c8b7656d010dfcb..be0625280c4633d4b8e5ab4498346342bfebeb7f 100644 (file)
@@ -1391,3 +1391,38 @@ class VolumeClient(CephfsClient["Module"]):
         except VolumeException as ve:
             ret = self.volume_exception_to_retval(ve)
         return ret
+
+    def subvolume_snapshot_visibility_set(self, **kwargs):
+        ret = 0, "", ""
+        volname = kwargs['vol_name']
+        subvolname = kwargs['sub_name']
+        groupname = kwargs['group_name']
+        value = kwargs['value']
+
+        try:
+            with open_volume(self, volname) as fs_handle:
+                with open_group(fs_handle, self.volspec, groupname) as group:
+                    with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname,
+                                     SubvolumeOpType.SNAPSHOT_VISIBILITY) as subvolume:
+                        v = subvolume.snapshot_visibility_set(value)
+                        ret = 0, v, ""
+        except VolumeException as ve:
+            ret = self.volume_exception_to_retval(ve)
+        return ret
+
+    def subvolume_snapshot_visibility_get(self, **kwargs):
+        ret = 0, "", ""
+        volname = kwargs['vol_name']
+        subvolname = kwargs['sub_name']
+        groupname = kwargs['group_name']
+
+        try:
+            with open_volume(self, volname) as fs_handle:
+                with open_group(fs_handle, self.volspec, groupname) as group:
+                    with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname,
+                                     SubvolumeOpType.SNAPSHOT_VISIBILITY) as subvolume:
+                        v = subvolume.snapshot_visibility_get()
+                        ret = 0, v, ""
+        except VolumeException as ve:
+            ret = self.volume_exception_to_retval(ve)
+        return ret
index 55a8efd36c2054ae89ef762c4f045af40a1b6adc..03d582b4440fc263eeef0cd6cdf85fe3fceb8313 100644 (file)
@@ -602,6 +602,23 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
             'desc': "Cancel an pending or ongoing clone operation.",
             'perm': 'r'
         },
+        {
+            'cmd': 'fs subvolume snapshot_visibility set'
+                   ' name=vol_name,type=CephString'
+                   ' name=sub_name,type=CephString'
+                   ' name=value,type=CephString,req=true'
+                   ' name=group_name,type=CephString,req=false',
+            'desc': "Set snapdir visibility for subvolume",
+            'perm': 'rw'
+        },
+        {
+            'cmd': 'fs subvolume snapshot_visibility get'
+                   ' name=vol_name,type=CephString'
+                   ' name=sub_name,type=CephString'
+                   ' name=group_name,type=CephString,req=false',
+            'desc': "Get snapdir visibility for subvolume",
+            'perm': 'rw'
+        },
         # volume ls [recursive]
         # subvolume ls <volume>
         # volume authorize/deauthorize
@@ -1143,3 +1160,16 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
         return self.vc.subvolume_info(vol_name=vol_name,
                                       sub_name=subvol,
                                       group_name=group_name)
+
+    @mgr_cmd_wrap
+    def _cmd_fs_subvolume_snapshot_visibility_set(self, inbuf, cmd):
+        return self.vc.subvolume_snapshot_visibility_set(vol_name=cmd['vol_name'],
+                                                        sub_name=cmd['sub_name'],
+                                                        value=cmd['value'],
+                                                        group_name=cmd.get('group_name', None))
+
+    @mgr_cmd_wrap
+    def _cmd_fs_subvolume_snapshot_visibility_get(self, inbuf, cmd):
+        return self.vc.subvolume_snapshot_visibility_get(vol_name=cmd['vol_name'],
+                                                        sub_name=cmd['sub_name'],
+                                                        group_name=cmd.get('group_name', None))