From 0b7d4ff69ce6b598233d63187ba8b0a913dcecd0 Mon Sep 17 00:00:00 2001 From: Damiano Cipriani Date: Thu, 28 Nov 2024 11:17:08 +0100 Subject: [PATCH] feat(lvol): add snapshot checksum APIs Longhorn 9709 Signed-off-by: Damiano Cipriani --- Dockerfile.dapper | 2 +- app/cmd/basic/bdev_lvol.go | 95 ++++++++++++++++++++++++++++++++++++++ pkg/spdk/client/basic.go | 38 +++++++++++++++ pkg/spdk/types/lvol.go | 12 +++++ 4 files changed, 146 insertions(+), 1 deletion(-) diff --git a/Dockerfile.dapper b/Dockerfile.dapper index 467ff7f..fce77e7 100644 --- a/Dockerfile.dapper +++ b/Dockerfile.dapper @@ -17,7 +17,7 @@ ENV GOLANGCI_LINT_VERSION="v1.60.3" WORKDIR ${DAPPER_SOURCE} -ENV SPDK_COMMIT_ID 10463b5c13b454e173707628b9eac608081f5082 +ENV SPDK_COMMIT_ID 002cd0679259c4e4b782d9540441a46e1228d484 ENV LIBJSONC_COMMIT_ID b4c371fa0cbc4dcbaccc359ce9e957a22988fb34 # Build nvme-cli 2.10.2 ENV NVME_CLI_COMMIT_ID eeaa08c9a0e9184f3889df0bff3d2a23db6d6294 diff --git a/app/cmd/basic/bdev_lvol.go b/app/cmd/basic/bdev_lvol.go index 150c149..e34954c 100644 --- a/app/cmd/basic/bdev_lvol.go +++ b/app/cmd/basic/bdev_lvol.go @@ -33,6 +33,8 @@ func BdevLvolCmd() cli.Command { BdevLvolGetXattrCmd(), BdevLvolGetFragmapCmd(), BdevLvolRenameCmd(), + BdevLvolRegisterSnapshotChecksumCmd(), + BdevLvolGetSnapshotChecksumCmd(), }, } } @@ -654,3 +656,96 @@ func bdevLvolRename(c *cli.Context) error { return util.PrintObject(renamed) } + +func BdevLvolRegisterSnapshotChecksumCmd() cli.Command { + return cli.Command{ + Name: "register-snapshot-checksum", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "alias", + Usage: "The alias of a snapshot is /. Specify this or uuid", + }, + cli.StringFlag{ + Name: "uuid", + Usage: "Specify this or alias", + }, + }, + Usage: "compute and store checksum of snapshot's data: \"register-snapshot-checksum --alias /\"," + + " or \"register-snapshot-checksum --uuid \"", + Action: func(c *cli.Context) { + if err := bdevLvolRegisterSnapshotChecksum(c); err != nil { + logrus.WithError(err).Fatalf("Failed to run register snapshot checksum command") + } + }, + } +} + +func bdevLvolRegisterSnapshotChecksum(c *cli.Context) error { + spdkCli, err := client.NewClient(context.Background()) + if err != nil { + return err + } + + name := c.String("alias") + if name == "" { + name = c.String("uuid") + } + if name == "" { + return fmt.Errorf("either alias or uuid must be provided") + } + + registered, err := spdkCli.BdevLvolRegisterSnapshotChecksum(name) + if err != nil { + return fmt.Errorf("failed to register checksum for snapshot %q: %v", name, err) + } + + return util.PrintObject(registered) +} + +func BdevLvolGetSnapshotChecksumCmd() cli.Command { + return cli.Command{ + Name: "get-snapshot-checksum", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "alias", + Usage: "The alias of a snapshot is /. Specify this or uuid", + }, + cli.StringFlag{ + Name: "uuid", + Usage: "Specify this or alias", + }, + }, + Usage: "get checksum of snapshot's data: \"get-snapshot-checksum --alias /\"," + + " or \"get-snapshot-checksum --uuid \"", + Action: func(c *cli.Context) { + if err := bdevLvolGetSnapshotChecksum(c); err != nil { + logrus.WithError(err).Fatalf("Failed to run get snapshot checksum command") + } + }, + } +} + +func bdevLvolGetSnapshotChecksum(c *cli.Context) error { + spdkCli, err := client.NewClient(context.Background()) + if err != nil { + return err + } + + name := c.String("alias") + if name == "" { + name = c.String("uuid") + } + if name == "" { + return fmt.Errorf("either alias or uuid must be provided") + } + + checksum, err := spdkCli.BdevLvolGetSnapshotChecksum(name) + if err != nil { + return fmt.Errorf("failed to get checksum for snapshot %q: %v", name, err) + } + if checksum == nil { + return fmt.Errorf("no checksum found for snapshot %q", name) + } + + return util.PrintObject(*checksum) +} diff --git a/pkg/spdk/client/basic.go b/pkg/spdk/client/basic.go index bbd5bae..0d6f977 100644 --- a/pkg/spdk/client/basic.go +++ b/pkg/spdk/client/basic.go @@ -502,6 +502,44 @@ func (c *Client) BdevLvolGetFragmap(name string, offset, size uint64) (*spdktype return &result, nil } +// BdevLvolRegisterSnapshotChecksum compute and store checksum of snapshot's data. Overwrite old checksum if already registered. +// +// "name": Required. UUID or alias of the snapshot. The alias of a snapshot is /. +func (c *Client) BdevLvolRegisterSnapshotChecksum(name string) (registered bool, err error) { + req := spdktypes.BdevLvolRegisterSnapshotChecksumRequest{ + Name: name, + } + + cmdOutput, err := c.jsonCli.SendCommandWithLongTimeout("bdev_lvol_register_snapshot_checksum", req) + if err != nil { + return false, err + } + + return registered, json.Unmarshal(cmdOutput, ®istered) +} + +// BdevLvolGetSnapshotChecksum gets snapshot's stored checksum. The checksum must has been previously registered. +// +// "name": Required. UUID or alias of the snapshot. The alias of a snapshot is /. +func (c *Client) BdevLvolGetSnapshotChecksum(name string) (checksum *uint64, err error) { + req := spdktypes.BdevLvolGetSnapshotChecksumRequest{ + Name: name, + } + + cmdOutput, err := c.jsonCli.SendCommandWithLongTimeout("bdev_lvol_get_snapshot_checksum", req) + if err != nil { + return nil, err + } + + var snapshotChecksum spdktypes.BdevLvolSnapshotChecksum + err = json.Unmarshal(cmdOutput, &snapshotChecksum) + if err != nil { + return nil, err + } + + return &snapshotChecksum.Checksum, nil +} + // BdevLvolRename renames a logical volume. // // "oldName": Required. UUID or alias of the existing logical volume. diff --git a/pkg/spdk/types/lvol.go b/pkg/spdk/types/lvol.go index 6f36b4e..ba1c1cc 100644 --- a/pkg/spdk/types/lvol.go +++ b/pkg/spdk/types/lvol.go @@ -150,6 +150,18 @@ type BdevLvolRenameRequest struct { NewName string `json:"new_name"` } +type BdevLvolRegisterSnapshotChecksumRequest struct { + Name string `json:"name"` +} + +type BdevLvolGetSnapshotChecksumRequest struct { + Name string `json:"name"` +} + +type BdevLvolSnapshotChecksum struct { + Checksum uint64 `json:"checksum"` +} + func GetLvolAlias(lvsName, lvolName string) string { return fmt.Sprintf("%s/%s", lvsName, lvolName) }