From: Mykola Golub Date: Mon, 26 Oct 2020 11:09:28 +0000 (+0000) Subject: pybind/rbd: add async mirror image get mode and info methods X-Git-Tag: v15.2.10~36^2~3 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=b20d12dd8220e05c2989a6f37f98e2039fd73781;p=ceph.git pybind/rbd: add async mirror image get mode and info methods Signed-off-by: Mykola Golub (cherry picked from commit 13ce488d7aaf60f85429c2e4c036362d61e5f763) --- diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 466a2ff292c41..0bdfcf52adeae 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -622,8 +622,14 @@ cdef extern from "rbd/librbd.h" nogil: size_t info_size) void rbd_mirror_image_get_info_cleanup( rbd_mirror_image_info_t *mirror_image_info) + int rbd_aio_mirror_image_get_info( + rbd_image_t image, rbd_mirror_image_info_t *mirror_image_info, + size_t info_size, rbd_completion_t c) int rbd_mirror_image_get_mode(rbd_image_t image, rbd_mirror_image_mode_t *mode) + int rbd_aio_mirror_image_get_mode(rbd_image_t image, + rbd_mirror_image_mode_t *mode, + rbd_completion_t c) int rbd_mirror_image_get_global_status( rbd_image_t image, rbd_mirror_image_global_status_t *mirror_image_global_status, @@ -5040,6 +5046,53 @@ written." % (self.name, ret, length)) rbd_mirror_image_get_info_cleanup(&c_info) return info + @requires_not_closed + def aio_mirror_image_get_info(self, oncomplete): + """ + Asynchronously get mirror info for the image. + + oncomplete will be called with the returned info as + well as the completion: + + oncomplete(completion, info) + + :param oncomplete: what to do when get info is complete + :type oncomplete: completion + :returns: :class:`Completion` - the completion object + """ + cdef: + Completion completion + + def oncomplete_(completion_v): + cdef: + Completion _completion_v = completion_v + rbd_mirror_image_info_t *c_info = _completion_v.buf + info = { + 'global_id' : decode_cstr(c_info[0].global_id), + 'state' : int(c_info[0].state), + 'primary' : c_info[0].primary, + } + rbd_mirror_image_get_info_cleanup(c_info) + return oncomplete(_completion_v, info) + + completion = self.__get_completion(oncomplete_) + completion.buf = PyBytes_FromStringAndSize( + NULL, sizeof(rbd_mirror_image_info_t)) + try: + completion.__persist() + with nogil: + ret = rbd_aio_mirror_image_get_info( + self.image, completion.buf, + sizeof(rbd_mirror_image_info_t), completion.rbd_comp) + if ret != 0: + raise make_ex( + ret, 'error getting mirror info for image %s' % self.name) + except: + completion.__unpersist() + raise + + return completion + @requires_not_closed def mirror_image_get_mode(self): """ @@ -5054,6 +5107,48 @@ written." % (self.name, ret, length)) raise make_ex(ret, 'error getting mirror mode for image %s' % self.name) return int(c_mode) + @requires_not_closed + def aio_mirror_image_get_mode(self, oncomplete): + """ + Asynchronously get mirror mode for the image. + + oncomplete will be called with the returned mode as + well as the completion: + + oncomplete(completion, mode) + + :param oncomplete: what to do when get info is complete + :type oncomplete: completion + :returns: :class:`Completion` - the completion object + """ + cdef: + Completion completion + + def oncomplete_(completion_v): + cdef Completion _completion_v = completion_v + return_value = _completion_v.get_return_value() + mode = int((_completion_v.buf)[0]) \ + if return_value >= 0 else None + return oncomplete(_completion_v, mode) + + completion = self.__get_completion(oncomplete_) + completion.buf = PyBytes_FromStringAndSize( + NULL, sizeof(rbd_mirror_image_mode_t)) + try: + completion.__persist() + with nogil: + ret = rbd_aio_mirror_image_get_mode( + self.image, completion.buf, + completion.rbd_comp) + if ret != 0: + raise make_ex( + ret, 'error getting mirror mode for image %s' % self.name) + except: + completion.__unpersist() + raise + + return completion + @requires_not_closed def mirror_image_get_status(self): """ diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index 7242e6646dd5a..03ecdde691c58 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -2208,6 +2208,29 @@ class TestMirroring(object): eq(RBD_SNAP_MIRROR_STATE_PRIMARY, snap['mirror']['state']) # this is a list so that the local cb() can modify it + info = [None] + def cb(_, _info): + info[0] = _info + + comp = self.image.aio_mirror_image_get_info(cb) + comp.wait_for_complete_and_cb() + assert_not_equal(info[0], None) + eq(comp.get_return_value(), 0) + eq(sys.getrefcount(comp), 2) + info = info[0] + global_id = info['global_id'] + self.check_info(info, global_id, RBD_MIRROR_IMAGE_ENABLED, True) + + mode = [None] + def cb(_, _mode): + mode[0] = _mode + + comp = self.image.aio_mirror_image_get_mode(cb) + comp.wait_for_complete_and_cb() + eq(comp.get_return_value(), 0) + eq(sys.getrefcount(comp), 2) + eq(mode[0], RBD_MIRROR_IMAGE_MODE_SNAPSHOT) + snap_id = [None] def cb(_, _snap_id): snap_id[0] = _snap_id