rbd: add DeepCopy()

With rbd_deep_copy() an image can be copied with selected options. This
can be used to create a copy and flatten the image in one go.

Updates: ceph/ceph-csi#2077
Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
Niels de Vos 2021-05-27 16:14:22 +02:00 committed by mergify[bot]
parent e0e56486b0
commit 92b808cbbe
2 changed files with 108 additions and 0 deletions

View File

@ -531,6 +531,33 @@ func (image *Image) Copy2(dest *Image) error {
return getError(C.rbd_copy2(image.image, dest.image))
}
// DeepCopy an rbd image to a new image with specific options.
//
// Implements:
// int rbd_deep_copy(rbd_image_t src, rados_ioctx_t dest_io_ctx,
// const char *destname, rbd_image_options_t dest_opts);
func (image *Image) DeepCopy(ioctx *rados.IOContext, destname string, rio *ImageOptions) error {
if err := image.validate(imageIsOpen); err != nil {
return err
}
if ioctx == nil {
return ErrNoIOContext
}
if destname == "" {
return ErrNoName
}
if rio == nil {
return rbdError(C.EINVAL)
}
cDestname := C.CString(destname)
defer C.free(unsafe.Pointer(cDestname))
ret := C.rbd_deep_copy(image.image, cephIoctx(ioctx), cDestname,
C.rbd_image_options_t(rio.options))
return getError(ret)
}
// Flatten removes snapshot references from the image.
//
// Implements:

View File

@ -958,6 +958,87 @@ func TestImageCopy(t *testing.T) {
conn.Shutdown()
}
func TestImageDeepCopy(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)
t.Run("invalidParameters", func(t *testing.T) {
name := GetUUID()
options := NewRbdImageOptions()
defer options.Destroy()
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
assert.NoError(t, err)
err = CreateImage(ioctx, name, testImageSize, options)
require.NoError(t, err)
// img not open, should fail
img := GetImage(ioctx, name)
err = img.DeepCopy(nil, "", nil)
assert.Equal(t, err, ErrImageNotOpen)
img, err := OpenImage(ioctx, name, NoSnapshot)
require.NoError(t, err)
// pass invalid parameters
err = img.DeepCopy(nil, "", nil)
assert.Error(t, err) // order of errors not enforced
err = img.DeepCopy(ioctx, "", options)
assert.Equal(t, err, ErrNoName)
err = img.DeepCopy(nil, "duplicate", options)
assert.Equal(t, err, ErrNoIOContext)
err = img.DeepCopy(ioctx, "copied", nil)
assert.Error(t, err) // rbdError(C.EINVAL), but can not use C in tests
err = img.Close()
assert.NoError(t, err)
err = RemoveImage(ioctx, name)
assert.NoError(t, err)
})
// try successful copying
t.Run("successfulDeepCopy", func(t *testing.T) {
name := GetUUID()
options := NewRbdImageOptions()
defer options.Destroy()
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
assert.NoError(t, err)
err = CreateImage(ioctx, name, testImageSize, options)
require.NoError(t, err)
img, err := OpenImage(ioctx, name, NoSnapshot)
require.NoError(t, err)
name2 := GetUUID()
err = img.DeepCopy(ioctx, name2, options)
require.NoError(t, err)
img2, err := OpenImage(ioctx, name2, NoSnapshot)
require.NoError(t, err)
err = img2.Close()
assert.NoError(t, err)
err = img2.Remove()
assert.NoError(t, err)
err = img.Close()
assert.NoError(t, err)
})
ioctx.Destroy()
conn.DeletePool(poolname)
conn.Shutdown()
}
func TestParentInfo(t *testing.T) {
conn := radosConnect(t)