From 883e30f0caf024dedf913613321ef941c1b9bd3b Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Tue, 5 Jun 2018 14:48:17 -0400 Subject: [PATCH] pybind/rados: new methods for manipulating self-managed snapshots Signed-off-by: Jason Dillaman (cherry picked from commit 21538304d78df9f3b9f54a5b3c9b6b62fc3e6b48) (cherry picked from commit 5bd343db3903d8aca45a40436a6dc240bdc1a0f3) (cherry picked from commit a45f60e0d1a940bef21ea00d0defc7a88a8c7700) --- src/pybind/rados/rados.pyx | 106 ++++++++++++++++++++++++++++++++++ src/test/pybind/test_rados.py | 37 ++++++++++++ 2 files changed, 143 insertions(+) diff --git a/src/pybind/rados/rados.pyx b/src/pybind/rados/rados.pyx index 84f0e33a0201e..0bbf8ebb540ac 100644 --- a/src/pybind/rados/rados.pyx +++ b/src/pybind/rados/rados.pyx @@ -202,6 +202,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) @@ -2701,6 +2712,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 = 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. diff --git a/src/test/pybind/test_rados.py b/src/test/pybind/test_rados.py index fecbbc75b9ffc..07f114e573bc3 100644 --- a/src/test/pybind/test_rados.py +++ b/src/test/pybind/test_rados.py @@ -768,6 +768,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): -- 2.39.5