Skip to content

Commit

Permalink
engine: add timestamp to user created snapshot
Browse files Browse the repository at this point in the history
Longhorn 7641

Signed-off-by: Damiano Cipriani <damiano.cipriani@suse.com>
  • Loading branch information
DamiaSan committed Jun 26, 2024
1 parent 3c9b52b commit 3948d85
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 58 deletions.
44 changes: 24 additions & 20 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

type SnapshotOptions struct {
UserCreated bool
Timestamp string
}

type Replica struct {
Expand All @@ -28,14 +29,15 @@ type Replica struct {
}

type Lvol struct {
Name string `json:"name"`
UUID string `json:"uuid"`
SpecSize uint64 `json:"spec_size"`
ActualSize uint64 `json:"actual_size"`
Parent string `json:"parent"`
Children map[string]bool `json:"children"`
CreationTime string `json:"creation_time"`
UserCreated bool `json:"user_created"`
Name string `json:"name"`
UUID string `json:"uuid"`
SpecSize uint64 `json:"spec_size"`
ActualSize uint64 `json:"actual_size"`
Parent string `json:"parent"`
Children map[string]bool `json:"children"`
CreationTime string `json:"creation_time"`
UserCreated bool `json:"user_created"`
SnapshotTimestamp string `json:"snapshot_timestamp"`
}

func ProtoLvolToLvol(l *spdkrpc.Lvol) *Lvol {
Expand All @@ -45,12 +47,13 @@ func ProtoLvolToLvol(l *spdkrpc.Lvol) *Lvol {
return &Lvol{
Name: l.Name,
// UUID: l.Uuid,
SpecSize: l.SpecSize,
ActualSize: l.ActualSize,
Parent: l.Parent,
Children: l.Children,
CreationTime: l.CreationTime,
UserCreated: l.UserCreated,
SpecSize: l.SpecSize,
ActualSize: l.ActualSize,
Parent: l.Parent,
Children: l.Children,
CreationTime: l.CreationTime,
UserCreated: l.UserCreated,
SnapshotTimestamp: l.SnapshotTimestamp,
}
}

Expand All @@ -61,12 +64,13 @@ func LvolToProtoLvol(l *Lvol) *spdkrpc.Lvol {
return &spdkrpc.Lvol{
Name: l.Name,
// Uuid: l.UUID,
SpecSize: l.SpecSize,
ActualSize: l.ActualSize,
Parent: l.Parent,
Children: l.Children,
CreationTime: l.CreationTime,
UserCreated: l.UserCreated,
SpecSize: l.SpecSize,
ActualSize: l.ActualSize,
Parent: l.Parent,
Children: l.Children,
CreationTime: l.CreationTime,
UserCreated: l.UserCreated,
SnapshotTimestamp: l.SnapshotTimestamp,
}
}

Expand Down
35 changes: 21 additions & 14 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,23 @@ func (c *SPDKClient) ReplicaWatch(ctx context.Context) (*api.ReplicaStream, erro
}

func (c *SPDKClient) ReplicaSnapshotCreate(name, snapshotName string, opts *api.SnapshotOptions) error {
if name == "" || snapshotName == "" {
return fmt.Errorf("failed to create SPDK replica snapshot: missing required parameter name or snapshot name")
if name == "" || snapshotName == "" || opts == nil {
return fmt.Errorf("failed to create SPDK replica snapshot: missing required parameter name, snapshot name or opts")
}

client := c.getSPDKServiceClient()
ctx, cancel := context.WithTimeout(context.Background(), GRPCServiceTimeout)
defer cancel()

_, err := client.ReplicaSnapshotCreate(ctx, &spdkrpc.SnapshotRequest{
Name: name,
SnapshotName: snapshotName,
UserCreated: opts != nil && opts.UserCreated,
})
snapshotRequest := spdkrpc.SnapshotRequest{
Name: name,
SnapshotName: snapshotName,
UserCreated: opts.UserCreated,
SnaphotTimestamp: opts.Timestamp,
}

_, err := client.ReplicaSnapshotCreate(ctx, &snapshotRequest)

return errors.Wrapf(err, "failed to create SPDK replica %s snapshot %s", name, snapshotName)
}

Expand Down Expand Up @@ -320,19 +324,22 @@ func (c *SPDKClient) ReplicaRebuildingDstFinish(replicaName string, unexposeRequ
}

func (c *SPDKClient) ReplicaRebuildingDstSnapshotCreate(name, snapshotName string, opts *api.SnapshotOptions) error {
if name == "" || snapshotName == "" {
return fmt.Errorf("failed to create dst SPDK replica rebuilding snapshot: missing required parameter name or snapshot name")
if name == "" || snapshotName == "" || opts == nil {
return fmt.Errorf("failed to create dst SPDK replica rebuilding snapshot: missing required parameter name, snapshot name or opts")
}

client := c.getSPDKServiceClient()
ctx, cancel := context.WithTimeout(context.Background(), GRPCServiceTimeout)
defer cancel()

_, err := client.ReplicaRebuildingDstSnapshotCreate(ctx, &spdkrpc.SnapshotRequest{
Name: name,
SnapshotName: snapshotName,
UserCreated: opts != nil && opts.UserCreated,
})
snapshotRequest := spdkrpc.SnapshotRequest{
Name: name,
SnapshotName: snapshotName,
UserCreated: opts.UserCreated,
SnaphotTimestamp: opts.Timestamp,
}

_, err := client.ReplicaRebuildingDstSnapshotCreate(ctx, &snapshotRequest)
return errors.Wrapf(err, "failed to create dst SPDK replica %s rebuilding snapshot %s", name, snapshotName)
}

Expand Down
18 changes: 14 additions & 4 deletions pkg/spdk/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,10 @@ func (e *Engine) ReplicaAddStart(spdkClient *spdkclient.Client, replicaName, rep

// TODO: For online rebuilding, the IO should be paused first
snapshotName := GenerateRebuildingSnapshotName()
updateRequired, err = e.snapshotOperationWithoutLock(spdkClient, replicaClients, snapshotName, SnapshotOperationCreate, nil)
opts := &api.SnapshotOptions{
Timestamp: time.Now().String(),
}
updateRequired, err = e.snapshotOperationWithoutLock(spdkClient, replicaClients, snapshotName, SnapshotOperationCreate, opts)
if err != nil {
return err
}
Expand Down Expand Up @@ -963,7 +966,13 @@ func (e *Engine) ReplicaShallowCopy(dstReplicaName, dstReplicaAddress string) (e
if err = srcReplicaServiceCli.ReplicaSnapshotShallowCopy(srcReplicaName, currentSnapshotName); err != nil {
return err
}
if err = dstReplicaServiceCli.ReplicaRebuildingDstSnapshotCreate(dstReplicaName, currentSnapshotName, &api.SnapshotOptions{UserCreated: rpcSrcReplica.Snapshots[currentSnapshotName].UserCreated}); err != nil {

snapshotOptions := &api.SnapshotOptions{
UserCreated: rpcSrcReplica.Snapshots[currentSnapshotName].UserCreated,
Timestamp: rpcSrcReplica.Snapshots[currentSnapshotName].SnapshotTimestamp,
}

if err = dstReplicaServiceCli.ReplicaRebuildingDstSnapshotCreate(dstReplicaName, currentSnapshotName, snapshotOptions); err != nil {
return err
}
prevSnapshotName = currentSnapshotName
Expand Down Expand Up @@ -1064,11 +1073,12 @@ const (
func (e *Engine) SnapshotCreate(spdkClient *spdkclient.Client, inputSnapshotName string) (snapshotName string, err error) {
e.log.Infof("Creating snapshot %s", inputSnapshotName)

opts := api.SnapshotOptions{
opts := &api.SnapshotOptions{
UserCreated: true,
Timestamp: time.Now().String(),
}

return e.snapshotOperation(spdkClient, inputSnapshotName, SnapshotOperationCreate, &opts)
return e.snapshotOperation(spdkClient, inputSnapshotName, SnapshotOperationCreate, opts)
}

func (e *Engine) SnapshotDelete(spdkClient *spdkclient.Client, snapshotName string) (err error) {
Expand Down
51 changes: 33 additions & 18 deletions pkg/spdk/replica.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,10 @@ type Lvol struct {
ActualSize uint64
Parent string
// Children is map[<snapshot lvol name>] rather than map[<snapshot name>]. <snapshot lvol name> consists of `<replica name>-snap-<snapshot name>`
Children map[string]*Lvol
CreationTime string
UserCreated bool
Children map[string]*Lvol
CreationTime string
UserCreated bool
SnapshotTimestamp string
}

func ServiceReplicaToProtoReplica(r *Replica) *spdkrpc.Replica {
Expand Down Expand Up @@ -122,13 +123,14 @@ func ServiceReplicaToProtoReplica(r *Replica) *spdkrpc.Replica {

func ServiceLvolToProtoLvol(replicaName string, lvol *Lvol) *spdkrpc.Lvol {
res := &spdkrpc.Lvol{
Uuid: lvol.UUID,
SpecSize: lvol.SpecSize,
ActualSize: lvol.ActualSize,
Parent: GetSnapshotNameFromReplicaSnapshotLvolName(replicaName, lvol.Parent),
Children: map[string]bool{},
CreationTime: lvol.CreationTime,
UserCreated: lvol.UserCreated,
Uuid: lvol.UUID,
SpecSize: lvol.SpecSize,
ActualSize: lvol.ActualSize,
Parent: GetSnapshotNameFromReplicaSnapshotLvolName(replicaName, lvol.Parent),
Children: map[string]bool{},
CreationTime: lvol.CreationTime,
UserCreated: lvol.UserCreated,
SnapshotTimestamp: lvol.SnapshotTimestamp,
}

if lvol.Name == replicaName {
Expand Down Expand Up @@ -158,9 +160,10 @@ func BdevLvolInfoToServiceLvol(bdev *spdktypes.BdevInfo) *Lvol {
ActualSize: bdev.DriverSpecific.Lvol.NumAllocatedClusters * defaultClusterSize,
Parent: bdev.DriverSpecific.Lvol.BaseSnapshot,
// Need to update this separately
Children: map[string]*Lvol{},
CreationTime: bdev.CreationTime,
UserCreated: bdev.DriverSpecific.Lvol.Xattrs[spdkclient.UserCreated] == "true",
Children: map[string]*Lvol{},
CreationTime: bdev.CreationTime,
UserCreated: bdev.DriverSpecific.Lvol.Xattrs[spdkclient.UserCreated] == "true",
SnapshotTimestamp: bdev.DriverSpecific.Lvol.Xattrs[spdkclient.SnapshotTimestamp],
}
}

Expand Down Expand Up @@ -403,7 +406,7 @@ func compareSvcLvols(prev, cur *Lvol, checkChildren, checkActualSize bool) error
if cur == nil {
return fmt.Errorf("cannot find the corresponding cur lvol")
}
if prev.Name != cur.Name || prev.UUID != cur.UUID || prev.CreationTime != cur.CreationTime || prev.SpecSize != cur.SpecSize || prev.Parent != cur.Parent || len(prev.Children) != len(cur.Children) {
if prev.Name != cur.Name || prev.UUID != cur.UUID || prev.SnapshotTimestamp != cur.SnapshotTimestamp || prev.SpecSize != cur.SpecSize || prev.Parent != cur.Parent || len(prev.Children) != len(cur.Children) {
return fmt.Errorf("found mismatching lvol %+v with recorded prev lvol %+v", cur, prev)
}
if checkChildren {
Expand Down Expand Up @@ -830,11 +833,17 @@ func (r *Replica) SnapshotCreate(spdkClient *spdkclient.Client, snapshotName str

var xattrs []spdkclient.Xattr
if opts != nil {
xattr := spdkclient.Xattr{
userCreated := spdkclient.Xattr{
Name: spdkclient.UserCreated,
Value: strconv.FormatBool(opts.UserCreated),
}
xattrs = append(xattrs, xattr)
xattrs = append(xattrs, userCreated)

snapshotTimestamp := spdkclient.Xattr{
Name: spdkclient.SnapshotTimestamp,
Value: opts.Timestamp,
}
xattrs = append(xattrs, snapshotTimestamp)
}

snapUUID, err := spdkClient.BdevLvolSnapshot(headSvcLvol.UUID, snapLvolName, xattrs)
Expand Down Expand Up @@ -1446,11 +1455,17 @@ func (r *Replica) RebuildingDstSnapshotCreate(spdkClient *spdkclient.Client, sna

var xattrs []spdkclient.Xattr
if opts != nil {
xattr := spdkclient.Xattr{
userCreated := spdkclient.Xattr{
Name: spdkclient.UserCreated,
Value: strconv.FormatBool(opts.UserCreated),
}
xattrs = append(xattrs, xattr)
xattrs = append(xattrs, userCreated)

snapshotTimestamp := spdkclient.Xattr{
Name: spdkclient.SnapshotTimestamp,
Value: opts.Timestamp,
}
xattrs = append(xattrs, snapshotTimestamp)
}

snapLvolName := GetReplicaSnapshotLvolName(r.Name, snapshotName)
Expand Down
14 changes: 12 additions & 2 deletions pkg/spdk/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,12 @@ func (s *Server) ReplicaSnapshotCreate(ctx context.Context, req *spdkrpc.Snapsho
return nil, grpcstatus.Errorf(grpccodes.NotFound, "cannot find replica %s during snapshot create", req.Name)
}

return r.SnapshotCreate(spdkClient, req.SnapshotName, &api.SnapshotOptions{UserCreated: req.UserCreated})
opts := &api.SnapshotOptions{
UserCreated: req.UserCreated,
Timestamp: req.SnaphotTimestamp,
}

return r.SnapshotCreate(spdkClient, req.SnapshotName, opts)
}

func (s *Server) ReplicaSnapshotDelete(ctx context.Context, req *spdkrpc.SnapshotRequest) (ret *emptypb.Empty, err error) {
Expand Down Expand Up @@ -660,7 +665,12 @@ func (s *Server) ReplicaRebuildingDstSnapshotCreate(ctx context.Context, req *sp
return nil, grpcstatus.Errorf(grpccodes.NotFound, "cannot find replica %s during rebuilding dst snapshot create", req.Name)
}

if err = r.RebuildingDstSnapshotCreate(spdkClient, req.SnapshotName, &api.SnapshotOptions{UserCreated: req.UserCreated}); err != nil {
opts := &api.SnapshotOptions{
UserCreated: req.UserCreated,
Timestamp: req.SnaphotTimestamp,
}

if err = r.RebuildingDstSnapshotCreate(spdkClient, req.SnapshotName, opts); err != nil {
return nil, err
}
return &emptypb.Empty{}, nil
Expand Down

0 comments on commit 3948d85

Please sign in to comment.