]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/rbd: add deep_copy method 19406/head
authorMykola Golub <to.my.trociny@gmail.com>
Fri, 8 Dec 2017 18:22:37 +0000 (20:22 +0200)
committerMykola Golub <to.my.trociny@gmail.com>
Mon, 11 Dec 2017 16:09:10 +0000 (18:09 +0200)
Signed-off-by: Mykola Golub <to.my.trociny@gmail.com>
src/pybind/rbd/rbd.pyx
src/test/pybind/test_rbd.py

index 7c6de819ae05d90344420c2d91e7d6611facda4c..abc9a2ed2a1b8e5ef85e3579c6db34af9e6af32b 100644 (file)
@@ -257,6 +257,8 @@ cdef extern from "rbd/librbd.h" nogil:
     int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len)
     int rbd_copy3(rbd_image_t src, rados_ioctx_t dest_io_ctx,
                   const char *destname, rbd_image_options_t dest_opts)
+    int rbd_deep_copy(rbd_image_t src, rados_ioctx_t dest_io_ctx,
+                      const char *destname, rbd_image_options_t dest_opts)
     int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
                       int *max_snaps)
     void rbd_snap_list_end(rbd_snap_info_t *snaps)
@@ -1787,6 +1789,61 @@ cdef class Image(object):
         if ret < 0:
             raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
 
+    def deep_copy(self, dest_ioctx, dest_name, features=None, order=None,
+                  stripe_unit=None, stripe_count=None, data_pool=None):
+        """
+        Deep copy the image to another location.
+
+        :param dest_ioctx: determines which pool to copy into
+        :type dest_ioctx: :class:`rados.Ioctx`
+        :param dest_name: the name of the copy
+        :type dest_name: str
+        :param features: bitmask of features to enable; if set, must include layering
+        :type features: int
+        :param order: the image is split into (2**order) byte objects
+        :type order: int
+        :param stripe_unit: stripe unit in bytes (default None to let librbd decide)
+        :type stripe_unit: int
+        :param stripe_count: objects to stripe over before looping
+        :type stripe_count: int
+        :param data_pool: optional separate pool for data blocks
+        :type data_pool: str
+        :raises: :class:`TypeError`
+        :raises: :class:`InvalidArgument`
+        :raises: :class:`ImageExists`
+        :raises: :class:`FunctionNotSupported`
+        :raises: :class:`ArgumentOutOfRange`
+        """
+        dest_name = cstr(dest_name, 'dest_name')
+        cdef:
+            rados_ioctx_t _dest_ioctx = convert_ioctx(dest_ioctx)
+            char *_dest_name = dest_name
+            rbd_image_options_t opts
+
+        rbd_image_options_create(&opts)
+        try:
+            if features is not None:
+                rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_FEATURES,
+                                             features)
+            if order is not None:
+                rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_ORDER,
+                                             order)
+            if stripe_unit is not None:
+                rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_UNIT,
+                                             stripe_unit)
+            if stripe_count is not None:
+                rbd_image_options_set_uint64(opts, RBD_IMAGE_OPTION_STRIPE_COUNT,
+                                             stripe_count)
+            if data_pool is not None:
+                rbd_image_options_set_string(opts, RBD_IMAGE_OPTION_DATA_POOL,
+                                             data_pool)
+            with nogil:
+                ret = rbd_deep_copy(self.image, _dest_ioctx, _dest_name, opts)
+        finally:
+            rbd_image_options_destroy(opts)
+        if ret < 0:
+            raise make_ex(ret, 'error copying image %s to %s' % (self.name, dest_name))
+
     def list_snaps(self):
         """
         Iterate over the snapshots of an image.
index bd4005e054740b9de49cf7726fe67aac7ed4fd23..43e723c99da8c61086b7ba622d8abeb204c064e9 100644 (file)
@@ -473,6 +473,28 @@ class TestImage(object):
         self._test_copy(features, self.image.stat()['order'],
                         self.image.stripe_unit(), self.image.stripe_count())
 
+    def test_deep_copy(self):
+        global ioctx
+        global features
+        self.image.write(b'a' * 256, 0)
+        self.image.create_snap('snap1')
+        self.image.write(b'b' * 256, 0)
+        dst_name = get_temp_image_name()
+        self.image.deep_copy(ioctx, dst_name, features=features,
+                             order=self.image.stat()['order'],
+                             stripe_unit=self.image.stripe_unit(),
+                             stripe_count=self.image.stripe_count(),
+                             data_pool=None)
+        self.image.remove_snap('snap1')
+        with Image(ioctx, dst_name, 'snap1') as copy:
+            copy_data = copy.read(0, 256)
+            eq(b'a' * 256, copy_data)
+        with Image(ioctx, dst_name) as copy:
+            copy_data = copy.read(0, 256)
+            eq(b'b' * 256, copy_data)
+            copy.remove_snap('snap1')
+        self.rbd.remove(ioctx, dst_name)
+
     def test_create_snap(self):
         global ioctx
         self.image.create_snap('snap1')