]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/rbd: add namespace helper API methods 25206/head
authorJason Dillaman <dillaman@redhat.com>
Wed, 21 Nov 2018 14:55:56 +0000 (09:55 -0500)
committerJason Dillaman <dillaman@redhat.com>
Wed, 21 Nov 2018 15:20:45 +0000 (10:20 -0500)
Fixes: http://tracker.ceph.com/issues/36622
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/api/Namespace.cc
src/librbd/librbd.cc
src/pybind/rbd/rbd.pyx
src/test/pybind/test_rbd.py

index 9d2a3be7c297ca50e8eb30c48c69de067f24d992..282744e5b9e317330bfcc98a1bf2b4b7c111a663 100644 (file)
@@ -177,6 +177,7 @@ int Namespace<I>::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<I>::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;
   }
index 5f9aacd191d0fc056bed931f4007887ff443e1d5..540a5ce92aafb01cd78de2bb3e753f49ccabaa77 100644 (file)
@@ -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);
index a1b588884782bb8767b12237de594fa7b7b6065f..7315299a82f5ddbf5c1c03de197a2493de8400a5 100644 (file)
@@ -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 = <char *>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
index ac09c99db1306f481102b83a65e584c95fe9c1d6..169e78096002273abb6dc2ba43aa496b8ecf19a6 100644 (file)
@@ -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()