]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/volumes: allow --force to delete snapshots even when UUID dir is missing
authorRishabh Dave <ridave@redhat.com>
Tue, 9 Sep 2025 11:04:18 +0000 (16:34 +0530)
committerVenky Shankar <vshankar@redhat.com>
Thu, 19 Feb 2026 06:18:47 +0000 (11:48 +0530)
Also, add tests for the same.

Fixes: https://tracker.ceph.com/issues/72956
Signed-off-by: Rishabh Dave <ridave@redhat.com>
qa/tasks/cephfs/test_volumes.py
src/pybind/mgr/volumes/fs/operations/template.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_v2.py
src/pybind/mgr/volumes/fs/volume.py

index 8450850609ee02feb1fe10358776e7ca87f86a43..ad7636af75e175743a7143ec6df2b4c4e8124be4 100644 (file)
@@ -10819,3 +10819,23 @@ class TestCorruptedSubvolumes(TestVolumesHelper):
                               retval=errno.ENOENT,
                               errmsgs='mount path missing for subvolume')
         self.run_ceph_cmd(f'fs subvolume rm {self.volname} {sv1} --force')
+
+    def test_rm_subvol_that_has_snap_and_missing__UUID_dir(self):
+        sv1 = 'sv1'
+        ss1 = 'ss1'
+
+        self.run_ceph_cmd(f'fs subvolume create {self.volname} {sv1}')
+        self.run_ceph_cmd(f'fs subvolume snapshot create {self.volname} {sv1} {ss1}')
+
+        sv_path = self.get_ceph_cmd_stdout('fs subvolume getpath '
+                                           f'{self.volname} {sv1}').strip()[1:]
+        self.mount_a.run_shell(f'sudo rmdir {sv_path}', omit_sudo=False)
+
+        self.negtest_ceph_cmd(f'fs subvolume snapshot rm {self.volname} {sv1} {ss1}',
+                              retval=errno.ENOENT,
+                              errmsgs='mount path missing for subvolume')
+        self.run_ceph_cmd(f'fs subvolume snapshot rm {self.volname} {sv1} {ss1} '
+                           '--force')
+
+        # cleanup
+        self.run_ceph_cmd(f'fs subvolume rm {self.volname} {sv1} --force')
index 713525c4efe6ee7c332359ecc74454f398eaf238..2189e20ce13eb5fba47b81fb736987ad6ba2cce4 100644 (file)
@@ -48,6 +48,7 @@ class SubvolumeOpType(Enum):
     RESIZE                = 'resize'
     SNAP_CREATE           = 'snap-create'
     SNAP_REMOVE           = 'snap-rm'
+    SNAP_REMOVE_FORCE     = 'snap-rm-force'
     SNAP_LIST             = 'snap-ls'
     SNAP_GETPATH          = 'snap-getpath'
     SNAP_INFO             = 'snap-info'
index 40c2270af37f5fa7f24cfe0cc4aa76e46f65461d..164448133e0f85b77349f3c242e4906f9540f57f 100644 (file)
@@ -282,6 +282,7 @@ class SubvolumeV2(SubvolumeV1):
                 SubvolumeOpType.LIST,
                 SubvolumeOpType.INFO,
                 SubvolumeOpType.SNAP_REMOVE,
+                SubvolumeOpType.SNAP_REMOVE_FORCE,
                 SubvolumeOpType.SNAP_LIST,
                 SubvolumeOpType.SNAP_GETPATH,
                 SubvolumeOpType.SNAP_INFO,
@@ -337,7 +338,7 @@ class SubvolumeV2(SubvolumeV1):
                 raise VolumeException(-errno.ENOENT, "subvolume '{0}' does not exist".format(self.subvolname))
             raise VolumeException(me.args[0], me.args[1])
         except cephfs.ObjectNotFound:
-            if op_type == SubvolumeOpType.REMOVE_FORCE:
+            if op_type in (SubvolumeOpType.REMOVE_FORCE, SubvolumeOpType.SNAP_REMOVE_FORCE):
                 log.debug("since --force is passed, ignoring missing subvolume '"
                           f"path '{subvol_path}' for subvolume "
                           f"{self.subvolname}'")
index be0625280c4633d4b8e5ab4498346342bfebeb7f..0de01aa04f89275cae81889ccc2f1cbfbe8c54a3 100644 (file)
@@ -827,7 +827,8 @@ class VolumeClient(CephfsClient["Module"]):
         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.SNAP_REMOVE) as subvolume:
+                    op = SubvolumeOpType.SNAP_REMOVE_FORCE if force else SubvolumeOpType.SNAP_REMOVE
+                    with open_subvol(self.mgr, fs_handle, self.volspec, group, subvolname, op) as subvolume:
                         subvolume.remove_snapshot(snapname, force)
         except VolumeException as ve:
             # ESTALE serves as an error to state that subvolume is currently stale due to internal removal and,