pybind/rados: new methods for manipulating self-managed snapshots

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2018-06-05 14:48:17 -04:00
parent 61c06200fe
commit 21538304d7
2 changed files with 143 additions and 0 deletions

View File

@ -235,6 +235,17 @@ cdef extern from "rados/librados.h" nogil:
int rados_ioctx_snap_list(rados_ioctx_t io, rados_snap_t * snaps, int maxlen)
int rados_ioctx_snap_get_stamp(rados_ioctx_t io, rados_snap_t id, time_t * t)
int rados_ioctx_selfmanaged_snap_create(rados_ioctx_t io,
rados_snap_t *snapid)
int rados_ioctx_selfmanaged_snap_remove(rados_ioctx_t io,
rados_snap_t snapid)
int rados_ioctx_selfmanaged_snap_set_write_ctx(rados_ioctx_t io,
rados_snap_t snap_seq,
rados_snap_t *snap,
int num_snaps)
int rados_ioctx_selfmanaged_snap_rollback(rados_ioctx_t io, const char *oid,
rados_snap_t snapid)
int rados_lock_exclusive(rados_ioctx_t io, const char * oid, const char * name,
const char * cookie, const char * desc,
timeval * duration, uint8_t flags)
@ -3182,6 +3193,101 @@ returned %d, but should return zero on success." % (self.name, ret))
if ret != 0:
raise make_ex(ret, "Failed to rollback %s" % oid)
def create_self_managed_snap(self):
"""
Creates a self-managed snapshot
:returns: snap id on success
:raises: :class:`Error`
"""
self.require_ioctx_open()
cdef:
rados_snap_t _snap_id
with nogil:
ret = rados_ioctx_selfmanaged_snap_create(self.io, &_snap_id)
if ret != 0:
raise make_ex(ret, "Failed to create self-managed snapshot")
return int(_snap_id)
@requires(('snap_id', int))
def remove_self_managed_snap(self, snap_id):
"""
Removes a self-managed snapshot
:param snap_id: the name of the snapshot
:type snap_id: int
:raises: :class:`TypeError`
:raises: :class:`Error`
"""
self.require_ioctx_open()
cdef:
rados_snap_t _snap_id = snap_id
with nogil:
ret = rados_ioctx_selfmanaged_snap_remove(self.io, _snap_id)
if ret != 0:
raise make_ex(ret, "Failed to remove self-managed snapshot")
def set_self_managed_snap_write(self, snaps):
"""
Updates the write context to the specified self-managed
snapshot ids.
:param snaps: all associated self-managed snapshot ids
:type snaps: list
:raises: :class:`TypeError`
:raises: :class:`Error`
"""
self.require_ioctx_open()
sorted_snaps = []
snap_seq = 0
if snaps:
sorted_snaps = sorted([int(x) for x in snaps], reverse=True)
snap_seq = sorted_snaps[0]
cdef:
rados_snap_t _snap_seq = snap_seq
rados_snap_t *_snaps = NULL
int _num_snaps = len(sorted_snaps)
try:
_snaps = <rados_snap_t *>malloc(_num_snaps * sizeof(rados_snap_t))
for i in range(len(sorted_snaps)):
_snaps[i] = sorted_snaps[i]
with nogil:
ret = rados_ioctx_selfmanaged_snap_set_write_ctx(self.io,
_snap_seq,
_snaps,
_num_snaps)
if ret != 0:
raise make_ex(ret, "Failed to update snapshot write context")
finally:
free(_snaps)
@requires(('oid', str_type), ('snap_id', int))
def rollback_self_managed_snap(self, oid, snap_id):
"""
Rolls an specific object back to a self-managed snapshot revision
:param oid: the name of the object
:type oid: str
:param snap_id: the name of the snapshot
:type snap_id: int
:raises: :class:`TypeError`
:raises: :class:`Error`
"""
self.require_ioctx_open()
oid = cstr(oid, 'oid')
cdef:
char *_oid = oid
rados_snap_t _snap_id = snap_id
with nogil:
ret = rados_ioctx_selfmanaged_snap_rollback(self.io, _oid, _snap_id)
if ret != 0:
raise make_ex(ret, "Failed to rollback %s" % oid)
def get_last_version(self):
"""
Return the version of the last object read or written to.

View File

@ -1011,6 +1011,43 @@ class TestObject(object):
eq(self.object.read(3), b'bar')
eq(self.object.read(3), b'baz')
class TestIoCtxSelfManagedSnaps(object):
def setUp(self):
self.rados = Rados(conffile='')
self.rados.connect()
self.rados.create_pool('test_pool')
assert self.rados.pool_exists('test_pool')
self.ioctx = self.rados.open_ioctx('test_pool')
def tearDown(self):
cmd = {"prefix":"osd unset", "key":"noup"}
self.rados.mon_command(json.dumps(cmd), b'')
self.ioctx.close()
self.rados.delete_pool('test_pool')
self.rados.shutdown()
def test(self):
# cannot mix-and-match pool and self-managed snapshot mode
self.ioctx.set_self_managed_snap_write([])
self.ioctx.write('abc', b'abc')
snap_id_1 = self.ioctx.create_self_managed_snap()
self.ioctx.set_self_managed_snap_write([snap_id_1])
self.ioctx.write('abc', b'def')
snap_id_2 = self.ioctx.create_self_managed_snap()
self.ioctx.set_self_managed_snap_write([snap_id_1, snap_id_2])
self.ioctx.write('abc', b'ghi')
self.ioctx.rollback_self_managed_snap('abc', snap_id_1)
eq(self.ioctx.read('abc'), b'abc')
self.ioctx.rollback_self_managed_snap('abc', snap_id_2)
eq(self.ioctx.read('abc'), b'def')
self.ioctx.remove_self_managed_snap(snap_id_1)
self.ioctx.remove_self_managed_snap(snap_id_2)
class TestCommand(object):
def setUp(self):