From 5e0f556aac0c42ce77b3fe03cb03c8cc6e63fd73 Mon Sep 17 00:00:00 2001 From: Ramana Raja Date: Wed, 22 Jan 2025 12:26:57 -0500 Subject: [PATCH] librbd: add C and Python bindings for async mirror group snapshot create Signed-off-by: Ramana Raja --- src/include/rbd/librbd.h | 6 ++++ src/include/rbd/librbd.hpp | 3 ++ src/librbd/librbd.cc | 60 ++++++++++++++++++++++++++++++++++++++ src/pybind/rbd/c_rbd.pxd | 5 ++++ src/pybind/rbd/rbd.pyx | 52 +++++++++++++++++++++++++++++++++ 5 files changed, 126 insertions(+) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index 525a3433a8e5b..6a0b6b49e51b2 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -1675,6 +1675,12 @@ CEPH_RBD_API int rbd_mirror_group_create_snapshot(rados_ioctx_t p, uint32_t flags, char *snap_id, size_t *max_snap_id_len); +CEPH_RBD_API int rbd_aio_mirror_group_create_snapshot(rados_ioctx_t p, + const char *name, + uint32_t flags, + char *snap_id, + size_t *max_snap_id_len, + rbd_completion_t c); CEPH_RBD_API int rbd_mirror_group_get_info( rados_ioctx_t p, const char *name, rbd_mirror_group_info_t *mirror_group_info, size_t info_size); diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 78e07e1d73452..aa5748f7d1bb0 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -586,6 +586,9 @@ public: int mirror_group_resync(IoCtx& io_ctx, const char *group_name); int mirror_group_create_snapshot(IoCtx& io_ctx, const char *group_name, uint32_t flags, std::string *snap_id); + int aio_mirror_group_create_snapshot(IoCtx& io_ctx, const char *group_name, + uint32_t flags, std::string *snap_id, + RBD::AioGroupCompletion *c); int mirror_group_get_info(IoCtx& io_ctx, const char *group_name, mirror_group_info_t *mirror_group_info, size_t info_size); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index b467b1e413b06..f7b63ffc10335 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -527,6 +527,28 @@ struct C_MirrorGroupGetInfo : public Context { } }; +struct C_MirrorGroupCreateSnapshot : public Context { + char *mirror_group_snap_id; + Context *on_finish; + + std::string cpp_mirror_group_snap_id; + + C_MirrorGroupCreateSnapshot(char *mirror_group_snap_id, + Context *on_finish) + : mirror_group_snap_id(mirror_group_snap_id), on_finish(on_finish) { + } + + void finish(int r) override { + if (r < 0) { + on_finish->complete(r); + return; + } + + strcpy(mirror_group_snap_id, cpp_mirror_group_snap_id.c_str()); + on_finish->complete(0); + } +}; + struct C_MirrorImageGetGlobalStatus : public Context { rbd_mirror_image_global_status_t *mirror_image_global_status; Context *on_finish; @@ -1742,6 +1764,18 @@ namespace librbd { flags, snap_id); } + int RBD::aio_mirror_group_create_snapshot(IoCtx& group_ioctx, + const char *group_name, + uint32_t flags, + std::string *snap_id, + RBD::AioGroupCompletion *c) { + librbd::api::Mirror<>::group_snapshot_create( + group_ioctx, group_name, flags, snap_id, + new C_AioGroupCompletion(group_ioctx, c)); + + return 0; + } + int RBD::mirror_group_get_info(IoCtx& group_ioctx, const char *group_name, mirror_group_info_t *mirror_group_info, size_t info_size) { @@ -8224,6 +8258,32 @@ extern "C" int rbd_mirror_group_create_snapshot(rados_ioctx_t group_p, return 0; } +extern "C" int rbd_aio_mirror_group_create_snapshot( + rados_ioctx_t group_p, const char *group_name, uint32_t flags, + char *snap_id, size_t *max_snap_id_len, rbd_completion_t c) { + if (*max_snap_id_len < RBD_MAX_IMAGE_ID_LENGTH + 1) { + *max_snap_id_len = RBD_MAX_IMAGE_ID_LENGTH + 1; + return -ERANGE; + } + + *max_snap_id_len = RBD_MAX_IMAGE_ID_LENGTH + 1; + + librados::IoCtx group_ioctx; + librados::IoCtx::from_rados_ioctx_t(group_p, group_ioctx); + + librbd::RBD::AioGroupCompletion *comp = (librbd::RBD::AioGroupCompletion *)c; + + auto ctx = new C_MirrorGroupCreateSnapshot( + snap_id, new C_AioGroupCompletion(group_ioctx, comp)); + + librbd::api::Mirror<>::group_snapshot_create(group_ioctx, + group_name, + flags, + &ctx->cpp_mirror_group_snap_id, + ctx); + return 0; +} + extern "C" int rbd_mirror_group_get_info( rados_ioctx_t group_p, const char *group_name, rbd_mirror_group_info_t *mirror_group_info, size_t info_size) { diff --git a/src/pybind/rbd/c_rbd.pxd b/src/pybind/rbd/c_rbd.pxd index 629870004ee07..f781ec0e3810b 100644 --- a/src/pybind/rbd/c_rbd.pxd +++ b/src/pybind/rbd/c_rbd.pxd @@ -486,6 +486,11 @@ cdef extern from "rbd/librbd.h" nogil: const char *gp_name, uint32_t flags, char *snap_id, size_t *max_snap_id_len) + int rbd_aio_mirror_group_create_snapshot(rados_ioctx_t gp_ioctx, + const char *gp_name, + uint32_t flags, char *snap_id, + size_t *max_snap_id_len, + rbd_completion_t c) int rbd_mirror_group_get_info(rados_ioctx_t gp_ioctx, const char *gp_name, rbd_mirror_group_info_t *mirror_gp_info, size_t info_size) diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 8a79ac5d6372a..d5a1ec3965666 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -3085,6 +3085,58 @@ cdef class Group(object): finally: free(snap_id) + def aio_mirror_group_create_snapshot(self, flags, oncomplete): + """ + Asynchronously create mirror group snapshot. + + Raises :class:`InvalidArgument` if the group is not in mirror + snapshot mode. + + oncomplete will be called with the created snap ID as + well as the completion: + + oncomplete(completion, snap_id) + + :param flags: create snapshot flags + :type flags: int + :param oncomplete: what to do when group snapshot creation is complete + :type oncomplete: completion + :returns: :class:`Completion` - the completion object + :raises: :class:`InvalidArgument` + """ + cdef: + size_t max_snap_id_size = RBD_MAX_SNAP_ID_SIZE + uint32_t _flags = flags + Completion completion + + def oncomplete_(completion_v): + cdef: + Completion _completion_v = completion_v + return_value = _completion_v.get_return_value() + if return_value == 0: + snap_id = decode_cstr(_completion_v.buf) + else: + snap_id = None + return oncomplete(_completion_v, snap_id) + + completion = self.__get_completion(oncomplete_) + completion.buf = PyBytes_FromStringAndSize(NULL, max_snap_id_size) + try: + completion.__persist() + with nogil: + ret = rbd_aio_mirror_group_create_snapshot( + self._ioctx, self._name, _flags, completion.buf, + &max_snap_id_size, completion.rbd_comp) + if ret < 0: + raise make_ex( + ret, + 'error creating mirror snapshot for group %s' % self.name) + except: + completion.__unpersist() + raise + + return completion + def mirror_group_get_info(self): """ Get mirror info of the group. -- 2.39.5