From: Mykola Golub Date: Fri, 8 Dec 2017 18:22:37 +0000 (+0200) Subject: pybind/rbd: add deep_copy method X-Git-Tag: v13.0.2~778^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F19406%2Fhead;p=ceph.git pybind/rbd: add deep_copy method Signed-off-by: Mykola Golub --- diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 7c6de819ae05..abc9a2ed2a1b 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -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. diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index bd4005e05474..43e723c99da8 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -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')