mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-04-11 18:13:00 +00:00
This commit modifies listSnapAndChildren() to make use of ListChildrenAttributes() instead of ListChildren() which allows us to filter out images in trash. This commit also order the alive images so that temp clone images are followed by images backing volume snapshots so that temp clone images are flattened first. Signed-off-by: Rakshith R <rar@redhat.com>
229 lines
6.3 KiB
Go
229 lines
6.3 KiB
Go
//
|
|
// Ceph Nautilus introduced rbd_get_parent() and deprecated rbd_get_parent_info().
|
|
// Ceph Nautilus introduced rbd_list_children3() and deprecated rbd_list_children().
|
|
|
|
package rbd
|
|
|
|
// #cgo LDFLAGS: -lrbd
|
|
// #include <rbd/librbd.h>
|
|
// #include <errno.h>
|
|
import "C"
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"github.com/ceph/go-ceph/internal/retry"
|
|
)
|
|
|
|
// GetParentInfo looks for the parent of the image and stores the pool, name
|
|
// and snapshot-name in the byte-arrays that are passed as arguments.
|
|
//
|
|
// 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) GetParentInfo(pool, name, snapname []byte) error {
|
|
if err := image.validate(imageIsOpen); err != nil {
|
|
return 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 getError(ret)
|
|
}
|
|
|
|
defer C.rbd_linked_image_spec_cleanup(&parentImage)
|
|
defer C.rbd_snap_spec_cleanup(&parentSnap)
|
|
|
|
strlen := int(C.strlen(parentImage.pool_name))
|
|
if len(pool) < strlen {
|
|
return getError(C.ERANGE)
|
|
}
|
|
if copy(pool, C.GoString(parentImage.pool_name)) != strlen {
|
|
return getError(C.ERANGE)
|
|
}
|
|
|
|
strlen = int(C.strlen(parentImage.image_name))
|
|
if len(name) < strlen {
|
|
return getError(C.ERANGE)
|
|
}
|
|
if copy(name, C.GoString(parentImage.image_name)) != strlen {
|
|
return getError(C.ERANGE)
|
|
}
|
|
|
|
strlen = int(C.strlen(parentSnap.name))
|
|
if len(snapname) < strlen {
|
|
return getError(C.ERANGE)
|
|
}
|
|
if copy(snapname, C.GoString(parentSnap.name)) != strlen {
|
|
return getError(C.ERANGE)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ImageSpec represents the image information.
|
|
type ImageSpec struct {
|
|
ImageName string
|
|
ImageID string
|
|
PoolName string
|
|
PoolNamespace string
|
|
PoolID uint64
|
|
Trash bool
|
|
}
|
|
|
|
// 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),
|
|
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{
|
|
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.
|
|
//
|
|
// Implements:
|
|
//
|
|
// int rbd_list_children3(rbd_image_t image, rbd_linked_image_spec_t *images,
|
|
// size_t *max_images);
|
|
func (image *Image) ListChildren() (pools []string, images []string, err error) {
|
|
if err := image.validate(imageIsOpen); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
var (
|
|
csize C.size_t
|
|
children []C.rbd_linked_image_spec_t
|
|
)
|
|
retry.WithSizes(16, 4096, func(size int) retry.Hint {
|
|
csize = C.size_t(size)
|
|
children = make([]C.rbd_linked_image_spec_t, csize)
|
|
ret := C.rbd_list_children3(
|
|
image.image,
|
|
(*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])),
|
|
&csize)
|
|
err = getErrorIfNegative(ret)
|
|
return retry.Size(int(csize)).If(err == errRange)
|
|
})
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
defer C.rbd_linked_image_spec_list_cleanup((*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])), csize)
|
|
|
|
pools = make([]string, csize)
|
|
images = make([]string, csize)
|
|
for i, child := range children[:csize] {
|
|
pools[i] = C.GoString(child.pool_name)
|
|
images[i] = C.GoString(child.image_name)
|
|
}
|
|
return pools, images, nil
|
|
}
|
|
|
|
// ListChildrenAttributes returns an array of struct with the names and ids of the
|
|
// images and pools and the trash of the images that are children of the given image.
|
|
//
|
|
// Implements:
|
|
//
|
|
// int rbd_list_children3(rbd_image_t image, rbd_linked_image_spec_t *images,
|
|
// size_t *max_images);
|
|
func (image *Image) ListChildrenAttributes() (imgSpec []ImageSpec, err error) {
|
|
if err := image.validate(imageIsOpen); err != nil {
|
|
return nil, err
|
|
}
|
|
var (
|
|
csize C.size_t
|
|
children []C.rbd_linked_image_spec_t
|
|
)
|
|
retry.WithSizes(16, 4096, func(size int) retry.Hint {
|
|
csize = C.size_t(size)
|
|
children = make([]C.rbd_linked_image_spec_t, csize)
|
|
ret := C.rbd_list_children3(
|
|
image.image,
|
|
(*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])),
|
|
&csize)
|
|
err = getErrorIfNegative(ret)
|
|
return retry.Size(int(csize)).If(err == errRange)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer C.rbd_linked_image_spec_list_cleanup((*C.rbd_linked_image_spec_t)(unsafe.Pointer(&children[0])), csize)
|
|
|
|
imgSpec = make([]ImageSpec, csize)
|
|
for i, child := range children[:csize] {
|
|
imgSpec[i] = ImageSpec{
|
|
ImageName: C.GoString(child.image_name),
|
|
ImageID: C.GoString(child.image_id),
|
|
PoolName: C.GoString(child.pool_name),
|
|
PoolNamespace: C.GoString(child.pool_namespace),
|
|
PoolID: uint64(child.pool_id),
|
|
Trash: bool(child.trash),
|
|
}
|
|
}
|
|
return imgSpec, nil
|
|
}
|
|
|
|
// SetSnapByID updates the rbd image (not the Snapshot) such that the snapshot
|
|
// is the source of readable data.
|
|
//
|
|
// Implements:
|
|
//
|
|
// int rbd_snap_set_by_id(rbd_image_t image, uint64_t snap_id);
|
|
func (image *Image) SetSnapByID(snapID uint64) error {
|
|
if err := image.validate(imageIsOpen); err != nil {
|
|
return err
|
|
}
|
|
|
|
ret := C.rbd_snap_set_by_id(image.image, C.uint64_t(snapID))
|
|
return getError(ret)
|
|
}
|