From aeac6a63a445b3e5fab352f55e13c5e56882fb9a Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Thu, 17 Feb 2011 09:38:11 -0800 Subject: [PATCH] pybind/rados: add snapshots Add snapshot lookup, iteration, creation, destruction interface. Add test. Signed-off-by: Colin McCabe --- src/pybind/rados.py | 80 ++++++++++++++++++++++++++++++++++++++++- src/test/pybind-test.py | 18 ++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/pybind/rados.py b/src/pybind/rados.py index d23c9fa06f1ce..96e594bc9fa96 100755 --- a/src/pybind/rados.py +++ b/src/pybind/rados.py @@ -3,6 +3,7 @@ Copyright 2011, Hannu Valtonen """ from ctypes import CDLL, c_char_p, c_size_t, c_void_p,\ create_string_buffer, byref, Structure, c_uint64, pointer +import ctypes import errno import time @@ -91,6 +92,7 @@ class Rados(object): return Pool(pool_name, self.librados, pool) class ObjectIterator(object): + """rados.Pool Object iterator""" def __init__(self, pool): self.pool = pool self.ctx = c_void_p() @@ -113,8 +115,61 @@ class ObjectIterator(object): def __del__(self): self.pool.librados.rados_list_objects_close(self.ctx) +class SnapIterator(object): + """Snapshot iterator""" + def __init__(self, pool): + self.pool = pool + # We don't know how big a buffer we need until we've called the + # function. So use the exponential doubling strategy. + num_snaps = 10 + while True: + self.snaps = (ctypes.c_uint64 * num_snaps)() + ret = self.pool.librados.rados_snap_list(self.pool.pool_id, + self.snaps, num_snaps) + if (ret >= 0): + self.max_snap = ret + break + elif (ret != -errno.ERANGE): + raise make_ex(ret, "error calling rados_snap_list for \ +pool '%s'" % self.pool.pool_name) + num_snaps = num_snaps * 2; + self.cur_snap = 0 + + def __iter__(self): + return self + + def next(self): + if (self.cur_snap >= self.max_snap): + raise StopIteration + snap_id = self.snaps[self.cur_snap] + name_len = 10 + while True: + name = create_string_buffer(name_len) + ret = self.pool.librados.rados_snap_get_name(self.pool.pool_id,\ + snap_id, byref(name), name_len) + if (ret == 0): + name_len = ret + break + elif (ret != -errno.ERANGE): + raise make_ex(ret, "rados_snap_get_name error") + name_len = name_len * 2 + snap = Snap(self.pool, name, snap_id) + self.cur_snap = self.cur_snap + 1 + return snap + +class Snap(object): + """Snapshot object""" + def __init__(self, pool, name, snap_id): + self.pool = pool + self.name = name + self.snap_id = snap_id + + def __str__(self): + return "rados.Snap(pool=%s,name=%s,snap_id=%d)" \ + % (str(self.pool), self.name, self.snap_id) + class Pool(object): - """Pool object""" + """rados.Pool object""" def __init__(self, name, librados, pool_id): self.name = name self.librados = librados @@ -242,6 +297,29 @@ written." % (self.name, ret, length)) def list_objects(self): return ObjectIterator(self) + def list_snaps(self): + return SnapIterator(self) + + def create_snap(self, snap_name): + ret = self.librados.rados_snap_create(self.pool_id, + c_char_p(snap_name)) + if (ret != 0): + raise make_ex(ret, "Failed to create snap %s" % snap_name) + + def remove_snap(self, snap_name): + ret = self.librados.rados_snap_remove(self.pool_id, + c_char_p(snap_name)) + if (ret != 0): + raise make_ex(ret, "Failed to remove snap %s" % snap_name) + + def lookup_snap(self, snap_name): + snap_id = c_uint64() + ret = self.librados.rados_snap_lookup(self.pool_id,\ + c_char_p(snap_name), byref(snap_id)) + if (ret != 0): + raise make_ex(ret, "Failed to lookup snap %s" % snap_name) + return Snap(self, snap_name, snap_id) + class Object(object): """Rados object wrapper, makes the object look like a file""" def __init__(self, pool, key): diff --git a/src/test/pybind-test.py b/src/test/pybind-test.py index 42626cf4d9b6b..8e0ec5ec44b2b 100755 --- a/src/test/pybind-test.py +++ b/src/test/pybind-test.py @@ -25,3 +25,21 @@ foo3_pool.write("abc", "abc") foo3_pool.write("def", "def") for obj in foo3_pool.list_objects(): print str(obj) + +# create some snapshots and do stuff with them +print "creating snap bjork" +foo3_pool.create_snap("bjork") +print "creating snap aardvark" +foo3_pool.create_snap("aardvark") +print "creating snap carnuba" +foo3_pool.create_snap("carnuba") +print "listing snaps..." +for snap in foo3_pool.list_snaps(): + print str(snap) + +print "removing snap bjork" +foo3_pool.remove_snap("bjork") + +# remove foo3 +print "deleting foo3" +foo3_pool.delete() -- 2.39.5