Skip to content

Commit

Permalink
rbd: add GetSnapGroupNamespace() to get details about group snapshots
Browse files Browse the repository at this point in the history
rbd_snap_get_group_namespace() can be used to get details about
snapshots of an image, that were created as part of a group.

Signed-off-by: Niels de Vos <ndevos@ibm.com>
  • Loading branch information
nixpanic authored and anoopcs9 committed Mar 6, 2024
1 parent 95c9d7a commit 5f2ed05
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 0 deletions.
6 changes: 6 additions & 0 deletions docs/api-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,12 @@
"comment": "Resize2 resizes an rbd image and allows configuration of allow_shrink and a callback function. The callback\nfunction will be called with the first argument as the progress, the second argument as the total, and the third\nargument as an opaque value that is passed to the Resize2 function's data argument in each callback execution.\nThe resize operation will be aborted if the progress callback returns a non-zero value.\n\nImplements:\n\n\tint rbd_resize2(rbd_image_t image, uint64_t size, allow_shrink bool, librbd_progress_fn_t cb, void *cbdata);\n",
"added_in_version": "v0.25.0",
"expected_stable_version": "v0.27.0"
},
{
"name": "Image.GetSnapGroupNamespace",
"comment": "GetSnapGroupNamespace returns the SnapGroupNamespace of the snapshot which\nis part of a group. The caller should make sure that the snapshot ID passed\nin this function belongs to a snapshot that was taken as part of a group\nsnapshot.\n\nImplements:\n\n\t\tint rbd_snap_get_group_namespace(rbd_image_t image, uint64_t snap_id,\n\t rbd_snap_group_namespace_t *group_snap,\n\t size_t group_snap_size)\n",
"added_in_version": "$NEXT_RELEASE",
"expected_stable_version": "$NEXT_RELEASE_STABLE"
}
]
},
Expand Down
1 change: 1 addition & 0 deletions docs/api-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ No Preview/Deprecated APIs found. All APIs are considered stable.
Name | Added in Version | Expected Stable Version |
---- | ---------------- | ----------------------- |
Image.Resize2 | v0.25.0 | v0.27.0 |
Image.GetSnapGroupNamespace | $NEXT_RELEASE | $NEXT_RELEASE_STABLE |

### Deprecated APIs

Expand Down
53 changes: 53 additions & 0 deletions rbd/snap_group_namespace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build ceph_preview

package rbd

// #cgo LDFLAGS: -lrbd
// #include <rbd/librbd.h>
import "C"

// SnapGroupNamespace provides details about a single snapshot that was taken
// as part of an RBD group.
type SnapGroupNamespace struct {
Pool uint64
GroupName string
GroupSnapName string
}

// GetSnapGroupNamespace returns the SnapGroupNamespace of the snapshot which
// is part of a group. The caller should make sure that the snapshot ID passed
// in this function belongs to a snapshot that was taken as part of a group
// snapshot.
//
// Implements:
//
// int rbd_snap_get_group_namespace(rbd_image_t image, uint64_t snap_id,
// rbd_snap_group_namespace_t *group_snap,
// size_t group_snap_size)
func (image *Image) GetSnapGroupNamespace(snapID uint64) (*SnapGroupNamespace, error) {
if err := image.validate(imageIsOpen); err != nil {
return nil, err
}

var (
err error
sgn C.rbd_snap_group_namespace_t
)

ret := C.rbd_snap_get_group_namespace(image.image,
C.uint64_t(snapID),
&sgn,
C.sizeof_rbd_snap_group_namespace_t)
err = getError(ret)
if err != nil {
return nil, err
}

defer C.rbd_snap_group_namespace_cleanup(&sgn, C.sizeof_rbd_snap_group_namespace_t)

return &SnapGroupNamespace{
Pool: uint64(sgn.group_pool),
GroupName: C.GoString(sgn.group_name),
GroupSnapName: C.GoString(sgn.group_snap_name),
}, nil
}
95 changes: 95 additions & 0 deletions rbd/snap_group_namespace_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//go:build ceph_preview

package rbd

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestGetSnapGroupNamespace(t *testing.T) {
conn := radosConnect(t)
defer conn.Shutdown()

poolname := GetUUID()
err := conn.MakePool(poolname)
require.NoError(t, err)
defer conn.DeletePool(poolname)

ioctx, err := conn.OpenIOContext(poolname)
require.NoError(t, err)
defer ioctx.Destroy()

imageName := "parent"
groupName := "myGroup"
groupSnapName := "myGroupSnap"
options := NewRbdImageOptions()
defer options.Destroy()
err = options.SetUint64(ImageOptionOrder, uint64(testImageOrder))
assert.NoError(t, err)
err = options.SetUint64(ImageOptionFeatures, 1)
assert.NoError(t, err)

err = CreateImage(ioctx, imageName, testImageSize, options)
assert.NoError(t, err)

img, err := OpenImage(ioctx, imageName, NoSnapshot)
assert.NoError(t, err)
defer func() {
assert.NoError(t, img.Close())
assert.NoError(t, img.Remove())
}()

err = GroupCreate(ioctx, groupName)
require.NoError(t, err)
defer func() {
assert.NoError(t, GroupRemove(ioctx, groupName))
}()

err = GroupImageAdd(ioctx, groupName, ioctx, imageName)
require.NoError(t, err)
defer func() {
assert.NoError(t, GroupImageRemove(ioctx, groupName, ioctx, imageName))
}()

err = GroupSnapCreate(ioctx, groupName, groupSnapName)
require.NoError(t, err)
defer func() {
assert.NoError(t, GroupSnapRemove(ioctx, groupName, groupSnapName))
}()

// Take the details of the 1st snapshot of the image.
snapInfoList, err := img.GetSnapshotNames()
assert.NoError(t, err)
snapInfo := snapInfoList[0]
assert.Positive(t, snapInfo.Id)
assert.Regexp(t, "^\\.group\\.", snapInfo.Name)

// The snapshot is expected to be in the 'group' namespace.
nsType, err := img.GetSnapNamespaceType(snapInfo.Id)
assert.NoError(t, err)
assert.Equal(t, nsType, SnapNamespaceTypeGroup)

// Get the info from the snapshot in the group.
sgn, err := img.GetSnapGroupNamespace(snapInfo.Id)
assert.NoError(t, err)
require.NotNil(t, sgn)
assert.Equal(t, groupName, sgn.GroupName)

// Negative testing follows.
invalidSnapID := uint64(22)

t.Run("InvalidSnapID", func(t *testing.T) {
_, err := img.GetSnapGroupNamespace(invalidSnapID)
assert.Error(t, err)
})

t.Run("InvalidImage", func(t *testing.T) {
invalidImgName := GetUUID()
invalidImg := GetImage(ioctx, invalidImgName)
_, err := invalidImg.GetSnapGroupNamespace(invalidSnapID)
assert.Error(t, err)
})
}

0 comments on commit 5f2ed05

Please sign in to comment.