mirror of https://github.com/ceph/go-ceph
rbd: add CloneImage as a wrapper for rbd_clone3 func
Add a new CloneImage that makes use of rbd_clone3 and thus behaves like the new CreateImage function. Signed-off-by: John Mulligan <jmulligan@redhat.com>
This commit is contained in:
parent
ea016c420a
commit
c662d6fb2e
44
rbd/rbd.go
44
rbd/rbd.go
|
@ -1457,3 +1457,47 @@ func RemoveImage(ioctx *rados.IOContext, name string) error {
|
|||
defer C.free(unsafe.Pointer(c_name))
|
||||
return getError(C.rbd_remove(C.rados_ioctx_t(ioctx.Pointer()), c_name))
|
||||
}
|
||||
|
||||
// CloneImage creates a clone of the image from the named snapshot in the
|
||||
// provided io-context with the given name and image options.
|
||||
//
|
||||
// Implements:
|
||||
// int rbd_clone3(rados_ioctx_t p_ioctx, const char *p_name,
|
||||
// const char *p_snapname, rados_ioctx_t c_ioctx,
|
||||
// const char *c_name, rbd_image_options_t c_opts);
|
||||
func CloneImage(ioctx *rados.IOContext, parentName, snapName string,
|
||||
destctx *rados.IOContext, name string, rio *RbdImageOptions) error {
|
||||
|
||||
if rio == nil {
|
||||
return RBDError(C.EINVAL)
|
||||
}
|
||||
|
||||
cParentName := C.CString(parentName)
|
||||
defer C.free(unsafe.Pointer(cParentName))
|
||||
cParentSnapName := C.CString(snapName)
|
||||
defer C.free(unsafe.Pointer(cParentSnapName))
|
||||
cCloneName := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cCloneName))
|
||||
|
||||
ret := C.rbd_clone3(
|
||||
C.rados_ioctx_t(ioctx.Pointer()),
|
||||
cParentName,
|
||||
cParentSnapName,
|
||||
C.rados_ioctx_t(destctx.Pointer()),
|
||||
cCloneName,
|
||||
C.rbd_image_options_t(rio.options))
|
||||
return getError(ret)
|
||||
}
|
||||
|
||||
// CloneFromImage creates a clone of the image from the named snapshot in the
|
||||
// provided io-context with the given name and image options.
|
||||
// This function is a convenience wrapper around CloneImage to support cloning
|
||||
// from an existing Image.
|
||||
func CloneFromImage(parent *Image, snapName string,
|
||||
destctx *rados.IOContext, name string, rio *RbdImageOptions) error {
|
||||
|
||||
if err := parent.validate(imageNeedsIOContext); err != nil {
|
||||
return err
|
||||
}
|
||||
return CloneImage(parent.ioctx, parent.name, snapName, destctx, name, rio)
|
||||
}
|
||||
|
|
106
rbd/rbd_test.go
106
rbd/rbd_test.go
|
@ -1413,6 +1413,112 @@ func TestRemoveImage(t *testing.T) {
|
|||
conn.Shutdown()
|
||||
}
|
||||
|
||||
func TestCloneImage(t *testing.T) {
|
||||
conn := radosConnect(t)
|
||||
|
||||
poolname := GetUUID()
|
||||
err := conn.MakePool(poolname)
|
||||
assert.NoError(t, err)
|
||||
|
||||
ioctx, err := conn.OpenIOContext(poolname)
|
||||
require.NoError(t, err)
|
||||
|
||||
imageName := "parent1"
|
||||
snapName := "snap1"
|
||||
cloneName := "clone1"
|
||||
options := NewRbdImageOptions()
|
||||
defer options.Destroy()
|
||||
err = options.SetUint64(RbdImageOptionOrder, uint64(testImageOrder))
|
||||
assert.NoError(t, err)
|
||||
err = options.SetUint64(RbdImageOptionFeatures, 1)
|
||||
assert.NoError(t, err)
|
||||
err = CreateImage(ioctx, imageName, testImageSize, options)
|
||||
assert.NoError(t, err)
|
||||
|
||||
image, err := OpenImage(ioctx, imageName, NoSnapshot)
|
||||
assert.NoError(t, err)
|
||||
|
||||
snapshot, err := image.CreateSnapshot(snapName)
|
||||
assert.NoError(t, err)
|
||||
err = snapshot.Protect()
|
||||
assert.NoError(t, err)
|
||||
|
||||
t.Run("cloneImage", func(t *testing.T) {
|
||||
imageNames, err := GetImageNames(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, imageNames, imageName)
|
||||
assert.NotContains(t, imageNames, cloneName)
|
||||
|
||||
options := NewRbdImageOptions()
|
||||
defer options.Destroy()
|
||||
err = options.SetUint64(RbdImageOptionFormat, uint64(2))
|
||||
assert.NoError(t, err)
|
||||
err = CloneImage(ioctx, imageName, snapName, ioctx, cloneName, options)
|
||||
assert.NoError(t, err)
|
||||
|
||||
imageNames, err = GetImageNames(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, imageNames, imageName)
|
||||
assert.Contains(t, imageNames, cloneName)
|
||||
|
||||
err = RemoveImage(ioctx, cloneName)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("cloneFromImage", func(t *testing.T) {
|
||||
imageNames, err := GetImageNames(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, imageNames, imageName)
|
||||
assert.NotContains(t, imageNames, cloneName)
|
||||
|
||||
options := NewRbdImageOptions()
|
||||
defer options.Destroy()
|
||||
err = options.SetUint64(RbdImageOptionFormat, uint64(2))
|
||||
assert.NoError(t, err)
|
||||
err = CloneFromImage(image, snapName, ioctx, cloneName, options)
|
||||
assert.NoError(t, err)
|
||||
|
||||
imageNames, err = GetImageNames(ioctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, imageNames, imageName)
|
||||
assert.Contains(t, imageNames, cloneName)
|
||||
|
||||
err = RemoveImage(ioctx, cloneName)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("cloneFromImageInvalidCtx", func(t *testing.T) {
|
||||
options := NewRbdImageOptions()
|
||||
defer options.Destroy()
|
||||
err = options.SetUint64(RbdImageOptionFormat, uint64(2))
|
||||
assert.NoError(t, err)
|
||||
badImage := GetImage(nil, image.name)
|
||||
err = CloneFromImage(badImage, snapName, ioctx, cloneName, options)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("cloneImageNilOpts", func(t *testing.T) {
|
||||
err = CloneImage(ioctx, imageName, snapName, ioctx, cloneName, nil)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
err = snapshot.Unprotect()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = snapshot.Remove()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = image.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = image.Remove()
|
||||
assert.NoError(t, err)
|
||||
|
||||
ioctx.Destroy()
|
||||
conn.DeletePool(poolname)
|
||||
conn.Shutdown()
|
||||
}
|
||||
|
||||
// quickCreate creates an image similar to Create but uses CreateImage.
|
||||
// If possible, avoid using this function for new code/tests. It mainly exists
|
||||
// to help with refactoring of existing tests.
|
||||
|
|
Loading…
Reference in New Issue