rbd: add wrapper for function rbd_snap_get_trash_namespace()

Added a wrapper for function rbd_snap_get_trash_namespace() which
returns the original name of the snapshot which was moved to Trash.

Signed-off-by: Mudit Agarwal <muagarwa@redhat.com>
This commit is contained in:
Mudit Agarwal 2020-06-25 17:20:46 +05:30 committed by John Mulligan
parent a5da5e308b
commit 982a3975a9
2 changed files with 127 additions and 0 deletions

View File

@ -8,6 +8,12 @@ package rbd
// #include <rbd/librbd.h> // #include <rbd/librbd.h>
import "C" import "C"
import (
"unsafe"
"github.com/ceph/go-ceph/internal/retry"
)
// SnapNamespaceType indicates the namespace to which the snapshot belongs to. // SnapNamespaceType indicates the namespace to which the snapshot belongs to.
type SnapNamespaceType C.rbd_snap_namespace_type_t type SnapNamespaceType C.rbd_snap_namespace_type_t
@ -40,3 +46,35 @@ func (image *Image) GetSnapNamespaceType(snapID uint64) (SnapNamespaceType, erro
(*C.rbd_snap_namespace_type_t)(&nsType)) (*C.rbd_snap_namespace_type_t)(&nsType))
return nsType, getError(ret) return nsType, getError(ret)
} }
// GetSnapTrashNamespace returns the original name of the snapshot which was
// moved to the Trash. The caller should make sure that the snapshot ID passed in this
// function belongs to a snapshot already in the Trash.
//
// Implements:
// int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id, char *original_name, size_t max_length)
func (image *Image) GetSnapTrashNamespace(snapID uint64) (string, error) {
if err := image.validate(imageIsOpen); err != nil {
return "", err
}
var (
buf []byte
err error
)
retry.WithSizes(4096, 262144, func(length int) retry.Hint {
cLength := C.size_t(length)
buf = make([]byte, cLength)
ret := C.rbd_snap_get_trash_namespace(image.image,
C.uint64_t(snapID),
(*C.char)(unsafe.Pointer(&buf[0])),
cLength)
err = getError(ret)
return retry.Size(int(cLength)).If(err == errRange)
})
if err != nil {
return "", err
}
return C.GoString((*C.char)(unsafe.Pointer(&buf[0]))), nil
}

View File

@ -109,3 +109,92 @@ func TestGetSnapNamespaceType(t *testing.T) {
assert.Equal(t, nsType, SnapNamespaceTypeTrash) assert.Equal(t, nsType, SnapNamespaceTypeTrash)
}) })
} }
func TestGetSnapTrashNamespace(t *testing.T) {
conn := radosConnect(t)
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()
imageName := "parent"
snapName := "mySnap"
cloneName := "myClone"
options := NewRbdImageOptions()
defer options.Destroy()
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
assert.NoError(t, err)
err = options.SetUint64(ImageOptionFeatures, 1)
assert.NoError(t, err)
err = CreateImage(ioctx, imageName, testImageSize, options)
assert.NoError(t, err)
img, err := OpenImage(ioctx, imageName, NoSnapshot)
assert.NoError(t, err)
defer func() {
assert.NoError(t, img.Close())
assert.NoError(t, img.Remove())
}()
snapshot, err := img.CreateSnapshot(snapName)
assert.NoError(t, err)
optionsClone := NewRbdImageOptions()
defer optionsClone.Destroy()
err = optionsClone.SetUint64(ImageOptionCloneFormat, 2)
assert.NoError(t, err)
// Create a clone of the image using the same snapshot.
err = CloneImage(ioctx, imageName, snapName, ioctx, cloneName, optionsClone)
assert.NoError(t, err)
defer func() { assert.NoError(t, RemoveImage(ioctx, cloneName)) }()
// Check the name of the snapshot.
snapInfoList, err := img.GetSnapshotNames()
assert.NoError(t, err)
snapInfo := snapInfoList[0]
assert.Equal(t, snapInfo.Name, snapName)
// Remove the snapshot.
err = snapshot.Remove()
assert.NoError(t, err)
// Snapshot would move to the trash because linked clone is still there.
nsType, err := img.GetSnapNamespaceType(snapInfo.Id)
assert.NoError(t, err)
assert.Equal(t, nsType, SnapNamespaceTypeTrash)
// Get the snap info again, name would have changed.
newSnapInfoList, err := img.GetSnapshotNames()
assert.NoError(t, err)
newSnapInfo := newSnapInfoList[0]
assert.NotEqual(t, newSnapInfo.Name, snapName)
// ID would have remained same.
assert.Equal(t, snapInfo.Id, newSnapInfo.Id)
// Get the original name.
origSnapName, err := img.GetSnapTrashNamespace(newSnapInfo.Id)
assert.NoError(t, err)
assert.Equal(t, snapName, origSnapName)
invalidSnapID := uint64(22)
t.Run("InvalidSnapID", func(t *testing.T) {
_, err := img.GetSnapTrashNamespace(invalidSnapID)
assert.Error(t, err)
})
t.Run("InvalidImage", func(t *testing.T) {
invalidImgName := GetUUID()
invalidImg := GetImage(ioctx, invalidImgName)
_, err := invalidImg.GetSnapTrashNamespace(invalidSnapID)
assert.Error(t, err)
})
}