]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind: Add support for rbd_watchers_list 19188/head
authorAdam Wolfe Gordon <awg@digitalocean.com>
Tue, 28 Nov 2017 20:37:57 +0000 (20:37 +0000)
committerAdam Wolfe Gordon <awg@digitalocean.com>
Tue, 28 Nov 2017 21:17:38 +0000 (21:17 +0000)
Also add a test.

Signed-off-by: Adam Wolfe Gordon <awg@digitalocean.com>
src/pybind/rbd/rbd.pyx
src/test/pybind/test_rbd.py

index 949504a34d2bcfa8ff57f100dfeae28379215980..37b1c7d963e3a9d29267c9cfdf8ba709d8927612 100644 (file)
@@ -154,6 +154,11 @@ cdef extern from "rbd/librbd.h" nogil:
         time_t deletion_time
         time_t deferment_end_time
 
+    ctypedef struct rbd_image_watcher_t:
+        char *addr
+        int64_t id
+        uint64_t cookie
+
     ctypedef void (*rbd_callback_t)(rbd_completion_t cb, void *arg)
     ctypedef int (*librbd_progress_fn_t)(uint64_t offset, uint64_t total, void* ptr)
 
@@ -349,6 +354,11 @@ cdef extern from "rbd/librbd.h" nogil:
                           char *keys, size_t *key_len, char *values,
                           size_t *vals_len)
 
+    int rbd_watchers_list(rbd_image_t image, rbd_image_watcher_t *watchers,
+                          size_t *max_watchers)
+    void rbd_watchers_list_cleanup(rbd_image_watcher_t *watchers,
+                                   size_t num_watchers)
+
 RBD_FEATURE_LAYERING = _RBD_FEATURE_LAYERING
 RBD_FEATURE_STRIPINGV2 = _RBD_FEATURE_STRIPINGV2
 RBD_FEATURE_EXCLUSIVE_LOCK = _RBD_FEATURE_EXCLUSIVE_LOCK
@@ -2755,6 +2765,16 @@ written." % (self.name, ret, length))
         """
         return MetadataIterator(self)
 
+
+    def watchers_list(self):
+        """
+        List image watchers.
+
+        :returns: :class:`WatcherIterator`
+        """
+        return WatcherIterator(self)
+
+
 cdef class LockOwnerIterator(object):
     """
     Iterator over managed lock owners for an image
@@ -3026,3 +3046,50 @@ cdef class ChildIterator(object):
         if self.children:
             rbd_list_children_cleanup(self.children, self.num_children)
             free(self.children)
+
+cdef class WatcherIterator(object):
+    """
+    Iterator over watchers of an image.
+
+    Yields a dictionary containing information about a watcher.
+
+    Keys are:
+
+    * ``addr`` (str) - address of the watcher
+
+    * ``id`` (int) - id of the watcher
+
+    * ``cookie`` (int) - the watcher's cookie
+    """
+
+    cdef rbd_image_watcher_t *watchers
+    cdef size_t num_watchers
+    cdef object image
+
+    def __init__(self, Image image):
+        self.image = image
+        self.watchers = NULL
+        self.num_watchers = 10
+        while True:
+            self.watchers = <rbd_image_watcher_t*>realloc_chk(self.watchers,
+                                                              self.num_watchers *
+                                                              sizeof(rbd_image_watcher_t))
+            with nogil:
+                ret = rbd_watchers_list(image.image, self.watchers, &self.num_watchers)
+            if ret >= 0:
+                break
+            elif ret != -errno.ERANGE:
+                raise make_ex(ret, 'error listing watchers.')
+
+    def __iter__(self):
+        for i in range(self.num_watchers):
+            yield {
+                'addr'   : decode_cstr(self.watchers[i].addr),
+                'id'     : self.watchers[i].id,
+                'cookie' : self.watchers[i].cookie
+                }
+
+    def __dealloc__(self):
+        if self.watchers:
+            rbd_watchers_list_cleanup(self.watchers, self.num_watchers)
+            free(self.watchers)
index f46f09cedcf9f1ef11738ed066d98049c8ca66b6..b5a7ce3ec8d015523ee6e595edcd2d19bcd54509 100644 (file)
@@ -854,6 +854,12 @@ class TestImage(object):
             metadata = list(self.image.metadata_list())
             eq(len(metadata), N - i - 1)
 
+    def test_watchers_list(self):
+        watchers = list(self.image.watchers_list())
+        # The image is open (in r/w mode) from setup, so expect there to be one
+        # watcher.
+        eq(len(watchers), 1)
+
 def check_diff(image, offset, length, from_snapshot, expected):
     extents = []
     def cb(offset, length, exists):