From 34cab3407f358bb55d080e10b1e701182797d210 Mon Sep 17 00:00:00 2001 From: Mudit Agarwal Date: Wed, 26 Aug 2020 12:51:23 +0530 Subject: [PATCH] rbd: add a new version of GetParentInfo() GetParentInfo() currently requires the caller to specify the string length for various attributes it returns. If the specified string length is less than required, it can return ERANGE error. Replacing it with a new function which avoids this. Signed-off-by: Mudit Agarwal --- rbd/rbd_nautilus_test.go | 77 ++++++++++++++++++++++++++++++++++++++++ rbd/snapshot_nautilus.go | 54 ++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/rbd/rbd_nautilus_test.go b/rbd/rbd_nautilus_test.go index 4e1cc12..39f3724 100644 --- a/rbd/rbd_nautilus_test.go +++ b/rbd/rbd_nautilus_test.go @@ -123,3 +123,80 @@ func TestSparsify(t *testing.T) { assert.Error(t, err) }) } + +func TestGetParent(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() + }() + + imgName := "parent" + 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()) + }() + + t.Run("ParentNotAvailable", func(t *testing.T) { + _, err := img.GetParent() + assert.Error(t, err) + assert.Equal(t, err, ErrNotFound) + }) + + t.Run("ParentAvailable", func(t *testing.T) { + cloneName := "child" + optionsClone := NewRbdImageOptions() + defer optionsClone.Destroy() + err := optionsClone.SetUint64(ImageOptionCloneFormat, 2) + assert.NoError(t, err) + + // Create a clone of the image using the snapshot. + err = CloneImage(ioctx, imgName, snapName, ioctx, cloneName, optionsClone) + assert.NoError(t, err) + defer func() { assert.NoError(t, RemoveImage(ioctx, cloneName)) }() + + imgNew, err := OpenImage(ioctx, cloneName, NoSnapshot) + defer func() { + assert.NoError(t, imgNew.Close()) + }() + assert.NoError(t, err) + + parentInfo, err := imgNew.GetParent() + assert.NoError(t, err) + assert.Equal(t, parentInfo.Image.ImageName, imgName) + assert.Equal(t, parentInfo.Snap.SnapName, snapName) + assert.Equal(t, parentInfo.Image.PoolName, poolName) + // TODO: add a comaprison for snap ID + }) + + t.Run("ClosedImage", func(t *testing.T) { + closedImg, err := Create(ioctx, "someImage", testImageSize, testImageOrder, 1) + assert.NoError(t, err) + defer func() { + assert.NoError(t, closedImg.Remove()) + }() + _, err = closedImg.GetParent() + assert.Error(t, err) + }) +} diff --git a/rbd/snapshot_nautilus.go b/rbd/snapshot_nautilus.go index f0eed0c..3245457 100644 --- a/rbd/snapshot_nautilus.go +++ b/rbd/snapshot_nautilus.go @@ -65,6 +65,60 @@ func (image *Image) GetParentInfo(pool, name, snapname []byte) error { return nil } +// ImageSpec represents the image information. +type ImageSpec struct { + ImageName string + PoolName string +} + +// SnapSpec represents the snapshot infomation. +type SnapSpec struct { + ID uint64 + SnapName string +} + +// ParentInfo represents the parent image and the parent snapshot information. +type ParentInfo struct { + Image ImageSpec + Snap SnapSpec +} + +// GetParent looks for the parent of the image and returns the parent image +// information which includes the image name, the pool name and +// the snapshot information. +// +// Implements: +// int rbd_get_parent(rbd_image_t image, rbd_linked_image_spec_t *parent_image, rbd_snap_spec_t *parent_snap) +func (image *Image) GetParent() (*ParentInfo, error) { + if err := image.validate(imageIsOpen); err != nil { + return nil, err + } + + parentImage := C.rbd_linked_image_spec_t{} + parentSnap := C.rbd_snap_spec_t{} + ret := C.rbd_get_parent(image.image, &parentImage, &parentSnap) + if ret != 0 { + return nil, getError(ret) + } + defer C.rbd_linked_image_spec_cleanup(&parentImage) + defer C.rbd_snap_spec_cleanup(&parentSnap) + + imageSpec := ImageSpec{ + ImageName: C.GoString(parentImage.image_name), + PoolName: C.GoString(parentImage.pool_name), + } + + snapSpec := SnapSpec{ + ID: uint64(parentSnap.id), + SnapName: C.GoString(parentSnap.name), + } + + return &ParentInfo{ + Image: imageSpec, + Snap: snapSpec, + }, nil +} + // ListChildren returns arrays with the pools and names of the images that are // children of the given image. The index of the pools and images arrays can be // used to link the two items together.