From 814bf4459a08b737cf37664c83255c9d8b121b00 Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Wed, 2 Dec 2020 15:58:31 +0530 Subject: [PATCH] cephfs: implement snapshot protect and unprotect to go-ceph Signed-off-by: Madhu Rajanna --- internal/cephfs/clone.go | 8 ++-- internal/cephfs/controllerserver.go | 6 +-- internal/cephfs/errors.go | 2 - internal/cephfs/snapshot.go | 66 ++++++++++------------------- 4 files changed, 29 insertions(+), 53 deletions(-) diff --git a/internal/cephfs/clone.go b/internal/cephfs/clone.go index 2151fc471..33fa25e1e 100644 --- a/internal/cephfs/clone.go +++ b/internal/cephfs/clone.go @@ -68,7 +68,7 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO if err = purgeVolume(ctx, cloneID, cr, volOpt, true); err != nil { util.ErrorLog(ctx, "failed to delete volume %s: %v", cloneID, err) } - if err = unprotectSnapshot(ctx, parentvolOpt, cr, snapshotID, volID); err != nil { + if err = parentvolOpt.unprotectSnapshot(ctx, snapshotID, volID); err != nil { // In case the snap is already unprotected we get ErrSnapProtectionExist error code // in that case we are safe and we could discard this error and we are good to go // ahead with deletion @@ -81,7 +81,7 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO } } }() - protectErr = protectSnapshot(ctx, parentvolOpt, cr, snapshotID, volID) + protectErr = parentvolOpt.protectSnapshot(ctx, snapshotID, volID) if protectErr != nil { util.ErrorLog(ctx, "failed to protect snapshot %s %v", snapshotID, protectErr) return protectErr @@ -117,7 +117,7 @@ func createCloneFromSubvolume(ctx context.Context, volID, cloneID volumeID, volO return err } // As we completed clone, remove the intermediate snap - if err = unprotectSnapshot(ctx, parentvolOpt, cr, snapshotID, volID); err != nil { + if err = parentvolOpt.unprotectSnapshot(ctx, snapshotID, volID); err != nil { // In case the snap is already unprotected we get ErrSnapProtectionExist error code // in that case we are safe and we could discard this error and we are good to go // ahead with deletion @@ -147,7 +147,7 @@ func cleanupCloneFromSubvolumeSnapshot(ctx context.Context, volID, cloneID volum } if snapInfo.Protected == snapshotIsProtected { - err = unprotectSnapshot(ctx, parentVolOpt, cr, snapShotID, volID) + err = parentVolOpt.unprotectSnapshot(ctx, snapShotID, volID) if err != nil { util.ErrorLog(ctx, "failed to unprotect snapshot %s %v", snapShotID, err) return err diff --git a/internal/cephfs/controllerserver.go b/internal/cephfs/controllerserver.go index 6b3d837d7..a83121bfb 100644 --- a/internal/cephfs/controllerserver.go +++ b/internal/cephfs/controllerserver.go @@ -534,7 +534,7 @@ func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS // check snapshot is protected protected := true if !(snapInfo.Protected == snapshotIsProtected) { - err = protectSnapshot(ctx, parentVolOptions, cr, volumeID(sid.FsSnapshotName), volumeID(vid.FsSubvolName)) + err = parentVolOptions.protectSnapshot(ctx, volumeID(sid.FsSnapshotName), volumeID(vid.FsSubvolName)) if err != nil { protected = false util.WarningLog(ctx, "failed to protect snapshot of snapshot: %s (%s)", @@ -611,7 +611,7 @@ func doSnapshot(ctx context.Context, volOpt *volumeOptions, subvolumeName, snaps return snap, err } snap.CreationTime = t - err = protectSnapshot(ctx, volOpt, cr, snapID, volID) + err = volOpt.protectSnapshot(ctx, snapID, volID) if err != nil { util.ErrorLog(ctx, "failed to protect snapshot %s %v", snapID, err) } @@ -706,7 +706,7 @@ func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteS return nil, status.Errorf(codes.FailedPrecondition, "snapshot %s has pending clones", snapshotID) } if snapInfo.Protected == snapshotIsProtected { - err = unprotectSnapshot(ctx, volOpt, cr, volumeID(sid.FsSnapshotName), volumeID(sid.FsSubvolName)) + err = volOpt.unprotectSnapshot(ctx, volumeID(sid.FsSnapshotName), volumeID(sid.FsSubvolName)) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/internal/cephfs/errors.go b/internal/cephfs/errors.go index b945969f1..73b86b97f 100644 --- a/internal/cephfs/errors.go +++ b/internal/cephfs/errors.go @@ -27,8 +27,6 @@ const ( // snapNotFound is returned when snap name passed is not found in the list // of snapshots for the given image. snapNotFound = "Error ENOENT" - // snapProtectionExist is returned when the snapshot is already protected - snapProtectionExist = "Error EEXIST" // volumeNotEmpty is returned when the volume is not empty. volumeNotEmpty = "Error ENOTEMPTY" ) diff --git a/internal/cephfs/snapshot.go b/internal/cephfs/snapshot.go index a9c18675a..88cd7790a 100644 --- a/internal/cephfs/snapshot.go +++ b/internal/cephfs/snapshot.go @@ -18,9 +18,11 @@ package cephfs import ( "context" + "errors" "strings" "github.com/ceph/ceph-csi/internal/util" + "github.com/ceph/go-ceph/rados" "github.com/golang/protobuf/ptypes/timestamp" ) @@ -119,75 +121,51 @@ func getSnapshotInfo(ctx context.Context, volOptions *volumeOptions, cr *util.Cr return snap, nil } -func protectSnapshot(ctx context.Context, volOptions *volumeOptions, cr *util.Credentials, snapID, volID volumeID) error { +func (vo *volumeOptions) protectSnapshot(ctx context.Context, snapID, volID volumeID) error { // If "snapshot-autoprotect" feature is present, The ProtectSnapshot // call should be treated as a no-op. - if checkSubvolumeHasFeature(autoProtect, volOptions.Features) { + if checkSubvolumeHasFeature(autoProtect, vo.Features) { return nil } - args := []string{ - "fs", - "subvolume", - "snapshot", - "protect", - volOptions.FsName, - string(volID), - string(snapID), - "--group_name", - volOptions.SubvolumeGroup, - "-m", volOptions.Monitors, - "-c", util.CephConfigPath, - "-n", cephEntityClientPrefix + cr.ID, - "--keyfile=" + cr.KeyFile, + fsa, err := vo.conn.GetFSAdmin() + if err != nil { + util.ErrorLog(ctx, "could not get FSAdmin: %s", err) + return err } - err := execCommandErr( - ctx, - "ceph", - args[:]...) + err = fsa.ProtectSubVolumeSnapshot(vo.FsName, vo.SubvolumeGroup, string(volID), + string(snapID)) if err != nil { - if strings.Contains(err.Error(), snapProtectionExist) { + if errors.Is(err, rados.ErrObjectExists) { return nil } - util.ErrorLog(ctx, "failed to protect subvolume snapshot %s %s(%s) in fs %s", string(snapID), string(volID), err, volOptions.FsName) + util.ErrorLog(ctx, "failed to protect subvolume snapshot %s %s in fs %s with error: %s", string(volID), string(snapID), vo.FsName, err) return err } return nil } -func unprotectSnapshot(ctx context.Context, volOptions *volumeOptions, cr *util.Credentials, snapID, volID volumeID) error { +func (vo *volumeOptions) unprotectSnapshot(ctx context.Context, snapID, volID volumeID) error { // If "snapshot-autoprotect" feature is present, The UnprotectSnapshot // call should be treated as a no-op. - if checkSubvolumeHasFeature(autoProtect, volOptions.Features) { + if checkSubvolumeHasFeature(autoProtect, vo.Features) { return nil } - args := []string{ - "fs", - "subvolume", - "snapshot", - "unprotect", - volOptions.FsName, - string(volID), - string(snapID), - "--group_name", - volOptions.SubvolumeGroup, - "-m", volOptions.Monitors, - "-c", util.CephConfigPath, - "-n", cephEntityClientPrefix + cr.ID, - "--keyfile=" + cr.KeyFile, + fsa, err := vo.conn.GetFSAdmin() + if err != nil { + util.ErrorLog(ctx, "could not get FSAdmin: %s", err) + return err } - err := execCommandErr( - ctx, - "ceph", - args[:]...) + err = fsa.UnprotectSubVolumeSnapshot(vo.FsName, vo.SubvolumeGroup, string(volID), + string(snapID)) if err != nil { // In case the snap is already unprotected we get ErrSnapProtectionExist error code // in that case we are safe and we could discard this error. - if strings.Contains(err.Error(), snapProtectionExist) { + if errors.Is(err, rados.ErrObjectExists) { return nil } - util.ErrorLog(ctx, "failed to unprotect subvolume snapshot %s %s(%s) in fs %s", string(snapID), string(volID), err, volOptions.FsName) + util.ErrorLog(ctx, "failed to unprotect subvolume snapshot %s %s in fs %s with error: %s", string(volID), string(snapID), vo.FsName, err) return err } return nil