rbd: include details for parent image in the trash

When a parent image has been removed, it will linger in the trash until
all siblings are gone. The image is not accessible through it's name
anymore, only through its ID.

The ImageSpec that is returned by Image.GetParent() now contains the
Trash boolean and the ImageID to identify if the image is in the trash,
and use OpenImageById() to access the removed parent image.

Related-to: ceph/ceph-csi#4013
Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
Niels de Vos 2023-07-31 15:14:21 +02:00 committed by mergify[bot]
parent 85524f6c39
commit 1257d817db
2 changed files with 62 additions and 4 deletions

View File

@ -2,6 +2,7 @@ package rbd
import ( import (
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -185,6 +186,55 @@ func TestGetParent(t *testing.T) {
assert.Equal(t, parentInfo.Image.ImageName, imgName) assert.Equal(t, parentInfo.Image.ImageName, imgName)
assert.Equal(t, parentInfo.Snap.SnapName, snapName) assert.Equal(t, parentInfo.Snap.SnapName, snapName)
assert.Equal(t, parentInfo.Image.PoolName, poolName) assert.Equal(t, parentInfo.Image.PoolName, poolName)
assert.False(t, parentInfo.Image.Trash)
// TODO: add a comaprison for snap ID
})
t.Run("ParentInTrash", func(t *testing.T) {
trashName := "trashed"
_, err := Create(ioctx, trashName, testImageSize, testImageOrder, 1)
assert.NoError(t, err)
imgTrash, err := OpenImage(ioctx, trashName, NoSnapshot)
assert.NoError(t, err)
defer func() { assert.NoError(t, imgTrash.Close()) }()
imgTrashID, err := imgTrash.GetId()
assert.NoError(t, err)
snapNameTrash := "snapTrash"
snapTrash, err := imgTrash.CreateSnapshot(snapNameTrash)
assert.NoError(t, err)
defer func() {
assert.NoError(t, snapTrash.Remove())
}()
cloneName := "childWithTrash"
optionsClone := NewRbdImageOptions()
defer optionsClone.Destroy()
err = optionsClone.SetUint64(ImageOptionCloneFormat, 2)
assert.NoError(t, err)
// Create a clone of the image.
err = CloneImage(ioctx, trashName, snapNameTrash, ioctx, cloneName, optionsClone)
assert.NoError(t, err)
defer func() { assert.NoError(t, RemoveImage(ioctx, cloneName)) }()
// Move the parent image to the trash, won't be deleted until the clone is removed.
assert.NoError(t, imgTrash.Trash(15*time.Second))
imgNew, err := OpenImage(ioctx, cloneName, NoSnapshot)
assert.NoError(t, err)
defer func() {
assert.NoError(t, imgNew.Close())
}()
parentInfo, err := imgNew.GetParent()
assert.NoError(t, err)
assert.Equal(t, parentInfo.Image.ImageName, trashName)
assert.Equal(t, parentInfo.Image.ImageID, imgTrashID)
assert.Equal(t, parentInfo.Image.PoolName, poolName)
assert.True(t, parentInfo.Image.Trash)
assert.Equal(t, parentInfo.Snap.SnapName, snapNameTrash)
// TODO: add a comaprison for snap ID // TODO: add a comaprison for snap ID
}) })

View File

@ -67,8 +67,12 @@ func (image *Image) GetParentInfo(pool, name, snapname []byte) error {
// ImageSpec represents the image information. // ImageSpec represents the image information.
type ImageSpec struct { type ImageSpec struct {
ImageName string ImageName string
PoolName string ImageID string
PoolName string
PoolNamespace string
PoolID uint64
Trash bool
} }
// SnapSpec represents the snapshot infomation. // SnapSpec represents the snapshot infomation.
@ -104,8 +108,12 @@ func (image *Image) GetParent() (*ParentInfo, error) {
defer C.rbd_snap_spec_cleanup(&parentSnap) defer C.rbd_snap_spec_cleanup(&parentSnap)
imageSpec := ImageSpec{ imageSpec := ImageSpec{
ImageName: C.GoString(parentImage.image_name), ImageName: C.GoString(parentImage.image_name),
PoolName: C.GoString(parentImage.pool_name), ImageID: C.GoString(parentImage.image_id),
PoolName: C.GoString(parentImage.pool_name),
PoolNamespace: C.GoString(parentImage.pool_namespace),
PoolID: uint64(parentImage.pool_id),
Trash: bool(parentImage.trash),
} }
snapSpec := SnapSpec{ snapSpec := SnapSpec{