pybind/rbd: add deep_copy method

Signed-off-by: Mykola Golub <to.my.trociny@gmail.com>
This commit is contained in:
Mykola Golub 2017-12-08 20:22:37 +02:00
parent f10904b617
commit 65b92c40ac
2 changed files with 79 additions and 0 deletions

View 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.

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