]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/rbd: add ImageMemberOfGroup exception
authorIlya Dryomov <idryomov@gmail.com>
Mon, 21 Apr 2025 15:11:17 +0000 (17:11 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 22 Apr 2025 18:25:45 +0000 (20:25 +0200)
EMLINK is returned by rbd_remove() if the image is a member of a group.
Add a dedicated exception similar to ImageBusy or ImageHasSnapshots and
a test for it.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
src/pybind/rbd/rbd.pyx
src/test/pybind/test_rbd.py

index b1a04af95c650a8236e788a90f1903190f49c31a..92bf12dd131984d0a93c15526640d8d0112391f3 100644 (file)
@@ -270,6 +270,12 @@ class ImageHasSnapshots(OSError):
                 "RBD image has snapshots (%s)" % message, errno)
 
 
+class ImageMemberOfGroup(OSError):
+    def __init__(self, message, errno=None):
+        super(ImageMemberOfGroup, self).__init__(
+                "RBD image is member of group (%s)" % message, errno)
+
+
 class FunctionNotSupported(OSError):
     def __init__(self, message, errno=None):
         super(FunctionNotSupported, self).__init__(
@@ -319,6 +325,7 @@ cdef errno_to_exception = {
     errno.EROFS      : ReadOnlyImage,
     errno.EBUSY      : ImageBusy,
     errno.ENOTEMPTY  : ImageHasSnapshots,
+    errno.EMLINK     : ImageMemberOfGroup,
     errno.ENOSYS     : FunctionNotSupported,
     errno.EDOM       : ArgumentOutOfRange,
     errno.ESHUTDOWN  : ConnectionShutdown,
@@ -338,6 +345,7 @@ cdef group_errno_to_exception = {
     errno.EROFS      : ReadOnlyImage,
     errno.EBUSY      : ImageBusy,
     errno.ENOTEMPTY  : ImageHasSnapshots,
+    errno.EMLINK     : ImageMemberOfGroup,
     errno.ENOSYS     : FunctionNotSupported,
     errno.EDOM       : ArgumentOutOfRange,
     errno.ESHUTDOWN  : ConnectionShutdown,
index 11b3b8f5e78738b49273aaeb0c35e607d063cf4e..ebbe37d5612cd19b0bcb17e7a3792c09947702f1 100644 (file)
@@ -21,7 +21,7 @@ from rados import (Rados,
                    LIBRADOS_OP_FLAG_FADVISE_RANDOM)
 from rbd import (RBD, Group, Image, ImageNotFound, InvalidArgument, ImageExists,
                  ImageBusy, ImageHasSnapshots, ReadOnlyImage, ObjectNotFound,
-                 FunctionNotSupported, ArgumentOutOfRange,
+                 FunctionNotSupported, ArgumentOutOfRange, ImageMemberOfGroup,
                  ECANCELED, OperationCanceled,
                  DiskQuotaExceeded, ConnectionShutdown, PermissionError,
                  RBD_FEATURE_LAYERING, RBD_FEATURE_STRIPINGV2,
@@ -3077,6 +3077,15 @@ class TestGroups(object):
         eq([], list(self.group.list_images()))
         RBD().trash_restore(ioctx, image_id, image_name)
 
+    def test_group_image_list_remove(self):
+        # need a closed image to get ImageMemberOfGroup instead of ImageBusy
+        self.image_names.append(create_image())
+        eq([], list(self.group.list_images()))
+        self.group.add_image(ioctx, image_name)
+        eq([image_name], [img['name'] for img in self.group.list_images()])
+        assert_raises(ImageMemberOfGroup, RBD().remove, ioctx, image_name)
+        eq([image_name], [img['name'] for img in self.group.list_images()])
+
     def test_group_get_id(self):
         id = self.group.id()
         assert isinstance(id, str)