From 0fd6851f637ab285ece9c1ca5909fee979efe0ab Mon Sep 17 00:00:00 2001 From: Rishabh Dave Date: Fri, 9 May 2025 22:10:47 +0530 Subject: [PATCH] mgr/vol: show clone source info in "subvolume info" cmd output Include clone source information in output of "ceph fs subvolume info" command so that users can access this information conveniently. Fixes: https://tracker.ceph.com/issues/71266 Signed-off-by: Rishabh Dave (cherry picked from commit 0ef6da69d993ca58270010e0b458bad0dff29034) Conflicts: - src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py Main branch version of info() method had code to fetch value of xattr ceph.dir.normalization and ceph.dir.casesensitive. But that isn't the case in Squid branch's info() method leading to conflict. - src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py Method get_clone_failure() in main branch is located in subvolume_v1.py but in squid it is located in async_cloner.py --- src/pybind/mgr/volumes/fs/async_cloner.py | 4 -- .../fs/operations/versions/subvolume_base.py | 51 ++++++++++++++++++- .../fs/operations/versions/subvolume_v1.py | 19 ------- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/pybind/mgr/volumes/fs/async_cloner.py b/src/pybind/mgr/volumes/fs/async_cloner.py index 0ff5a6786d3..3c800816229 100644 --- a/src/pybind/mgr/volumes/fs/async_cloner.py +++ b/src/pybind/mgr/volumes/fs/async_cloner.py @@ -84,10 +84,6 @@ def set_clone_state(fs_client, volspec, volname, groupname, subvolname, state): with open_at_volume(fs_client, volspec, volname, groupname, subvolname, SubvolumeOpType.CLONE_INTERNAL) as subvolume: subvolume.state = (state, True) -def get_clone_source(clone_subvolume): - source = clone_subvolume._get_clone_source() - return (source['volume'], source.get('group', None), source['subvolume'], source['snapshot']) - def get_next_state_on_error(errnum): if errnum == -errno.EINTR: next_state = SubvolumeOpSm.transition(SubvolumeTypes.TYPE_CLONE, diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py index 3aaf78e4648..347ef1a62fa 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py @@ -415,6 +415,34 @@ class SubvolumeBase(object): except cephfs.Error as e: raise VolumeException(-e.args[0], e.args[1]) + def _get_clone_source(self): + try: + clone_source = { + 'volume' : self.metadata_mgr.get_option("source", "volume"), + 'subvolume': self.metadata_mgr.get_option("source", "subvolume"), + 'snapshot' : self.metadata_mgr.get_option("source", "snapshot"), + } + + try: + clone_source["group"] = self.metadata_mgr.get_option("source", "group") + except MetadataMgrException as me: + if me.errno == -errno.ENOENT: + pass + else: + raise + except MetadataMgrException as e: + if e.errno == -errno.ENOENT: + clone_source = {} + else: + raise VolumeException(-errno.EINVAL, + "error fetching subvolume metadata") + return clone_source + + def get_clone_source(self): + src = self._get_clone_source() + return (src['volume'], src.get('group', None), src['subvolume'], + src['snapshot']) + def info(self): subvolpath = (self.metadata_mgr.get_global_option( MetadataManager.GLOBAL_META_KEY_PATH)) @@ -452,7 +480,8 @@ class SubvolumeBase(object): except EarmarkException: earmark = '' - return {'path': subvolpath, + subvol_info = { + 'path': subvolpath, 'type': etype.value, 'uid': int(st["uid"]), 'gid': int(st["gid"]), @@ -472,6 +501,26 @@ class SubvolumeBase(object): 'state': self.state.value, 'earmark': earmark} + subvol_src_info = self._get_clone_source() + if subvol_src_info: + if subvol_src_info.get('group', None) == None: + # group name won't be saved in .meta file in case it's + # default group + subvol_src_info['group'] = '_nogroup' + subvol_info['source'] = subvol_src_info + else: + # it could be that the clone was created in previous release of Ceph + # where its source info used to be deleted after cloning finishes. + # print "N/A" for such cases. + if self.subvol_type == SubvolumeTypes.TYPE_CLONE: + subvol_info['source'] = 'N/A' + else: + # only clones can have a source subvol, therefore don't even + # print "N/A" for source info if subvolume is not a clone. + pass + + return subvol_info + def set_user_metadata(self, keyname, value): try: self.metadata_mgr.add_section(MetadataManager.USER_METADATA_SECTION) diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py index 20f67a58e7d..acf4aa3e0d3 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py @@ -650,25 +650,6 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate): log.error(msg) raise EvictionError(msg) - def _get_clone_source(self): - try: - clone_source = { - 'volume' : self.metadata_mgr.get_option("source", "volume"), - 'subvolume': self.metadata_mgr.get_option("source", "subvolume"), - 'snapshot' : self.metadata_mgr.get_option("source", "snapshot"), - } - - try: - clone_source["group"] = self.metadata_mgr.get_option("source", "group") - except MetadataMgrException as me: - if me.errno == -errno.ENOENT: - pass - else: - raise - except MetadataMgrException: - raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata") - return clone_source - def _get_clone_failure(self): clone_failure = { 'errno' : self.metadata_mgr.get_option(MetadataManager.CLONE_FAILURE_SECTION, MetadataManager.CLONE_FAILURE_META_KEY_ERRNO), -- 2.39.5