pybind/rbd: support open the image by image_id

We can initialize an image with image name or image id.

Signed-off-by: songweibin <song.weibin@zte.com.cn>
This commit is contained in:
songweibin 2017-12-06 16:51:49 +08:00
parent f3b2eb9d2d
commit 9eff61bf52
2 changed files with 60 additions and 7 deletions

View File

@ -227,8 +227,12 @@ cdef extern from "rbd/librbd.h" nogil:
int rbd_open(rados_ioctx_t io, const char *name,
rbd_image_t *image, const char *snap_name)
int rbd_open_by_id(rados_ioctx_t io, const char *image_id,
rbd_image_t *image, const char *snap_name)
int rbd_open_read_only(rados_ioctx_t io, const char *name,
rbd_image_t *image, const char *snap_name)
int rbd_open_by_id_read_only(rados_ioctx_t io, const char *image_id,
rbd_image_t *image, const char *snap_name)
int rbd_close(rbd_image_t image)
int rbd_resize(rbd_image_t image, uint64_t size)
int rbd_stat(rbd_image_t image, rbd_image_info_t *info, size_t infosize)
@ -1370,9 +1374,12 @@ cdef class Image(object):
cdef object ioctx
cdef rados_ioctx_t _ioctx
def __init__(self, ioctx, name, snapshot=None, read_only=False):
def __init__(self, ioctx, name=None, snapshot=None,
read_only=False, image_id=None):
"""
Open the image at the given snapshot.
Specify either name or id, otherwise :class:`InvalidArgument` is raised.
If a snapshot is specified, the image will be read-only, unless
:func:`Image.set_snap` is called later.
@ -1392,25 +1399,42 @@ cdef class Image(object):
:type snaphshot: str
:param read_only: whether to open the image in read-only mode
:type read_only: bool
:param image_id: the id of the image
:type image_id: str
"""
name = cstr(name, 'name')
name = cstr(name, 'name', opt=True)
image_id = cstr(image_id, 'image_id', opt=True)
snapshot = cstr(snapshot, 'snapshot', opt=True)
self.closed = True
self.name = name
if name is not None and image_id is not None:
raise InvalidArgument("only need to specify image name or image id")
elif name is None and image_id is None:
raise InvalidArgument("image name or image id was not specified")
elif name is not None:
self.name = name
else:
self.name = image_id
# Keep around a reference to the ioctx, so it won't get deleted
self.ioctx = ioctx
cdef:
rados_ioctx_t _ioctx = convert_ioctx(ioctx)
char *_name = name
char *_name = opt_str(name)
char *_image_id = opt_str(image_id)
char *_snapshot = opt_str(snapshot)
if read_only:
with nogil:
ret = rbd_open_read_only(_ioctx, _name, &self.image, _snapshot)
if name is not None:
ret = rbd_open_read_only(_ioctx, _name, &self.image, _snapshot)
else:
ret = rbd_open_by_id_read_only(_ioctx, _image_id, &self.image, _snapshot)
else:
with nogil:
ret = rbd_open(_ioctx, _name, &self.image, _snapshot)
if name is not None:
ret = rbd_open(_ioctx, _name, &self.image, _snapshot)
else:
ret = rbd_open_by_id(_ioctx, _image_id, &self.image, _snapshot)
if ret != 0:
raise make_ex(ret, 'error opening image %s at snapshot %s' % (name, snapshot))
raise make_ex(ret, 'error opening image %s at snapshot %s' % (self.name, snapshot))
self.closed = False
def __enter__(self):

View File

@ -862,6 +862,35 @@ class TestImage(object):
# watcher.
eq(len(watchers), 1)
class TestImageId(object):
def setUp(self):
self.rbd = RBD()
create_image()
self.image = Image(ioctx, image_name)
self.image2 = Image(ioctx, None, None, False, self.image.id())
def tearDown(self):
self.image.close()
self.image2.close()
remove_image()
self.image = None
self.image2 = None
def test_read(self):
data = self.image2.read(0, 20)
eq(data, b'\0' * 20)
def test_write(self):
data = rand_data(256)
self.image2.write(data, 0)
def test_resize(self):
new_size = IMG_SIZE * 2
self.image2.resize(new_size)
info = self.image2.stat()
check_stat(info, new_size, IMG_ORDER)
def check_diff(image, offset, length, from_snapshot, expected):
extents = []
def cb(offset, length, exists):