mirror of
https://github.com/ceph/ceph
synced 2025-01-31 23:44:10 +00:00
Merge pull request #14463 from trociny/wip-19451
pybind/rbd: add image metadata methods Reviewed-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
commit
7d12a7e184
@ -326,6 +326,14 @@ cdef extern from "rbd/librbd.h" nogil:
|
||||
void rbd_aio_release(rbd_completion_t c)
|
||||
int rbd_aio_flush(rbd_image_t image, rbd_completion_t c)
|
||||
|
||||
int rbd_metadata_get(rbd_image_t image, const char *key, char *value,
|
||||
size_t *val_len)
|
||||
int rbd_metadata_set(rbd_image_t image, const char *key, const char *value)
|
||||
int rbd_metadata_remove(rbd_image_t image, const char *key)
|
||||
int rbd_metadata_list(rbd_image_t image, const char *start, uint64_t max,
|
||||
char *keys, size_t *key_len, char *values,
|
||||
size_t *vals_len)
|
||||
|
||||
RBD_FEATURE_LAYERING = _RBD_FEATURE_LAYERING
|
||||
RBD_FEATURE_STRIPINGV2 = _RBD_FEATURE_STRIPINGV2
|
||||
RBD_FEATURE_EXCLUSIVE_LOCK = _RBD_FEATURE_EXCLUSIVE_LOCK
|
||||
@ -2552,6 +2560,81 @@ written." % (self.name, ret, length))
|
||||
|
||||
return completion
|
||||
|
||||
def metadata_get(self, key):
|
||||
"""
|
||||
Get image metadata for the given key.
|
||||
|
||||
:param key: metadata key
|
||||
:type key: str
|
||||
:returns: str - image id
|
||||
"""
|
||||
key = cstr(key, 'key')
|
||||
cdef:
|
||||
char *_key = key
|
||||
size_t size = 4096
|
||||
char *value = NULL
|
||||
int ret
|
||||
try:
|
||||
while True:
|
||||
value = <char *>realloc_chk(value, size)
|
||||
with nogil:
|
||||
ret = rbd_metadata_get(self.image, _key, value, &size)
|
||||
if ret != -errno.ERANGE:
|
||||
break
|
||||
if ret != 0:
|
||||
raise make_ex(ret, 'error getting metadata %s for image %s' %
|
||||
(self.key, self.name,))
|
||||
return decode_cstr(value)
|
||||
finally:
|
||||
free(value)
|
||||
|
||||
def metadata_set(self, key, value):
|
||||
"""
|
||||
Set image metadata for the given key.
|
||||
|
||||
:param key: metadata key
|
||||
:type key: str
|
||||
:param value: metadata value
|
||||
:type value: str
|
||||
"""
|
||||
key = cstr(key, 'key')
|
||||
value = cstr(value, 'value')
|
||||
cdef:
|
||||
char *_key = key
|
||||
char *_value = value
|
||||
with nogil:
|
||||
ret = rbd_metadata_set(self.image, _key, _value)
|
||||
|
||||
if ret != 0:
|
||||
raise make_ex(ret, 'error setting metadata %s for image %s' %
|
||||
(self.key, self.name,))
|
||||
|
||||
|
||||
def metadata_remove(self, key):
|
||||
"""
|
||||
Remove image metadata for the given key.
|
||||
|
||||
:param key: metadata key
|
||||
:type key: str
|
||||
"""
|
||||
key = cstr(key, 'key')
|
||||
cdef:
|
||||
char *_key = key
|
||||
with nogil:
|
||||
ret = rbd_metadata_remove(self.image, _key)
|
||||
|
||||
if ret != 0:
|
||||
raise make_ex(ret, 'error removing metadata %s for image %s' %
|
||||
(self.key, self.name,))
|
||||
|
||||
def metadata_list(self):
|
||||
"""
|
||||
List image metadata.
|
||||
|
||||
:returns: :class:`MetadataIterator`
|
||||
"""
|
||||
return MetadataIterator(self)
|
||||
|
||||
cdef class LockOwnerIterator(object):
|
||||
"""
|
||||
Iterator over managed lock owners for an image
|
||||
@ -2600,6 +2683,69 @@ cdef class LockOwnerIterator(object):
|
||||
rbd_lock_get_owners_cleanup(self.lock_owners, self.num_lock_owners)
|
||||
free(self.lock_owners)
|
||||
|
||||
cdef class MetadataIterator(object):
|
||||
"""
|
||||
Iterator over metadata list for an image.
|
||||
|
||||
Yields ``(key, value)`` tuple.
|
||||
|
||||
* ``key`` (str) - metadata key
|
||||
* ``value`` (str) - metadata value
|
||||
"""
|
||||
|
||||
cdef:
|
||||
object image_name
|
||||
rbd_image_t image
|
||||
char *last_read
|
||||
uint64_t max_read
|
||||
object next_chunk
|
||||
|
||||
def __init__(self, Image image):
|
||||
self.image_name = image.name
|
||||
self.image = image.image
|
||||
self.last_read = strdup("")
|
||||
self.max_read = 32
|
||||
self.get_next_chunk()
|
||||
|
||||
def __iter__(self):
|
||||
while len(self.next_chunk) > 0:
|
||||
for pair in self.next_chunk:
|
||||
yield pair
|
||||
if len(self.next_chunk) < self.max_read:
|
||||
break
|
||||
self.get_next_chunk()
|
||||
|
||||
def get_next_chunk(self):
|
||||
cdef:
|
||||
char *c_keys = NULL
|
||||
size_t keys_size = 4096
|
||||
char *c_vals = NULL
|
||||
size_t vals_size = 4096
|
||||
try:
|
||||
while True:
|
||||
c_keys = <char *>realloc_chk(c_keys, keys_size)
|
||||
c_vals = <char *>realloc_chk(c_vals, vals_size)
|
||||
with nogil:
|
||||
ret = rbd_metadata_list(self.image, self.last_read,
|
||||
self.max_read, c_keys, &keys_size,
|
||||
c_vals, &vals_size)
|
||||
if ret >= 0:
|
||||
break
|
||||
elif ret != -errno.ERANGE:
|
||||
raise make_ex(ret, 'error listing metadata for image %s' %
|
||||
(self.image_name,))
|
||||
keys = [decode_cstr(key) for key in
|
||||
c_keys[:keys_size].split(b'\0') if key]
|
||||
vals = [decode_cstr(val) for val in
|
||||
c_vals[:vals_size].split(b'\0') if val]
|
||||
if len(keys) > 0:
|
||||
free(self.last_read)
|
||||
self.last_read = strdup(keys[-1])
|
||||
self.next_chunk = zip(keys, vals)
|
||||
finally:
|
||||
free(c_keys)
|
||||
free(c_vals)
|
||||
|
||||
cdef class SnapIterator(object):
|
||||
"""
|
||||
Iterator over snapshot info for an image.
|
||||
|
@ -819,7 +819,34 @@ class TestImage(object):
|
||||
eq(retval[0], 0)
|
||||
eq(sys.getrefcount(comp), 2)
|
||||
|
||||
def test_metadata(self):
|
||||
metadata = list(self.image.metadata_list())
|
||||
eq(len(metadata), 0)
|
||||
self.image.metadata_set("key1", "value1")
|
||||
self.image.metadata_set("key2", "value2")
|
||||
value = self.image.metadata_get("key1")
|
||||
eq(value, "value1")
|
||||
value = self.image.metadata_get("key2")
|
||||
eq(value, "value2")
|
||||
metadata = list(self.image.metadata_list())
|
||||
eq(len(metadata), 2)
|
||||
self.image.metadata_remove("key1")
|
||||
metadata = list(self.image.metadata_list())
|
||||
eq(len(metadata), 1)
|
||||
eq(metadata[0], ("key2", "value2"))
|
||||
self.image.metadata_remove("key2")
|
||||
metadata = list(self.image.metadata_list())
|
||||
eq(len(metadata), 0)
|
||||
|
||||
N = 65
|
||||
for i in xrange(N):
|
||||
self.image.metadata_set("key" + str(i), "X" * 1025)
|
||||
metadata = list(self.image.metadata_list())
|
||||
eq(len(metadata), N)
|
||||
for i in xrange(N):
|
||||
self.image.metadata_remove("key" + str(i))
|
||||
metadata = list(self.image.metadata_list())
|
||||
eq(len(metadata), N - i - 1)
|
||||
|
||||
def check_diff(image, offset, length, from_snapshot, expected):
|
||||
extents = []
|
||||
|
Loading…
Reference in New Issue
Block a user