From: Jason Dillaman Date: Wed, 21 Nov 2018 14:55:56 +0000 (-0500) Subject: pybind/rbd: add namespace helper API methods X-Git-Tag: v14.1.0~826^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F25206%2Fhead;p=ceph.git pybind/rbd: add namespace helper API methods Fixes: http://tracker.ceph.com/issues/36622 Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/api/Namespace.cc b/src/librbd/api/Namespace.cc index 9d2a3be7c297c..282744e5b9e31 100644 --- a/src/librbd/api/Namespace.cc +++ b/src/librbd/api/Namespace.cc @@ -177,6 +177,7 @@ int Namespace::exists(librados::IoCtx& io_ctx, const std::string& name, bool CephContext *cct = (CephContext *)io_ctx.cct(); ldout(cct, 5) << "name=" << name << dendl; + *exists = false; if (name.empty()) { return -EINVAL; } @@ -189,9 +190,7 @@ int Namespace::exists(librados::IoCtx& io_ctx, const std::string& name, bool cls::rbd::DIRECTORY_STATE_READY); if (r == 0) { *exists = true; - } else if (r == -ENOENT) { - *exists = false; - } else { + } else if (r != -ENOENT) { lderr(cct) << "error asserting namespace: " << cpp_strerror(r) << dendl; return r; } diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 5f9aacd191d0f..540a5ce92aafb 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -3116,6 +3116,7 @@ extern "C" int rbd_namespace_list(rados_ioctx_t io, char *names, size_t *size) { return -ERANGE; } + *size = expected_size; for (int i = 0; i < (int)cpp_names.size(); i++) { const char* name = cpp_names[i].c_str(); strcpy(names, name); diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index a1b588884782b..7315299a82f5d 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -559,6 +559,13 @@ cdef extern from "rbd/librbd.h" nogil: void rbd_config_image_list_cleanup(rbd_config_option_t *options, int max_options) + int rbd_namespace_create(rados_ioctx_t io, const char *namespace_name) + int rbd_namespace_remove(rados_ioctx_t io, const char *namespace_name) + int rbd_namespace_list(rados_ioctx_t io, char *namespace_names, + size_t *size) + int rbd_namespace_exists(rados_ioctx_t io, const char *namespace_name, + bint *exists) + int rbd_pool_init(rados_ioctx_t, bint force) void rbd_pool_stats_create(rbd_pool_stats_t *stats) @@ -1932,6 +1939,89 @@ class RBD(object): if ret != 0: raise make_ex(ret, 'error renaming group') + def namespace_create(self, ioctx, name): + """ + Create an RBD namespace within a pool + + :param ioctx: determines which RADOS pool + :type ioctx: :class:`rados.Ioctx` + :param name: namespace name + :type name: str + """ + name = cstr(name, 'name') + cdef: + rados_ioctx_t _ioctx = convert_ioctx(ioctx) + const char *_name = name + with nogil: + ret = rbd_namespace_create(_ioctx, _name) + if ret != 0: + raise make_ex(ret, 'error creating namespace') + + def namespace_remove(self, ioctx, name): + """ + Remove an RBD namespace from a pool + + :param ioctx: determines which RADOS pool + :type ioctx: :class:`rados.Ioctx` + :param name: namespace name + :type name: str + """ + name = cstr(name, 'name') + cdef: + rados_ioctx_t _ioctx = convert_ioctx(ioctx) + const char *_name = name + with nogil: + ret = rbd_namespace_remove(_ioctx, _name) + if ret != 0: + raise make_ex(ret, 'error removing namespace') + + def namespace_exists(self, ioctx, name): + """ + Verifies if a namespace exists within a pool + + :param ioctx: determines which RADOS pool + :type ioctx: :class:`rados.Ioctx` + :param name: namespace name + :type name: str + :returns: bool - true if namespace exists + """ + name = cstr(name, 'name') + cdef: + rados_ioctx_t _ioctx = convert_ioctx(ioctx) + const char *_name = name + bint _exists = False + with nogil: + ret = rbd_namespace_exists(_ioctx, _name, &_exists) + if ret != 0: + raise make_ex(ret, 'error verifying namespace') + return bool(_exists != 0) + + def namespace_list(self, ioctx): + """ + List all namespaces within a pool + + :param ioctx: determines which RADOS pool + :type ioctx: :class:`rados.Ioctx` + :returns: list - collection of namespace names + """ + cdef: + rados_ioctx_t _ioctx = convert_ioctx(ioctx) + char *_names = NULL + size_t _size = 512 + try: + while True: + _names = realloc_chk(_names, _size) + with nogil: + ret = rbd_namespace_list(_ioctx, _names, &_size) + if ret >= 0: + break + elif ret != -errno.ERANGE: + raise make_ex(ret, 'error listing namespaces') + return [decode_cstr(name) for name in _names[:_size].split(b'\0') + if name] + finally: + free(_names) + def pool_init(self, ioctx, force): """ Initialize an RBD pool diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index ac09c99db1306..169e780960022 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -380,6 +380,21 @@ def test_config_list(): for option in rbd.config_list(ioctx): eq(option['source'], RBD_CONFIG_SOURCE_CONFIG) +def test_namespaces(): + rbd = RBD() + + eq(False, rbd.namespace_exists(ioctx, 'ns1')) + eq([], rbd.namespace_list(ioctx)) + assert_raises(ImageNotFound, rbd.namespace_remove, ioctx, 'ns1') + + rbd.namespace_create(ioctx, 'ns1') + eq(True, rbd.namespace_exists(ioctx, 'ns1')) + + assert_raises(ImageExists, rbd.namespace_create, ioctx, 'ns1') + eq(['ns1'], rbd.namespace_list(ioctx)) + rbd.namespace_remove(ioctx, 'ns1') + eq([], rbd.namespace_list(ioctx)) + @require_new_format() def test_pool_stats(): rbd = RBD()