]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/rbd: add interfaces to fetch and list mirror group info
authorRamana Raja <rraja@redhat.com>
Tue, 6 Aug 2024 18:20:14 +0000 (14:20 -0400)
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>
Thu, 24 Apr 2025 15:56:27 +0000 (21:26 +0530)
Signed-off-by: Ramana Raja <rraja@redhat.com>
src/pybind/rbd/c_rbd.pxd
src/pybind/rbd/rbd.pyx

index 80bc1f0e506a00a4d77d846bc8c8b87738f81d37..322b279d561cdf73111d879dabe0ebc6506d6850 100644 (file)
@@ -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)
index 127f29b9b71b50571b975d79a158189c2c291dc9..67302a170f3e5841bfece2b9a72106d86393211d 100644 (file)
@@ -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 = <char **>calloc(sizeof(char *), self.max_read)
+        self.gp_info_entries = <rbd_mirror_group_info_t *>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("")