diff --git a/internal/rbd/controllerserver.go b/internal/rbd/controllerserver.go index 3ec067c3ecf..6709765fa27 100644 --- a/internal/rbd/controllerserver.go +++ b/internal/rbd/controllerserver.go @@ -1157,7 +1157,7 @@ func (cs *ControllerServer) CreateSnapshot( return cloneFromSnapshot(ctx, rbdVol, rbdSnap, cr, req.GetParameters()) } - err = flattenTemporaryClonedImages(ctx, rbdVol, cr) + err = rbdVol.PrepareVolumeForSnapshot(ctx, cr) if err != nil { return nil, err } @@ -1376,11 +1376,6 @@ func (cs *ControllerServer) doSnapshotClone( return cloneRbd, err } - err = cloneRbd.flattenRbdImage(ctx, false, rbdHardMaxCloneDepth, rbdSoftMaxCloneDepth) - if err != nil { - return cloneRbd, err - } - return cloneRbd, nil } diff --git a/internal/rbd/group_controllerserver.go b/internal/rbd/group_controllerserver.go index 4e4d3c408bc..d3ee55a45d5 100644 --- a/internal/rbd/group_controllerserver.go +++ b/internal/rbd/group_controllerserver.go @@ -130,6 +130,17 @@ func (cs *ControllerServer) CreateVolumeGroupSnapshot( "failed to get existing one with name %q: %v", vgsName, err) } + creds, err := mgr.GetCredentials() + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + for _, volume := range volumes { + err = volume.PrepareVolumeForSnapshot(ctx, &creds) + if err != nil { + return nil, status.Error(codes.Aborted, err.Error()) + } + } + // create a temporary VolumeGroup with a different name vg, err = mgr.CreateVolumeGroup(ctx, vgName) if err != nil { diff --git a/internal/rbd/manager.go b/internal/rbd/manager.go index 8b0d6a06448..dcbcaad1004 100644 --- a/internal/rbd/manager.go +++ b/internal/rbd/manager.go @@ -66,8 +66,8 @@ func (mgr *rbdManager) Destroy(ctx context.Context) { } } -// getCredentials sets up credentials and connects to the journal. -func (mgr *rbdManager) getCredentials() (*util.Credentials, error) { +// GetCredentials sets up credentials and connects to the journal. +func (mgr *rbdManager) GetCredentials() (*util.Credentials, error) { if mgr.creds != nil { return mgr.creds, nil } @@ -87,7 +87,7 @@ func (mgr *rbdManager) getVolumeGroupJournal(clusterID string) (journal.VolumeGr return mgr.vgJournal, nil } - creds, err := mgr.getCredentials() + creds, err := mgr.GetCredentials() if err != nil { return nil, err } @@ -166,7 +166,7 @@ func (mgr *rbdManager) getGroupUUID( } func (mgr *rbdManager) GetVolumeByID(ctx context.Context, id string) (types.Volume, error) { - creds, err := mgr.getCredentials() + creds, err := mgr.GetCredentials() if err != nil { return nil, err } @@ -191,7 +191,7 @@ func (mgr *rbdManager) GetVolumeByID(ctx context.Context, id string) (types.Volu } func (mgr *rbdManager) GetSnapshotByID(ctx context.Context, id string) (types.Snapshot, error) { - creds, err := mgr.getCredentials() + creds, err := mgr.GetCredentials() if err != nil { return nil, err } @@ -216,7 +216,7 @@ func (mgr *rbdManager) GetSnapshotByID(ctx context.Context, id string) (types.Sn } func (mgr *rbdManager) GetVolumeGroupByID(ctx context.Context, id string) (types.VolumeGroup, error) { - creds, err := mgr.getCredentials() + creds, err := mgr.GetCredentials() if err != nil { return nil, err } @@ -230,7 +230,7 @@ func (mgr *rbdManager) GetVolumeGroupByID(ctx context.Context, id string) (types } func (mgr *rbdManager) CreateVolumeGroup(ctx context.Context, name string) (types.VolumeGroup, error) { - creds, err := mgr.getCredentials() + creds, err := mgr.GetCredentials() if err != nil { return nil, err } @@ -324,7 +324,7 @@ func (mgr *rbdManager) GetVolumeGroupSnapshotByID( ctx context.Context, id string, ) (types.VolumeGroupSnapshot, error) { - creds, err := mgr.getCredentials() + creds, err := mgr.GetCredentials() if err != nil { return nil, err } diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index fbae7f4181d..1fb5b77d06a 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -2273,3 +2273,28 @@ func (ri *rbdImage) GetClusterID(ctx context.Context) (string, error) { return ri.ClusterID, nil } + +func (rv *rbdVolume) PrepareVolumeForSnapshot(ctx context.Context, cr *util.Credentials) error { + hardLimit := rbdHardMaxCloneDepth + softLimit := rbdSoftMaxCloneDepth + err := flattenTemporaryClonedImages(ctx, rv, cr) + if err != nil { + return err + } + + // choosing 2, since snapshot adds one depth and we'll be flattening the parent. + const depthToAvoidFlatten = 2 + if rbdHardMaxCloneDepth > depthToAvoidFlatten { + hardLimit = rbdHardMaxCloneDepth - depthToAvoidFlatten + } + if rbdSoftMaxCloneDepth > depthToAvoidFlatten { + softLimit = rbdSoftMaxCloneDepth - depthToAvoidFlatten + } + + err = rv.flattenParentImage(ctx, hardLimit, softLimit) + if err != nil { + return getGRPCErrorForCreateVolume(err) + } + + return nil +} diff --git a/internal/rbd/types/manager.go b/internal/rbd/types/manager.go index 273bd58109f..145cd54ead9 100644 --- a/internal/rbd/types/manager.go +++ b/internal/rbd/types/manager.go @@ -18,6 +18,8 @@ package types import ( "context" + + "github.com/ceph/ceph-csi/internal/util" ) // VolumeResolver can be used to construct a Volume from a CSI VolumeId. @@ -45,6 +47,9 @@ type Manager interface { // Destroy frees all resources that the Manager allocated. Destroy(ctx context.Context) + // Getcredentials sets up credentials and connects to the journal. + GetCredentials() (util.Credentials, error) + // GetVolumeGroupByID uses the CSI-Addons VolumeGroupId to resolve the // returned VolumeGroup. GetVolumeGroupByID(ctx context.Context, id string) (VolumeGroup, error) diff --git a/internal/rbd/types/volume.go b/internal/rbd/types/volume.go index 1f235bf16ba..a8b390b622a 100644 --- a/internal/rbd/types/volume.go +++ b/internal/rbd/types/volume.go @@ -58,6 +58,10 @@ type Volume interface { // if the parent image is in trash, it returns an error. // if the parent image exists and is not enabled for mirroring, it returns an error. HandleParentImageExistence(ctx context.Context, flattenMode FlattenMode) error + // PrepareVolumeForSnapshot prepares the volume for snapshot by + // checking snapshots limit and clone depth limit and flattening it + // if required. + PrepareVolumeForSnapshot(ctx context.Context, cr *util.Credentials) error // ToMirror converts the Volume to a Mirror. ToMirror() (Mirror, error)