-
Notifications
You must be signed in to change notification settings - Fork 555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RBD: Flatten group snapshot #4973
Changes from all commits
fc07198
897722e
a81887d
2597e45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,8 @@ import ( | |
// group snapshot and remove all images from the group again. This leaves the | ||
// group and its snapshot around, the group snapshot can be inspected to list | ||
// the snapshots of the images. | ||
// | ||
//nolint:gocyclo,cyclop // TODO: reduce complexity. | ||
func (cs *ControllerServer) CreateVolumeGroupSnapshot( | ||
ctx context.Context, | ||
req *csi.CreateVolumeGroupSnapshotRequest, | ||
|
@@ -130,6 +132,27 @@ func (cs *ControllerServer) CreateVolumeGroupSnapshot( | |
"failed to get existing one with name %q: %v", vgsName, err) | ||
} | ||
|
||
creds, err := util.NewUserCredentials(req.GetSecrets()) | ||
if err != nil { | ||
return nil, status.Error(codes.Internal, err.Error()) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
defer creds.DeleteCredentials() | ||
|
||
errList := make([]error, 0) | ||
for _, volume := range volumes { | ||
err = volume.PrepareVolumeForSnapshot(ctx, creds) | ||
if err != nil { | ||
errList = append(errList, err) | ||
} | ||
} | ||
if len(errList) > 0 { | ||
// FIXME: we should probably choose a error code that has more priority. | ||
return nil, status.Errorf( | ||
Madhu-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
status.Code(errList[0]), | ||
"failed to prepare volumes for snapshot: %v", | ||
errList) | ||
} | ||
|
||
// create a temporary VolumeGroup with a different name | ||
vg, err = mgr.CreateVolumeGroup(ctx, vgName) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -785,13 +785,9 @@ func (ri *rbdImage) getCloneDepth(ctx context.Context) (uint, error) { | |||||
} | ||||||
} | ||||||
|
||||||
type trashSnapInfo struct { | ||||||
origSnapName string | ||||||
} | ||||||
|
||||||
func flattenClonedRbdImages( | ||||||
ctx context.Context, | ||||||
snaps []librbd.SnapInfo, | ||||||
children []string, | ||||||
pool, monitors, rbdImageName string, | ||||||
cr *util.Credentials, | ||||||
) error { | ||||||
|
@@ -807,26 +803,9 @@ func flattenClonedRbdImages( | |||||
|
||||||
return err | ||||||
} | ||||||
var origNameList []trashSnapInfo | ||||||
for _, snapInfo := range snaps { | ||||||
// check if the snapshot belongs to trash namespace. | ||||||
isTrash, retErr := rv.isTrashSnap(snapInfo.Id) | ||||||
if retErr != nil { | ||||||
return retErr | ||||||
} | ||||||
|
||||||
if isTrash { | ||||||
// get original snap name for the snapshot in trash namespace | ||||||
origSnapName, retErr := rv.getOrigSnapName(snapInfo.Id) | ||||||
if retErr != nil { | ||||||
return retErr | ||||||
} | ||||||
origNameList = append(origNameList, trashSnapInfo{origSnapName}) | ||||||
} | ||||||
} | ||||||
|
||||||
for _, snapName := range origNameList { | ||||||
rv.RbdImageName = snapName.origSnapName | ||||||
for _, childName := range children { | ||||||
rv.RbdImageName = childName | ||||||
err = rv.flattenRbdImage(ctx, true, rbdHardMaxCloneDepth, rbdSoftMaxCloneDepth) | ||||||
if err != nil { | ||||||
log.ErrorLog(ctx, "failed to flatten %s; err %v", rv, err) | ||||||
|
@@ -2052,57 +2031,26 @@ func (ri *rbdImage) DisableDeepFlatten() error { | |||||
return image.UpdateFeatures(librbd.FeatureDeepFlatten, false) | ||||||
} | ||||||
|
||||||
func (ri *rbdImage) listSnapshots() ([]librbd.SnapInfo, error) { | ||||||
// listSnapAndChildren returns list of names of snapshots and child images. | ||||||
func (ri *rbdImage) listSnapAndChildren() ([]librbd.SnapInfo, []string, error) { | ||||||
image, err := ri.open() | ||||||
if err != nil { | ||||||
return nil, err | ||||||
return nil, nil, err | ||||||
} | ||||||
defer image.Close() | ||||||
|
||||||
snapInfoList, err := image.GetSnapshotNames() | ||||||
if err != nil { | ||||||
return nil, err | ||||||
} | ||||||
|
||||||
return snapInfoList, nil | ||||||
} | ||||||
|
||||||
// isTrashSnap returns true if the snapshot belongs to trash namespace. | ||||||
func (ri *rbdImage) isTrashSnap(snapID uint64) (bool, error) { | ||||||
image, err := ri.open() | ||||||
if err != nil { | ||||||
return false, err | ||||||
} | ||||||
defer image.Close() | ||||||
|
||||||
// Get namespace type for the snapshot | ||||||
nsType, err := image.GetSnapNamespaceType(snapID) | ||||||
if err != nil { | ||||||
return false, err | ||||||
} | ||||||
|
||||||
if nsType == librbd.SnapNamespaceTypeTrash { | ||||||
return true, nil | ||||||
} | ||||||
|
||||||
return false, nil | ||||||
} | ||||||
|
||||||
// getOrigSnapName returns the original snap name for | ||||||
// the snapshots in Trash Namespace. | ||||||
func (ri *rbdImage) getOrigSnapName(snapID uint64) (string, error) { | ||||||
image, err := ri.open() | ||||||
snaps, err := image.GetSnapshotNames() | ||||||
if err != nil { | ||||||
return "", err | ||||||
return nil, nil, err | ||||||
} | ||||||
defer image.Close() | ||||||
|
||||||
origSnapName, err := image.GetSnapTrashNamespace(snapID) | ||||||
// ListChildren() returns pools, images, err. | ||||||
_, children, err := image.ListChildren() | ||||||
if err != nil { | ||||||
return "", err | ||||||
return nil, nil, err | ||||||
} | ||||||
|
||||||
return origSnapName, nil | ||||||
return snaps, children, nil | ||||||
} | ||||||
|
||||||
func (ri *rbdImage) isCompatibleEncryption(dst *rbdImage) error { | ||||||
|
@@ -2277,3 +2225,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 { | ||||||
Madhu-1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
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.flattenParent(ctx, hardLimit, softLimit) | ||||||
if err != nil { | ||||||
return getGRPCErrorForCreateVolume(err) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why its returning GRPC error that to for CreateVolume? ideally internal functions are expected to return plain error message and the caller should pick the right GRPC message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ceph-csi/internal/rbd/controllerserver.go Line 301 in a32ba13
It's used in the same form at multiple places. ceph-csi/internal/rbd/controllerserver.go Line 575 in a32ba13
Let's handle it separately |
||||||
} | ||||||
|
||||||
return nil | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -276,6 +276,10 @@ func (rv *rbdVolume) NewSnapshotByID( | |
return nil, err | ||
} | ||
|
||
// set the features for the clone image. | ||
f := []string{librbd.FeatureNameLayering, librbd.FeatureNameDeepFlatten} | ||
rv.ImageFeatureSet = librbd.FeatureSetFromNames(f) | ||
Comment on lines
+280
to
+281
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dont we need to use the image features present on the parent rbd image? what is the specific reason for this change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
deep-flatten feature is not present on the parent image. We can make this change for volgroupSnapshot as well when we are dealing with #4936 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Why? If it's because it's not enabled by default (i.e. it's not set in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes 😓 , Its bit of extensive change. We'll do it through #4936. |
||
|
||
options, err := rv.constructImageOptions(ctx) | ||
if err != nil { | ||
return nil, err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The recent changes addresses this edge case @iPraveenParihar pointed out.
Added comments to better explain the scenario as well.