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)
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.
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')