From 08536b9d9367e87f86bc8eb7639188fd9839c719 Mon Sep 17 00:00:00 2001 From: Mudit Agarwal Date: Sat, 6 Jun 2020 11:13:47 +0530 Subject: [PATCH] rbd: add wrappers for rbd_namespace_create(), rbd_namespace_exists() and rbd_namespace_remove(). rbd_namespace_create() function creates namespace for a given iocontext. rbd_namespace_exists() function checks whether the given namespace exists or not. rbd_namespace_remove() function removes the given namespace. Signed-off-by: Mudit Agarwal --- rbd/errors.go | 3 ++ rbd/namespace_nautilus.go | 74 +++++++++++++++++++++++++++++++++ rbd/namespace_nautilus_test.go | 76 ++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 rbd/namespace_nautilus.go create mode 100644 rbd/namespace_nautilus_test.go diff --git a/rbd/errors.go b/rbd/errors.go index 1d0e579..f9c0482 100644 --- a/rbd/errors.go +++ b/rbd/errors.go @@ -66,6 +66,9 @@ var ( // ErrNotFound may be returned from an api call when the requested item is // missing. ErrNotFound = errors.New("RBD image not found") + // ErrNoNamespaceName maye be returned if an api call requires a namespace + // name and it is not provided. + ErrNoNamespaceName = errors.New("Namespace value is missing") // revive:disable:exported for compatibility with old versions RbdErrorImageNotOpen = ErrImageNotOpen diff --git a/rbd/namespace_nautilus.go b/rbd/namespace_nautilus.go new file mode 100644 index 0000000..7cc5e63 --- /dev/null +++ b/rbd/namespace_nautilus.go @@ -0,0 +1,74 @@ +// +build !luminous,!mimic +// +// Ceph Nautilus is the first release that includes rbd_namespace_create(), +// rbd_namespace_remove(), rbd_namespace_exists(). + +package rbd + +// #cgo LDFLAGS: -lrbd +// #include +// #include +// #include +// #include +import "C" + +import ( + "unsafe" + + "github.com/ceph/go-ceph/rados" +) + +// NamespaceCreate creates the namespace for a given Rados IOContext. +// +// Implements: +// int rbd_namespace_create(rados_ioctx_t io, const char *namespace_name); +func NamespaceCreate(ioctx *rados.IOContext, namespaceName string) error { + if ioctx == nil { + return ErrNoIOContext + } + if namespaceName == "" { + return ErrNoNamespaceName + } + cNamespaceName := C.CString(namespaceName) + defer C.free(unsafe.Pointer(cNamespaceName)) + + ret := C.rbd_namespace_create(cephIoctx(ioctx), cNamespaceName) + return getError(ret) +} + +// NamespaceRemove removes a given namespace. +// +// Implements: +// int rbd_namespace_remove(rados_ioctx_t io, const char *namespace_name); +func NamespaceRemove(ioctx *rados.IOContext, namespaceName string) error { + if ioctx == nil { + return ErrNoIOContext + } + if namespaceName == "" { + return ErrNoNamespaceName + } + cNamespaceName := C.CString(namespaceName) + defer C.free(unsafe.Pointer(cNamespaceName)) + + ret := C.rbd_namespace_remove(cephIoctx(ioctx), cNamespaceName) + return getError(ret) +} + +// NamespaceExists checks whether a given namespace exists or not. +// +// Implements: +// int rbd_namespace_exists(rados_ioctx_t io, const char *namespace_name, bool *exists); +func NamespaceExists(ioctx *rados.IOContext, namespaceName string) (bool, error) { + if ioctx == nil { + return false, ErrNoIOContext + } + if namespaceName == "" { + return false, ErrNoNamespaceName + } + cNamespaceName := C.CString(namespaceName) + defer C.free(unsafe.Pointer(cNamespaceName)) + + var exists C.bool + ret := C.rbd_namespace_exists(cephIoctx(ioctx), cNamespaceName, &exists) + return bool(exists), getErrorIfNegative(ret) +} diff --git a/rbd/namespace_nautilus_test.go b/rbd/namespace_nautilus_test.go new file mode 100644 index 0000000..9a65cdd --- /dev/null +++ b/rbd/namespace_nautilus_test.go @@ -0,0 +1,76 @@ +// +build !luminous,!mimic + +package rbd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNamespace(t *testing.T) { + conn := radosConnect(t) + + poolName := GetUUID() + err := conn.MakePool(poolName) + assert.NoError(t, err) + + ioctx, err := conn.OpenIOContext(poolName) + assert.NoError(t, err) + + defer func() { + ioctx.Destroy() + conn.DeletePool(poolName) + conn.Shutdown() + }() + + t.Run("invalidInputNamespace", func(t *testing.T) { + // NamespaceCreate. + err := NamespaceCreate(nil, "someName") + assert.Error(t, err) + err = NamespaceCreate(ioctx, "") + assert.Error(t, err) + + // NamespaceRemove. + err = NamespaceRemove(nil, "someName") + assert.Error(t, err) + err = NamespaceRemove(ioctx, "") + assert.Error(t, err) + + // NamespaceExists. + _, err = NamespaceExists(nil, "someName") + assert.Error(t, err) + _, err = NamespaceExists(ioctx, "") + assert.Error(t, err) + }) + + t.Run("CreateNamespace", func(t *testing.T) { + nameSpace := "myNamespace" + err := NamespaceCreate(ioctx, nameSpace) + assert.NoError(t, err) + + // Check whether it exists or not. + val, err := NamespaceExists(ioctx, nameSpace) + assert.NoError(t, err) + assert.Equal(t, val, true) + + // Create again with same name. + err = NamespaceCreate(ioctx, nameSpace) + assert.Error(t, err) + + // Remove the namespace. + err = NamespaceRemove(ioctx, nameSpace) + assert.NoError(t, err) + }) + + t.Run("NonExistingNamespace", func(t *testing.T) { + // Try to remove. + err := NamespaceRemove(ioctx, "someNamespace") + assert.Error(t, err) + + // Check the existence. + val, err := NamespaceExists(ioctx, "someNamespace") + assert.NoError(t, err) + assert.Equal(t, val, false) + }) +}