mirror of
https://github.com/ceph/go-ceph
synced 2025-01-09 15:29:53 +00:00
rbd: add snapshot ID related functions
added wrappers for rbd_snap_get_name() and rbd_snap_get_id() Signed-off-by: Mudit Agarwal <muagarwa@redhat.com>
This commit is contained in:
parent
34cab3407f
commit
0e09cd4370
66
rbd/snapshot_octopus.go
Normal file
66
rbd/snapshot_octopus.go
Normal file
@ -0,0 +1,66 @@
|
||||
// +build octopus
|
||||
|
||||
package rbd
|
||||
|
||||
// #cgo LDFLAGS: -lrbd
|
||||
// #include <stdlib.h>
|
||||
// #include <rbd/librbd.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/ceph/go-ceph/internal/retry"
|
||||
)
|
||||
|
||||
// GetSnapID returns the snapshot ID for the given snapshot name.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_snap_get_id(rbd_image_t image, const char *snapname, uint64_t *snap_id)
|
||||
func (image *Image) GetSnapID(snapName string) (uint64, error) {
|
||||
var snapID C.uint64_t
|
||||
if err := image.validate(imageIsOpen); err != nil {
|
||||
return uint64(snapID), err
|
||||
}
|
||||
if snapName == "" {
|
||||
return uint64(snapID), ErrSnapshotNoName
|
||||
}
|
||||
|
||||
cSnapName := C.CString(snapName)
|
||||
defer C.free(unsafe.Pointer(cSnapName))
|
||||
|
||||
ret := C.rbd_snap_get_id(image.image, cSnapName, &snapID)
|
||||
return uint64(snapID), getError(ret)
|
||||
}
|
||||
|
||||
// GetSnapByID returns the snapshot name for the given snapshot ID.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_snap_get_name(rbd_image_t image, uint64_t snap_id, char *snapname, size_t *name_len)
|
||||
func (image *Image) GetSnapByID(snapID uint64) (string, error) {
|
||||
if err := image.validate(imageIsOpen); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var (
|
||||
buf []byte
|
||||
err error
|
||||
)
|
||||
// range from 1k to 64KiB
|
||||
retry.WithSizes(1024, 1<<16, func(len int) retry.Hint {
|
||||
cLen := C.size_t(len)
|
||||
buf = make([]byte, cLen)
|
||||
ret := C.rbd_snap_get_name(
|
||||
image.image,
|
||||
(C.uint64_t)(snapID),
|
||||
(*C.char)(unsafe.Pointer(&buf[0])),
|
||||
&cLen)
|
||||
err = getError(ret)
|
||||
return retry.Size(int(cLen)).If(err == errRange)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
|
||||
}
|
113
rbd/snapshot_octopus_test.go
Normal file
113
rbd/snapshot_octopus_test.go
Normal file
@ -0,0 +1,113 @@
|
||||
// +build octopus
|
||||
|
||||
package rbd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSnapIDFunctions(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()
|
||||
assert.NoError(t, conn.DeletePool(poolName))
|
||||
conn.Shutdown()
|
||||
}()
|
||||
|
||||
t.Run("happyPath", func(t *testing.T) {
|
||||
imgName := "myImage"
|
||||
img, err := Create(ioctx, imgName, testImageSize, testImageOrder, 1)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, img.Remove())
|
||||
}()
|
||||
|
||||
img, err = OpenImage(ioctx, imgName, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, img.Close())
|
||||
}()
|
||||
|
||||
snapName := "mySnap"
|
||||
snapshot, err := img.CreateSnapshot(snapName)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, snapshot.Remove())
|
||||
}()
|
||||
|
||||
snapID, err := img.GetSnapID(snapshot.name)
|
||||
assert.NoError(t, err)
|
||||
snapNameByID, err := img.GetSnapByID(snapID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, snapshot.name, snapNameByID)
|
||||
})
|
||||
|
||||
t.Run("closedImage", func(t *testing.T) {
|
||||
imgName := "myImage"
|
||||
closedImg, err := Create(ioctx, imgName, testImageSize, testImageOrder, 1)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, closedImg.Remove())
|
||||
}()
|
||||
|
||||
img, err := OpenImage(ioctx, imgName, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
snapName := "mySnap"
|
||||
snapshot, err := img.CreateSnapshot(snapName)
|
||||
assert.NoError(t, err)
|
||||
|
||||
snapID, err := img.GetSnapID(snapshot.name)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// close the image
|
||||
assert.NoError(t, img.Close())
|
||||
|
||||
// try to get the ID again
|
||||
_, err = img.GetSnapID(snapshot.name)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = img.GetSnapByID(snapID)
|
||||
assert.Error(t, err)
|
||||
|
||||
// Open the image for snapshot removal
|
||||
img, err = OpenImage(ioctx, imgName, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
snapshot = img.GetSnapshot(snapName)
|
||||
assert.NoError(t, snapshot.Remove())
|
||||
assert.NoError(t, img.Close())
|
||||
})
|
||||
|
||||
t.Run("invalidOptions", func(t *testing.T) {
|
||||
imgName := "someImage"
|
||||
img, err := Create(ioctx, imgName, testImageSize, testImageOrder, 1)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, img.Remove())
|
||||
}()
|
||||
|
||||
img, err = OpenImage(ioctx, imgName, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
assert.NoError(t, img.Close())
|
||||
}()
|
||||
|
||||
_, err = img.GetSnapID("")
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = img.GetSnapID("someSnap")
|
||||
assert.Error(t, err)
|
||||
|
||||
var snapID uint64
|
||||
snapID = 22
|
||||
_, err = img.GetSnapByID(snapID)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user