From 854e9452e8b85af96e206dd209a004ff92f9848d Mon Sep 17 00:00:00 2001 From: Ramana Raja Date: Tue, 6 Aug 2024 14:20:14 -0400 Subject: [PATCH] pybind/rbd: add interfaces to fetch and list mirror group info Signed-off-by: Ramana Raja --- src/pybind/rbd/c_rbd.pxd | 26 ++++++++ src/pybind/rbd/rbd.pyx | 128 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/src/pybind/rbd/c_rbd.pxd b/src/pybind/rbd/c_rbd.pxd index 80bc1f0e506a0..322b279d561cd 100644 --- a/src/pybind/rbd/c_rbd.pxd +++ b/src/pybind/rbd/c_rbd.pxd @@ -194,6 +194,18 @@ cdef extern from "rbd/librbd.h" nogil: uint32_t site_statuses_count rbd_mirror_image_site_status_t *site_statuses + ctypedef enum rbd_mirror_group_state_t: + _RBD_MIRROR_GROUP_DISABLING "RBD_MIRROR_GROUP_DISABLING" + _RBD_MIRROR_GROUP_ENABLING "RBD_MIRROR_GROUP_ENABLING" + _RBD_MIRROR_GROUP_ENABLED "RBD_MIRROR_GROUP_ENABLED" + _RBD_MIRROR_GROUP_DISABLED "RBD_MIRROR_GROUP_DISABLED" + + ctypedef struct rbd_mirror_group_info_t: + char *global_id + rbd_mirror_image_mode_t mirror_image_mode + rbd_mirror_group_state_t state + bint primary + ctypedef enum rbd_lock_mode_t: _RBD_LOCK_MODE_EXCLUSIVE "RBD_LOCK_MODE_EXCLUSIVE" _RBD_LOCK_MODE_SHARED "RBD_LOCK_MODE_SHARED" @@ -466,6 +478,20 @@ cdef extern from "rbd/librbd.h" nogil: void rbd_mirror_image_info_list_cleanup(char **image_ids, rbd_mirror_image_info_t *info_entries, size_t num_entries) + 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) + void rbd_mirror_group_get_info_cleanup( + rbd_mirror_group_info_t *mirror_gp_info) + int rbd_mirror_group_info_list(rados_ioctx_t gp_ioctx, + rbd_mirror_image_mode_t *mode_filter, + const char *start_id, size_t max, + char **group_ids, + rbd_mirror_group_info_t *info_entries, + size_t *num_entries); + void rbd_mirror_group_info_list_cleanup( + char **group_ids, rbd_mirror_group_info_t *info_entries, + size_t num_entries); int rbd_pool_metadata_get(rados_ioctx_t io_ctx, const char *key, char *value, size_t *val_len) diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 127f29b9b71b5..67302a170f3e5 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -21,7 +21,7 @@ import sys from cpython cimport PyObject, ref, exc from libc cimport errno from libc.stdint cimport * -from libc.stdlib cimport malloc, realloc, free +from libc.stdlib cimport calloc, malloc, realloc, free from libc.string cimport strdup, memset cimport libcpp @@ -100,6 +100,11 @@ RBD_MIRROR_IMAGE_ENABLED = _RBD_MIRROR_IMAGE_ENABLED RBD_MIRROR_IMAGE_DISABLED = _RBD_MIRROR_IMAGE_DISABLED RBD_MIRROR_IMAGE_CREATING = _RBD_MIRROR_IMAGE_CREATING +RBD_MIRROR_GROUP_DISABLING = _RBD_MIRROR_GROUP_DISABLING +RBD_MIRROR_GROUP_ENABLING = _RBD_MIRROR_GROUP_ENABLING +RBD_MIRROR_GROUP_ENABLED = _RBD_MIRROR_GROUP_ENABLED +RBD_MIRROR_GROUP_DISABLED = _RBD_MIRROR_GROUP_DISABLED + MIRROR_IMAGE_STATUS_STATE_UNKNOWN = _MIRROR_IMAGE_STATUS_STATE_UNKNOWN MIRROR_IMAGE_STATUS_STATE_ERROR = _MIRROR_IMAGE_STATUS_STATE_ERROR MIRROR_IMAGE_STATUS_STATE_SYNCING = _MIRROR_IMAGE_STATUS_STATE_SYNCING @@ -1702,6 +1707,17 @@ class RBD(object): """ return MirrorImageInfoIterator(ioctx, mode_filter) + def mirror_group_info_list(self, ioctx, mode_filter=None): + """ + Iterate over the mirror group ids of a pool. + + :param ioctx: determines which RADOS pool is read + :param mode_filter: list groups in this group mirror mode + :type ioctx: :class:`rados.Ioctx` + :returns: :class:`MirrorGroupInfoIterator` + """ + return MirrorGroupInfoIterator(ioctx, mode_filter) + def pool_metadata_get(self, ioctx, key): """ Get pool metadata for the given key. @@ -2958,6 +2974,37 @@ cdef class Group(object): if ret != 0: raise make_ex(ret, 'error rolling back group to snapshot', group_errno_to_exception) + def mirror_group_get_info(self): + """ + Get mirror info of the group. + + :returns: dict - contains the following keys: + + * ``global_id`` (str) - group global id + + * ``mode`` (int) - mirror mode + + * ``state`` (int) - mirror state + + * ``primary`` (bool) - is group primary + """ + cdef rbd_mirror_group_info_t c_info + with nogil: + ret = rbd_mirror_group_get_info(self._ioctx, self._name, &c_info, + sizeof(c_info)) + if ret != 0: + raise make_ex(ret, + 'error getting mirror info of group %s' % self._name, + group_errno_to_exception) + info = { + 'global_id' : decode_cstr(c_info.global_id), + 'image_mode' : int(c_info.mirror_image_mode), + 'state' : int(c_info.state), + 'primary' : c_info.primary, + } + rbd_mirror_group_get_info_cleanup(&c_info) + return info + def requires_not_closed(f): def wrapper(self, *args, **kwargs): self.require_not_closed() @@ -6168,3 +6215,82 @@ cdef class GroupSnapIterator(object): rbd_group_snap_list2_cleanup(self.group_snaps, self.num_group_snaps) free(self.group_snaps) + +cdef class MirrorGroupInfoIterator(object): + """ + Iterator over mirror group info in a pool. + + Yields ``(group_id, info)`` tuple. + """ + + cdef: + rados_ioctx_t ioctx + rbd_mirror_image_mode_t mode_filter + rbd_mirror_image_mode_t *mode_filter_ptr + size_t max_read + char *last_read + char **gp_ids + rbd_mirror_group_info_t *gp_info_entries + size_t size + + def __init__(self, ioctx, mode_filter): + self.ioctx = convert_ioctx(ioctx) + if mode_filter is not None: + self.mode_filter = mode_filter + self.mode_filter_ptr = &self.mode_filter + else: + self.mode_filter_ptr = NULL + self.max_read = 1024 + self.last_read = strdup("") + self.gp_ids = calloc(sizeof(char *), self.max_read) + self.gp_info_entries = calloc( + sizeof(rbd_mirror_group_info_t), self.max_read) + self.size = 0 + + self.get_next_chunk() + + def __iter__(self): + while self.size > 0: + for i in range(self.size): + yield (decode_cstr(self.gp_ids[i]), + { + 'global_id' : decode_cstr(self.gp_info_entries[i].global_id), + 'mode' : int(self.gp_info_entries[i].mirror_image_mode), + 'state' : int(self.gp_info_entries[i].state), + 'primary' : self.gp_info_entries[i].primary, + }) + if self.size < self.max_read: + break + self.get_next_chunk() + + def __dealloc__(self): + rbd_mirror_group_info_list_cleanup(self.gp_ids, self.gp_info_entries, + self.size) + if self.last_read: + free(self.last_read) + if self.gp_ids: + free(self.gp_ids) + if self.gp_info_entries: + free(self.gp_info_entries) + + def get_next_chunk(self): + if self.size > 0: + rbd_mirror_group_info_list_cleanup(self.gp_ids, + self.gp_info_entries, self.size) + self.size = 0 + + with nogil: + ret = rbd_mirror_group_info_list(self.ioctx, self.mode_filter_ptr, + self.last_read, self.max_read, + self.gp_ids, self.gp_info_entries, + &self.size) + if ret < 0: + raise make_ex(ret, 'error listing mirror group info', + group_errno_to_exception) + + free(self.last_read) + if self.size > 0: + last_read = cstr(self.gp_ids[self.size - 1], 'last_read') + self.last_read = strdup(last_read) + else: + self.last_read = strdup("") -- 2.39.5