From 1c1497f7c27f73d5c5d29c90aacacbdbb05c6f93 Mon Sep 17 00:00:00 2001 From: Niels de Vos <ndevos@ibm.com> Date: Fri, 30 Aug 2024 17:02:52 +0200 Subject: [PATCH] [WIP] rbd-group-snapshot tool for go-ceph API testing --- Makefile | 2 +- deploy/cephcsi/image/Dockerfile | 2 + tools/rbd-group-snapshot/main.go | 302 +++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 tools/rbd-group-snapshot/main.go diff --git a/Makefile b/Makefile index 3d984dcfa68..05efc6cef11 100644 --- a/Makefile +++ b/Makefile @@ -174,7 +174,7 @@ e2e.test: check-env .PHONY: rbd-group-snapshot rbd-group-snapshot: - go build -o _output/rbd-group-snapshot ./tools/rbd-group-snapshot + go build $(GO_TAGS) -o _output/rbd-group-snapshot ./tools/rbd-group-snapshot # # Update the generated deploy/ files when the template changed. This requires diff --git a/deploy/cephcsi/image/Dockerfile b/deploy/cephcsi/image/Dockerfile index 552e8273d91..fa96fff86a2 100644 --- a/deploy/cephcsi/image/Dockerfile +++ b/deploy/cephcsi/image/Dockerfile @@ -68,6 +68,7 @@ COPY . ${SRC_DIR} # Build executable RUN make cephcsi +RUN make rbd-group-snapshot #-- Final container FROM updated_base @@ -80,6 +81,7 @@ LABEL maintainers="Ceph-CSI Authors" \ description="Ceph-CSI Plugin" COPY --from=builder ${SRC_DIR}/_output/cephcsi /usr/local/bin/cephcsi +COPY --from=builder ${SRC_DIR}/_output/rbd-group-snapshot /usr/local/bin/rbd-group-snapshot # verify that all dynamically linked libraries are available RUN [ $(ldd /usr/local/bin/cephcsi | grep -c '=> not found') = '0' ] diff --git a/tools/rbd-group-snapshot/main.go b/tools/rbd-group-snapshot/main.go new file mode 100644 index 00000000000..2c6266f1a8f --- /dev/null +++ b/tools/rbd-group-snapshot/main.go @@ -0,0 +1,302 @@ +package main + +import ( + "fmt" + + "github.com/ceph/go-ceph/rados" + "github.com/ceph/go-ceph/rbd" +) + +var ( + imageNames = []string{ + "first-volume", + "second-volume", + } + + restoreName = "restored-image" + + pool = "ocs-storagecluster-cephblockpool" + + group = "all-the-volumes" + groupSnap = "all-the-snapshots" +) + +type rbdGroupTest struct { + conn *rados.Conn + ioctx *rados.IOContext +} + +func main() { + rgt := &rbdGroupTest{} + + rgt.connect() + defer rgt.conn.Shutdown() + + rgt.createImages() + defer rgt.removeImages() + + rgt.createGroup() + defer rgt.removeGroup() + + rgt.addImagesToGroup() + defer rgt.removeImagesFromGroup() + + rgt.createGroupSnapshot() + defer rgt.removeGroupSnapshot() + + fmt.Println("images are still in the group") + rgt.listSnapshots() + + rgt.listGroupSnapshot() + + rgt.removeImagesFromGroup() + + fmt.Println("images have been removed from the group") + rgt.listSnapshots() + + rgt.removeGroup() // fails as there is still a group snapshot? + + fmt.Println("the group has been removed - expected to fail") + rgt.listSnapshots() + + fmt.Println("the group snapshot has been removed") + rgt.removeGroupSnapshot() + + rgt.listSnapshots() + + // rgt.restoreFromSnapshot() + // defer rgt.removeRestoredImage() +} + +func (rgt *rbdGroupTest) connect() { + conn, err := rados.NewConn() + if err != nil { + panic(err) + } + + err = conn.ReadDefaultConfigFile() + if err != nil { + panic(err) + } + + err = conn.Connect() + if err != nil { + panic(err) + } + + rgt.conn = conn + + ioctx, err := conn.OpenIOContext(pool) + if err != nil { + panic(err) + } + + rgt.ioctx = ioctx +} + +func (rgt *rbdGroupTest) createImages() { + for _, name := range imageNames { + _, err := rbd.Create(rgt.ioctx, name, uint64(1<<22), 22) + if err != nil { + panic(err) + } + } +} + +func (rgt *rbdGroupTest) removeImages() { + fmt.Println("removing the images") + + for _, name := range imageNames { + err := rbd.RemoveImage(rgt.ioctx, name) + if err != nil { + fmt.Printf("failed to remove image %q: %v\n", name, err) + } + } +} + +func (rgt *rbdGroupTest) createGroup() { + err := rbd.GroupCreate(rgt.ioctx, group) + if err != nil { + panic(err) + } +} + +func (rgt *rbdGroupTest) removeGroup() { + fmt.Println("removing the group") + + err := rbd.GroupRemove(rgt.ioctx, group) + if err != nil { + fmt.Printf("failed to remove group %q: %v\n", group, err) + } +} + +func (rgt *rbdGroupTest) addImagesToGroup() { + for _, name := range imageNames { + err := rbd.GroupImageAdd(rgt.ioctx, group, rgt.ioctx, name) + if err != nil { + panic(err) + } + } +} + +func (rgt *rbdGroupTest) removeImagesFromGroup() { + fmt.Println("removing images from the group") + + for _, name := range imageNames { + err := rbd.GroupImageRemove(rgt.ioctx, group, rgt.ioctx, name) + if err != nil { + fmt.Printf("failed to remove image %q from group %q: %v\n", name, group, err) + } + } +} + +func (rgt *rbdGroupTest) createGroupSnapshot() { + err := rbd.GroupSnapCreate(rgt.ioctx, group, groupSnap) + if err != nil { + panic(err) + } +} + +func (rgt *rbdGroupTest) removeGroupSnapshot() { + fmt.Println("removing the group snapshot") + + err := rbd.GroupSnapRemove(rgt.ioctx, group, groupSnap) + if err != nil { + fmt.Printf("failed to remove group snapshot %q: %v\n", groupSnap, err) + } +} + +func (rgt *rbdGroupTest) listGroupSnapshot() { + fmt.Printf("listing snapshots of group %q\n", group) + + info, err := rbd.GroupSnapGetInfo(rgt.ioctx, group, groupSnap) + if err != nil { + panic(fmt.Sprintf("failed to list snapshots of group %q: %v\n", group, err)) + } + + fmt.Printf("snapshots in the group snapshot %q:\n", group+"@"+info.Name) + for _, snap := range info.Snapshots { + fmt.Printf(" - %q from %+v\n", snap.Name+"@"+info.SnapName, snap) + } +} + +func (rgt *rbdGroupTest) listSnapshots() { + img, err := rbd.OpenImage(rgt.ioctx, imageNames[0], rbd.NoSnapshot) + if err != nil { + panic(err) + } + defer img.Close() + + snaps, err := img.GetSnapshotNames() + if err != nil { + panic(err) + } + + fmt.Printf("listing %d snapshots for image %q\n", len(snaps), imageNames[0]) + for _, snap := range snaps { + fmt.Printf("Snapshot: %+v\n", snap) + } +} + +func (rgt *rbdGroupTest) restoreFromSnapshot() { + img, err := rbd.OpenImage(rgt.ioctx, imageNames[0], rbd.NoSnapshot) + if err != nil { + panic(err) + } + defer img.Close() + + snaps, err := img.GetSnapshotNames() + if err != nil { + panic(err) + } + + options := rbd.NewRbdImageOptions() + defer options.Destroy() + err = options.SetUint64(rbd.ImageOptionOrder, 22) + if err != nil { + panic(err) + } + // err = options.SetUint64(rbd.ImageOptionFeatures, 1) + // if err != nil { + // panic(err) + // } + + fmt.Printf("restoring image %q from parent %q at snapshot %q\n", restoreName, imageNames[0], snaps[0].Name) + snap := img.GetSnapshot(snaps[0].Name) + err = snap.Protect() + if err != nil { + panic(err) + } + defer snap.Unprotect() + + //err = rbd.CloneFromImage(img, snaps[0].Name, rgt.ioctx, restoreName, options) + err = rbd.CloneImageByID(rgt.ioctx, imageNames[0], snaps[0].Id, rgt.ioctx, restoreName, options) + if err != nil { + panic(err) + } + + /* + // alternative to the above -- segfaults, needs a snapshot + fmt.Printf("restoring image %q from parent %q without a snapshot\n", restoreName, imageNames[0]) + err = rbd.CloneFromImage(img, rbd.NoSnapshot, rgt.ioctx, restoreName, options) + if err != nil { + panic(err) + } + defer rbd.RemoveImage(rgt.ioctx, restoreName) + + restored, err := rbd.OpenImage(rgt.ioctx, restoreName, rbd.NoSnapshot) + if err != nil { + panic(err) + } + defer restored.Close() + + //err = restored.SetSnapshot(snaps[0].Name) + err = restored.SetSnapByID(snaps[0].Id) + if err != nil { + panic(err) + } + */ + + // alternative to the above + /* + snapname := "tmp-snap" + snap, err := img.CreateSnapshot(snapname) + if err != nil { + panic(err) + } + defer snap.Remove() + + err = snap.Protect() + if err != nil { + panic(err) + } + defer snap.Unprotect() + + fmt.Printf("restoring image %q from parent %q at snapshot %q\n", restoreName, imageNames[0], snapname) + err = rbd.CloneFromImage(img, snapname, rgt.ioctx, restoreName, options) + if err != nil { + panic(err) + } + defer rbd.RemoveImage(rgt.ioctx, restoreName) + + restored, err := rbd.OpenImage(rgt.ioctx, restoreName, rbd.NoSnapshot) + if err != nil { + panic(err) + } + defer restored.Close() + + err = restored.SetSnapByID(snaps[0].Id) + if err != nil { + panic(err) + } + */ +} + +func (rgt *rbdGroupTest) removeRestoredImage() { + fmt.Println("removing the restored image") + + err := rbd.RemoveImage(rgt.ioctx, restoreName) + if err != nil { + fmt.Printf("failed to remove image %q: %v\n", restoreName, err) + } +}