rbd: implement librbd.rbd_group_snap_get_info

The new GroupSnapGetInfo function can be used to get a list of the RBD
image snapshots that were created as part of the RBD group snapshot.

Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
Niels de Vos 2024-08-30 11:22:23 +02:00 committed by mergify[bot]
parent 065319c787
commit b3b70bc6da
3 changed files with 107 additions and 2 deletions

View File

@ -91,11 +91,25 @@ const (
GroupSnapStateComplete = GroupSnapState(C.RBD_GROUP_SNAP_STATE_COMPLETE)
)
// GroupSnapInfo values are returned by GroupSnapList, representing the
// snapshots that are part of an rbd group.
// GroupSnap contains the information of a single snapshot that is part of a
// group snapshot.
type GroupSnap struct {
Name string
PoolID uint64
SnapID uint64
}
// GroupSnapInfo values are returned by GroupSnapList and GroupSnapGetInfo,
// representing the group snapshots that are created of an rbd group.
// SnapName, ID and Snapshots are only set by the GroupSnapGetInfo function.
type GroupSnapInfo struct {
Name string
State GroupSnapState
SnapName string
ID string
Snapshots []GroupSnap
}
// GroupSnapList returns a slice of snapshots in a group.

71
rbd/group_snap_info.go Normal file
View File

@ -0,0 +1,71 @@
//go:build ceph_preview && !(nautilus || octopus || pacific || quincy || reef || squid)
package rbd
/*
#cgo LDFLAGS: -lrbd
#include <errno.h>
#include <stdlib.h>
#include <rbd/librbd.h>
*/
import "C"
import (
"unsafe"
"github.com/ceph/go-ceph/internal/cutil"
"github.com/ceph/go-ceph/rados"
)
type imgSnapInfoArray [cutil.MaxIdx]C.rbd_group_image_snap_info_t
// GroupSnapGetInfo returns a slice of RBD image snapshots that are part of a
// group snapshot.
//
// Implements:
//
// int rbd_group_snap_get_info(rados_ioctx_t group_p,
// const char *group_name,
// const char *snap_name,
// rbd_group_snap_info2_t *snaps);
func GroupSnapGetInfo(ioctx *rados.IOContext, group, snap string) (GroupSnapInfo, error) {
cGroupName := C.CString(group)
defer C.free(unsafe.Pointer(cGroupName))
cSnapName := C.CString(snap)
defer C.free(unsafe.Pointer(cSnapName))
cSnapInfo := C.rbd_group_snap_info2_t{}
ret := C.rbd_group_snap_get_info(
cephIoctx(ioctx),
cGroupName,
cSnapName,
&cSnapInfo)
err := getErrorIfNegative(ret)
if err != nil {
return GroupSnapInfo{}, err
}
snapCount := uint64(cSnapInfo.image_snaps_count)
snapInfo := GroupSnapInfo{
ID: C.GoString(cSnapInfo.id),
Name: C.GoString(cSnapInfo.name),
SnapName: C.GoString(cSnapInfo.image_snap_name),
State: GroupSnapState(cSnapInfo.state),
Snapshots: make([]GroupSnap, snapCount),
}
imgSnaps := (*imgSnapInfoArray)(unsafe.Pointer(cSnapInfo.image_snaps))[0:snapCount]
for i, imgSnap := range imgSnaps {
snapInfo.Snapshots[i].Name = C.GoString(imgSnap.image_name)
snapInfo.Snapshots[i].PoolID = uint64(imgSnap.pool_id)
snapInfo.Snapshots[i].SnapID = uint64(imgSnap.snap_id)
}
// free C memory allocated by C.rbd_group_snap_get_info call
C.rbd_group_snap_get_info_cleanup(&cSnapInfo)
return snapInfo, nil
}

View File

@ -104,6 +104,26 @@ func TestGroupSnapshots(t *testing.T) {
assert.NoError(t, err)
assert.Len(t, gsl, 0)
})
t.Run("groupSnapGetInfo", func(t *testing.T) {
err := GroupSnapCreate(ioctx, gname, "snapDetails")
assert.NoError(t, err)
defer func() {
err = GroupSnapRemove(ioctx, gname, "snapDetails")
assert.NoError(t, err)
}()
info, err := GroupSnapGetInfo(ioctx, gname, "snapDetails")
assert.NoError(t, err)
assert.Equal(t, GroupSnapStateComplete, info.State)
names := make([]string, len(info.Snapshots))
for i, snap := range info.Snapshots {
names[i] = snap.Name
}
assert.Contains(t, names, name1)
assert.Contains(t, names, name2)
})
t.Run("groupSnapRollback", func(t *testing.T) {
img, err := OpenImage(ioctx, name1, NoSnapshot)
assert.NoError(t, err)