uint8_t enabled)
int rbd_get_stripe_unit(rbd_image_t image, uint64_t *stripe_unit)
int rbd_get_stripe_count(rbd_image_t image, uint64_t *stripe_count)
+ int rbd_get_create_timestamp(rbd_image_t image, timespec *timestamp)
int rbd_get_overlap(rbd_image_t image, uint64_t *overlap)
int rbd_get_id(rbd_image_t image, char *id, size_t id_len)
int rbd_get_block_name_prefix(rbd_image_t image, char *prefix,
size_t prefix_len)
+ int64_t rbd_get_data_pool_id(rbd_image_t image)
int rbd_get_parent_info2(rbd_image_t image,
char *parent_poolname, size_t ppoolnamelen,
char *parent_name, size_t pnamelen,
class OSError(Error):
""" `OSError` class, derived from `Error` """
- def __init__(self, errno, strerror):
+ def __init__(self, message, errno=None):
+ super(OSError, self).__init__(message)
self.errno = errno
- self.strerror = strerror
def __str__(self):
- return '[Errno {0}] {1}'.format(self.errno, self.strerror)
+ msg = super(OSError, self).__str__()
+ if self.errno is None:
+ return msg
+ return '[errno {0}] {1}'.format(self.errno, msg)
+ def __reduce__(self):
+ return (self.__class__, (self.message, self.errno))
class PermissionError(OSError):
pass
"""
ret = abs(ret)
if ret in errno_to_exception:
- return errno_to_exception[ret](ret, msg)
+ return errno_to_exception[ret](msg, errno=ret)
else:
- return Error(ret, msg + (": error code %d" % ret))
+ return OSError(msg, errno=ret)
cdef rados_ioctx_t convert_ioctx(rados.Ioctx ioctx) except? NULL:
return None
if isinstance(val, bytes):
return val
- elif isinstance(val, unicode):
+ elif isinstance(val, str):
+ return val.encode(encoding)
+ elif sys.version_info < (3, 0) and isinstance(val, unicode):
return val.encode(encoding)
else:
raise InvalidArgument('%s must be a string' % name)
:raises: :class:`FunctionNotSupported`
"""
name = cstr(name, 'name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
cdef:
rados_ioctx_t _ioctx = convert_ioctx(ioctx)
char *_name = name
p_snapname = cstr(p_snapname, 'p_snapname')
p_name = cstr(p_name, 'p_name')
c_name = cstr(c_name, 'c_name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
cdef:
rados_ioctx_t _p_ioctx = convert_ioctx(p_ioctx)
rados_ioctx_t _c_ioctx = convert_ioctx(c_ioctx)
def trash_move(self, ioctx, name, delay=0):
"""
- Moves an RBD image to the trash.
+ Move an RBD image to the trash.
:param ioctx: determines which RADOS pool the image is in
:type ioctx: :class:`rados.Ioctx`
:param name: the name of the image to remove
def trash_remove(self, ioctx, image_id, force=False):
"""
- Deletes an RBD image from trash. If image deferment time has not
+ Delete an RBD image from trash. If image deferment time has not
expired :class:`PermissionError` is raised.
:param ioctx: determines which RADOS pool the image is in
:type ioctx: :class:`rados.Ioctx`
'id' : decode_cstr(c_info.id),
'name' : decode_cstr(c_info.name),
'source' : __source_string[c_info.source],
- 'deletion_time' : datetime.fromtimestamp(c_info.deletion_time),
- 'deferment_end_time' : datetime.fromtimestamp(c_info.deferment_end_time)
+ 'deletion_time' : datetime.utcfromtimestamp(c_info.deletion_time),
+ 'deferment_end_time' : datetime.utcfromtimestamp(c_info.deferment_end_time)
}
rbd_trash_get_cleanup(&c_info)
return info
def trash_list(self, ioctx):
"""
- Lists all entries from trash.
+ List all entries from trash.
:param ioctx: determines which RADOS pool the image is in
:type ioctx: :class:`rados.Ioctx`
:returns: :class:`TrashIterator`
def trash_restore(self, ioctx, image_id, name):
"""
- Restores an RBD image from trash.
+ Restore an RBD image from trash.
:param ioctx: determines which RADOS pool the image is in
:type ioctx: :class:`rados.Ioctx`
:param image_id: the id of the image to restore
},
'state' : self.images[i].state,
'description' : decode_cstr(self.images[i].description),
- 'last_update' : datetime.fromtimestamp(self.images[i].last_update),
+ 'last_update' : datetime.utcfromtimestamp(self.images[i].last_update),
'up' : self.images[i].up,
}
if self.size < self.max_read:
finally:
free(prefix)
+ def data_pool_id(self):
+ """
+ Get the pool id of the pool where the data of this RBD image is stored.
+
+ :returns: int - the pool id
+ """
+ return rbd_get_data_pool_id(self.image)
+
def parent_info(self):
"""
Get information about a cloned image's parent (if any)
def features(self):
"""
- Gets the features bitmask of the image.
+ Get the features bitmask of the image.
:returns: int - the features bitmask of the image
"""
def update_features(self, features, enabled):
"""
- Updates the features bitmask of the image by enabling/disabling
+ Update the features bitmask of the image by enabling/disabling
a single feature. The feature must support the ability to be
dynamically enabled/disabled.
def overlap(self):
"""
- Gets the number of overlapping bytes between the image and its parent
+ Get the number of overlapping bytes between the image and its parent
image. If open to a snapshot, returns the overlap between the snapshot
and the parent image.
def flags(self):
"""
- Gets the flags bitmask of the image.
+ Get the flags bitmask of the image.
:returns: int - the flags bitmask of the image
"""
def is_exclusive_lock_owner(self):
"""
- Gets the status of the image exclusive lock.
+ Get the status of the image exclusive lock.
:returns: bool - true if the image is exclusively locked
"""
:raises: :class:`ArgumentOutOfRange`
"""
dest_name = cstr(dest_name, 'dest_name')
+ data_pool = cstr(data_pool, 'data_pool', opt=True)
cdef:
rados_ioctx_t _dest_ioctx = convert_ioctx(dest_ioctx)
char *_dest_name = dest_name
ret = rbd_snap_get_timestamp(self.image, _snap_id, ×tamp)
if ret != 0:
raise make_ex(ret, 'error getting snapshot timestamp for image: %s, snap_id: %d' % (self.name, snap_id))
- return datetime.fromtimestamp(timestamp.tv_sec)
+ return datetime.utcfromtimestamp(timestamp.tv_sec)
def remove_snap_limit(self):
"""
def stripe_unit(self):
"""
- Returns the stripe unit used for the image.
+ Return the stripe unit used for the image.
"""
cdef uint64_t stripe_unit
with nogil:
def stripe_count(self):
"""
- Returns the stripe count used for the image.
+ Return the stripe count used for the image.
"""
cdef uint64_t stripe_count
with nogil:
raise make_ex(ret, 'error getting stripe count for image %s' % (self.name))
return stripe_count
+ def create_timestamp(self):
+ """
+ Return the create timestamp for the image.
+ """
+ cdef:
+ timespec timestamp
+ with nogil:
+ ret = rbd_get_create_timestamp(self.image, ×tamp)
+ if ret != 0:
+ raise make_ex(ret, 'error getting create timestamp for image: %s' % (self.name))
+ return datetime.utcfromtimestamp(timestamp.tv_sec)
+
def flatten(self):
"""
Flatten clone image (copy all blocks from parent to child)
def rebuild_object_map(self):
"""
- Rebuilds the object map for the image HEAD or currently set snapshot
+ Rebuild the object map for the image HEAD or currently set snapshot
"""
cdef librbd_progress_fn_t prog_cb = &no_op_progress_callback
with nogil:
},
'state' : c_status.state,
'description' : decode_cstr(c_status.description),
- 'last_update' : datetime.fromtimestamp(c_status.last_update),
+ 'last_update' : datetime.utcfromtimestamp(c_status.last_update),
'up' : c_status.up,
}
free(c_status.name)
ret = rbd_metadata_get(self.image, _key, value, &size)
if ret != -errno.ERANGE:
break
+ if ret == -errno.ENOENT:
+ raise KeyError('no metadata %s for image %s' % (key, self.name))
if ret != 0:
raise make_ex(ret, 'error getting metadata %s for image %s' %
- (self.key, self.name,))
+ (key, self.name,))
return decode_cstr(value)
finally:
free(value)
if ret != 0:
raise make_ex(ret, 'error setting metadata %s for image %s' %
- (self.key, self.name,))
+ (key, self.name,))
def metadata_remove(self, key):
with nogil:
ret = rbd_metadata_remove(self.image, _key)
+ if ret == -errno.ENOENT:
+ raise KeyError('no metadata %s for image %s' % (key, self.name))
if ret != 0:
raise make_ex(ret, 'error removing metadata %s for image %s' %
- (self.key, self.name,))
+ (key, self.name,))
def metadata_list(self):
"""
break
self.get_next_chunk()
+ def __dealloc__(self):
+ if self.last_read:
+ free(self.last_read)
+
def get_next_chunk(self):
cdef:
char *c_keys = NULL
self.num_snaps = 10
while True:
self.snaps = <rbd_snap_info_t*>realloc_chk(self.snaps,
- self.num_snaps *
- sizeof(rbd_snap_info_t))
+ self.num_snaps *
+ sizeof(rbd_snap_info_t))
with nogil:
ret = rbd_snap_list(image.image, self.snaps, &self.num_snaps)
if ret >= 0:
def __init__(self, ioctx):
self.ioctx = convert_ioctx(ioctx)
self.num_entries = 1024
- self.entries = <rbd_trash_image_info_t *>realloc_chk(NULL,
- sizeof(rbd_trash_image_info_t) * self.num_entries)
- with nogil:
- ret = rbd_trash_list(self.ioctx, self.entries, &self.num_entries)
- if ret < 0:
- raise make_ex(ret, 'error listing trash entries')
+ self.entries = NULL
+ while True:
+ self.entries = <rbd_trash_image_info_t*>realloc_chk(self.entries,
+ self.num_entries *
+ sizeof(rbd_trash_image_info_t))
+ with nogil:
+ ret = rbd_trash_list(self.ioctx, self.entries, &self.num_entries)
+ if ret >= 0:
+ self.num_entries = ret
+ break
+ elif ret != -errno.ERANGE:
+ raise make_ex(ret, 'error listing trash entries')
__source_string = ['USER', 'MIRRORING']
'id' : decode_cstr(self.entries[i].id),
'name' : decode_cstr(self.entries[i].name),
'source' : TrashIterator.__source_string[self.entries[i].source],
- 'deletion_time' : datetime.fromtimestamp(self.entries[i].deletion_time),
- 'deferment_end_time' : datetime.fromtimestamp(self.entries[i].deferment_end_time)
+ 'deletion_time' : datetime.utcfromtimestamp(self.entries[i].deletion_time),
+ 'deferment_end_time' : datetime.utcfromtimestamp(self.entries[i].deferment_end_time)
}
def __dealloc__(self):