From 61075e344c18e57b7416072f66c2e335d4d89d75 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Mon, 21 Apr 2025 17:11:17 +0200 Subject: [PATCH] pybind/rbd: add ImageMemberOfGroup exception 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 --- src/pybind/rbd/rbd.pyx | 8 ++++++++ src/test/pybind/test_rbd.py | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index b1a04af95c6..92bf12dd131 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -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, diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index 11b3b8f5e78..ebbe37d5612 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -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) -- 2.39.5