diff --git a/rbd/group_snap.go b/rbd/group_snap.go new file mode 100644 index 0000000..fa010af --- /dev/null +++ b/rbd/group_snap.go @@ -0,0 +1,66 @@ +package rbd + +/* +#cgo LDFLAGS: -lrbd +#include +#include +*/ +import "C" + +import ( + "unsafe" + + "github.com/ceph/go-ceph/rados" +) + +// GroupSnapCreate will create a group snapshot. +// +// Implements: +// int rbd_group_snap_create(rados_ioctx_t group_p, +// const char *group_name, +// const char *snap_name); +func GroupSnapCreate(ioctx *rados.IOContext, group, snap string) error { + cGroupName := C.CString(group) + defer C.free(unsafe.Pointer(cGroupName)) + cSnapName := C.CString(snap) + defer C.free(unsafe.Pointer(cSnapName)) + + ret := C.rbd_group_snap_create(cephIoctx(ioctx), cGroupName, cSnapName) + return getError(ret) +} + +// GroupSnapRemove removes an existing group snapshot. +// +// Implements: +// int rbd_group_snap_remove(rados_ioctx_t group_p, +// const char *group_name, +// const char *snap_name); +func GroupSnapRemove(ioctx *rados.IOContext, group, snap string) error { + cGroupName := C.CString(group) + defer C.free(unsafe.Pointer(cGroupName)) + cSnapName := C.CString(snap) + defer C.free(unsafe.Pointer(cSnapName)) + + ret := C.rbd_group_snap_remove(cephIoctx(ioctx), cGroupName, cSnapName) + return getError(ret) +} + +// GroupSnapRename will rename an existing group snapshot. +// +// Implements: +// int rbd_group_snap_rename(rados_ioctx_t group_p, +// const char *group_name, +// const char *old_snap_name, +// const char *new_snap_name); +func GroupSnapRename(ioctx *rados.IOContext, group, src, dest string) error { + cGroupName := C.CString(group) + defer C.free(unsafe.Pointer(cGroupName)) + cOldSnapName := C.CString(src) + defer C.free(unsafe.Pointer(cOldSnapName)) + cNewSnapName := C.CString(dest) + defer C.free(unsafe.Pointer(cNewSnapName)) + + ret := C.rbd_group_snap_rename( + cephIoctx(ioctx), cGroupName, cOldSnapName, cNewSnapName) + return getError(ret) +} diff --git a/rbd/group_snap_test.go b/rbd/group_snap_test.go new file mode 100644 index 0000000..c42a1ab --- /dev/null +++ b/rbd/group_snap_test.go @@ -0,0 +1,77 @@ +package rbd + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGroupSnapshots(t *testing.T) { + // tests are done as subtests to avoid creating pools, images, etc + // over and over again. + conn := radosConnect(t) + require.NotNil(t, conn) + defer conn.Shutdown() + + poolname := GetUUID() + err := conn.MakePool(poolname) + require.NoError(t, err) + defer conn.DeletePool(poolname) + + ioctx, err := conn.OpenIOContext(poolname) + require.NoError(t, err) + defer ioctx.Destroy() + + // create a group, some images, and add images to the group + gname := "snapme" + err = GroupCreate(ioctx, gname) + assert.NoError(t, err) + + options := NewRbdImageOptions() + assert.NoError(t, + options.SetUint64(ImageOptionOrder, uint64(testImageOrder))) + + name1 := GetUUID() + err = CreateImage(ioctx, name1, testImageSize, options) + require.NoError(t, err) + + name2 := GetUUID() + err = CreateImage(ioctx, name2, testImageSize, options) + require.NoError(t, err) + + err = GroupImageAdd(ioctx, gname, ioctx, name1) + assert.NoError(t, err) + err = GroupImageAdd(ioctx, gname, ioctx, name2) + assert.NoError(t, err) + + t.Run("groupSnapCreateRemove", func(t *testing.T) { + err := GroupSnapCreate(ioctx, gname, "snap1") + assert.NoError(t, err) + err = GroupSnapRemove(ioctx, gname, "snap1") + assert.NoError(t, err) + }) + t.Run("groupSnapRename", func(t *testing.T) { + err := GroupSnapCreate(ioctx, gname, "snap2a") + assert.NoError(t, err) + err = GroupSnapRename(ioctx, gname, "fred", "wilma") + assert.Error(t, err) + err = GroupSnapRename(ioctx, gname, "snap2a", "snap2b") + assert.NoError(t, err) + err = GroupSnapRemove(ioctx, gname, "snap2a") + assert.Error(t, err, "remove of old name: expect error") + err = GroupSnapRemove(ioctx, gname, "snap2b") + assert.NoError(t, err, "remove of current name: expect success") + }) + t.Run("invalidIOContext", func(t *testing.T) { + assert.Panics(t, func() { + GroupSnapCreate(nil, gname, "foo") + }) + assert.Panics(t, func() { + GroupSnapRemove(nil, gname, "foo") + }) + assert.Panics(t, func() { + GroupSnapRename(nil, gname, "foo", "bar") + }) + }) +}