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_aio_open(rados_ioctx_t io, const char *name, rbd_image_t *image,
+ const char *snap_name, rbd_completion_t c)
+ int rbd_aio_open_by_id(rados_ioctx_t io, const char *id, rbd_image_t *image,
+ const char *snap_name, rbd_completion_t c)
+ int rbd_aio_open_read_only(rados_ioctx_t io, const char *name,
+ rbd_image_t *image, const char *snap_name,
+ rbd_completion_t c)
+ int rbd_aio_open_by_id_read_only(rados_ioctx_t io, const char *id,
+ rbd_image_t *image, const char *snap_name,
+ rbd_completion_t c)
int rbd_features_to_string(uint64_t features, char *str_features, size_t *size)
int rbd_features_from_string(const char *str_features, uint64_t *features)
int rbd_close(rbd_image_t image)
+ int rbd_aio_close(rbd_image_t image, rbd_completion_t c)
int rbd_resize2(rbd_image_t image, uint64_t size, bint allow_shrink,
librbd_progress_fn_t cb, void *cbdata)
int rbd_stat(rbd_image_t image, rbd_image_info_t *info, size_t infosize)
raise make_ex(ret, 'error getting features bitmask from str')
return features
+ def aio_open_image(self, oncomplete, ioctx, name=None, snapshot=None,
+ read_only=False, image_id=None):
+ """
+ Asynchronously open the image at the given snapshot.
+ Specify either name or id, otherwise :class:`InvalidArgument` is raised.
+
+ oncomplete will be called with the created Image object as
+ well as the completion:
+
+ oncomplete(completion, image)
+
+ If a snapshot is specified, the image will be read-only, unless
+ :func:`Image.set_snap` is called later.
+
+ If read-only mode is used, metadata for the :class:`Image`
+ object (such as which snapshots exist) may become obsolete. See
+ the C api for more details.
+
+ To clean up from opening the image, :func:`Image.close` or
+ :func:`Image.aio_close` should be called.
+
+ :param oncomplete: what to do when open is complete
+ :type oncomplete: completion
+ :param ioctx: determines which RADOS pool the image is in
+ :type ioctx: :class:`rados.Ioctx`
+ :param name: the name of the image
+ :type name: str
+ :param snapshot: which snapshot to read from
+ :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
+ :returns: :class:`Completion` - the completion object
+ """
+
+ image = Image(ioctx, name, snapshot, read_only, image_id, oncomplete)
+ comp, image._open_completion = image._open_completion, None
+ return comp
cdef class MirrorPeerIterator(object):
"""
cdef object name
cdef object ioctx
cdef rados_ioctx_t _ioctx
+ cdef Completion _open_completion
def __init__(self, ioctx, name=None, snapshot=None,
- read_only=False, image_id=None):
+ read_only=False, image_id=None, _oncomplete=None):
"""
Open the image at the given snapshot.
Specify either name or id, otherwise :class:`InvalidArgument` is raised.
char *_name = opt_str(name)
char *_image_id = opt_str(image_id)
char *_snapshot = opt_str(snapshot)
+ cdef Completion completion
+
+ if _oncomplete:
+ def oncomplete(completion_v):
+ cdef Completion _completion_v = completion_v
+ return_value = _completion_v.get_return_value()
+ if return_value == 0:
+ self.closed = False
+ if name is None:
+ self.name = self.get_name()
+ return _oncomplete(_completion_v, self)
+
+ completion = self.__get_completion(oncomplete)
+ try:
+ completion.__persist()
+ if read_only:
+ with nogil:
+ if name is not None:
+ ret = rbd_aio_open_read_only(
+ _ioctx, _name, &self.image, _snapshot,
+ completion.rbd_comp)
+ else:
+ ret = rbd_aio_open_by_id_read_only(
+ _ioctx, _image_id, &self.image, _snapshot,
+ completion.rbd_comp)
+ else:
+ with nogil:
+ if name is not None:
+ ret = rbd_aio_open(
+ _ioctx, _name, &self.image, _snapshot,
+ completion.rbd_comp)
+ else:
+ ret = rbd_aio_open_by_id(
+ _ioctx, _image_id, &self.image, _snapshot,
+ completion.rbd_comp)
+ if ret != 0:
+ raise make_ex(ret, 'error opening image %s at snapshot %s' %
+ (self.name, snapshot))
+ except:
+ completion.__unpersist()
+ raise
+
+ self._open_completion = completion
+ return
+
if read_only:
with nogil:
if name is not None:
raise make_ex(ret, 'error while closing image %s' % (
self.name,))
+ @requires_not_closed
+ def aio_close(self, oncomplete):
+ """
+ Asynchronously close the image.
+
+ After this is called, this object should not be used.
+
+ :param oncomplete: what to do when close is complete
+ :type oncomplete: completion
+ :returns: :class:`Completion` - the completion object
+ """
+ cdef Completion completion = self.__get_completion(oncomplete)
+ self.closed = True
+ try:
+ completion.__persist()
+ with nogil:
+ ret = rbd_aio_close(self.image, completion.rbd_comp)
+ if ret < 0:
+ raise make_ex(ret, 'error while closing image %s' %
+ self.name)
+ except:
+ completion.__unpersist()
+ raise
+ return completion
+
def __dealloc__(self):
self.close()
eq(image.get_name(), image_name)
RBD().remove(ioctx, image_name)
+def test_aio_open():
+ with Rados(conffile='') as cluster:
+ with cluster.open_ioctx(pool_name) as ioctx:
+ image_name = get_temp_image_name()
+ order = 20
+ RBD().create(ioctx, image_name, IMG_SIZE, order)
+
+ # this is a list so that the open_cb() can modify it
+ image = [None]
+ def open_cb(_, image_):
+ image[0] = image_
+
+ comp = RBD().aio_open_image(open_cb, ioctx, image_name)
+ comp.wait_for_complete_and_cb()
+ eq(comp.get_return_value(), 0)
+ eq(sys.getrefcount(comp), 2)
+ assert_not_equal(image[0], None)
+
+ image = image[0]
+ eq(image.get_name(), image_name)
+ check_stat(image.stat(), IMG_SIZE, order)
+
+ closed = [False]
+ def close_cb(_):
+ closed[0] = True
+
+ comp = image.aio_close(close_cb)
+ comp.wait_for_complete_and_cb()
+ eq(comp.get_return_value(), 0)
+ eq(sys.getrefcount(comp), 2)
+ eq(closed[0], True)
+
+ RBD().remove(ioctx, image_name)
+
def test_remove_dne():
assert_raises(ImageNotFound, remove_image)