mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rbd: add support for flattenMode option for replication
This commit adds support for flattenMode option for replication. If the flattenMode is set to "force" in volumereplicationclass parameters, cephcsi will add a task to flatten the image if it has parent. This enable cephcsi to then mirror such images after flattening them. The error message when the image's parent is in trash or unmirrored is improved as well. Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
@ -74,6 +74,12 @@ const (
|
||||
// (optional) StartTime is the time the snapshot schedule
|
||||
// begins, can be specified using the ISO 8601 time format.
|
||||
schedulingStartTimeKey = "schedulingStartTime"
|
||||
|
||||
// flattenModeKey to get the flattenMode from the parameters.
|
||||
// (optional) flattenMode decides how to handle images with parent.
|
||||
// (default) If set to "never", the image with parent will not be flattened.
|
||||
// If set to "force", the image with parent will be flattened.
|
||||
flattenModeKey = "flattenMode"
|
||||
)
|
||||
|
||||
// ReplicationServer struct of rbd CSI driver with supported methods of Replication
|
||||
@ -115,6 +121,27 @@ func getForceOption(ctx context.Context, parameters map[string]string) (bool, er
|
||||
return force, nil
|
||||
}
|
||||
|
||||
// getFlattenMode gets flatten mode from the input GRPC request parameters.
|
||||
// flattenMode is the key to check the mode in the parameters.
|
||||
func getFlattenMode(ctx context.Context, parameters map[string]string) (corerbd.FlattenMode, error) {
|
||||
val, ok := parameters[flattenModeKey]
|
||||
if !ok {
|
||||
log.DebugLog(ctx, "%q is not set in parameters, setting to default (%v)",
|
||||
flattenModeKey, corerbd.FlattenModeNever)
|
||||
|
||||
return corerbd.FlattenModeNever, nil
|
||||
}
|
||||
|
||||
mode := corerbd.FlattenMode(val)
|
||||
switch mode {
|
||||
case corerbd.FlattenModeForce, corerbd.FlattenModeNever:
|
||||
return mode, nil
|
||||
}
|
||||
log.ErrorLog(ctx, "%q=%q is not supported", flattenModeKey, val)
|
||||
|
||||
return mode, status.Errorf(codes.InvalidArgument, "%q=%q is not supported", flattenModeKey, val)
|
||||
}
|
||||
|
||||
// getMirroringMode gets the mirroring mode from the input GRPC request parameters.
|
||||
// mirroringMode is the key to check the mode in the parameters.
|
||||
func getMirroringMode(ctx context.Context, parameters map[string]string) (librbd.ImageMirrorMode, error) {
|
||||
@ -265,6 +292,11 @@ func (rs *ReplicationServer) EnableVolumeReplication(ctx context.Context,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// extract the flatten mode
|
||||
flattenMode, err := getFlattenMode(ctx, req.GetParameters())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mirroringInfo, err := rbdVol.GetImageMirroringInfo()
|
||||
if err != nil {
|
||||
@ -274,6 +306,12 @@ func (rs *ReplicationServer) EnableVolumeReplication(ctx context.Context,
|
||||
}
|
||||
|
||||
if mirroringInfo.State != librbd.MirrorImageEnabled {
|
||||
err = rbdVol.HandleParentImageExistence(ctx, flattenMode)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, err.Error())
|
||||
|
||||
return nil, getGRPCError(err)
|
||||
}
|
||||
err = rbdVol.EnableImageMirroring(mirroringMode)
|
||||
if err != nil {
|
||||
log.ErrorLog(ctx, err.Error())
|
||||
@ -777,6 +815,7 @@ func getGRPCError(err error) error {
|
||||
|
||||
errorStatusMap := map[error]codes.Code{
|
||||
corerbd.ErrInvalidArgument: codes.InvalidArgument,
|
||||
corerbd.ErrFlattenInProgress: codes.Aborted,
|
||||
corerbd.ErrAborted: codes.Aborted,
|
||||
corerbd.ErrFailedPrecondition: codes.FailedPrecondition,
|
||||
corerbd.ErrUnavailable: codes.Unavailable,
|
||||
|
@ -641,3 +641,69 @@ func Test_timestampFromString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getFlattenMode(t *testing.T) {
|
||||
t.Parallel()
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
parameters map[string]string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want corerbd.FlattenMode
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "flattenMode option not set",
|
||||
args: args{
|
||||
ctx: context.TODO(),
|
||||
parameters: map[string]string{},
|
||||
},
|
||||
want: corerbd.FlattenModeNever,
|
||||
},
|
||||
{
|
||||
name: "flattenMode option set to never",
|
||||
args: args{
|
||||
ctx: context.TODO(),
|
||||
parameters: map[string]string{
|
||||
flattenModeKey: string(corerbd.FlattenModeNever),
|
||||
},
|
||||
},
|
||||
want: corerbd.FlattenModeNever,
|
||||
},
|
||||
{
|
||||
name: "flattenMode option set to force",
|
||||
args: args{
|
||||
ctx: context.TODO(),
|
||||
parameters: map[string]string{
|
||||
flattenModeKey: string(corerbd.FlattenModeForce),
|
||||
},
|
||||
},
|
||||
want: corerbd.FlattenModeForce,
|
||||
},
|
||||
|
||||
{
|
||||
name: "flattenMode option set to invalid value",
|
||||
args: args{
|
||||
ctx: context.TODO(),
|
||||
parameters: map[string]string{
|
||||
flattenModeKey: "invalid123",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := getFlattenMode(tt.args.ctx, tt.args.parameters)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("getFlattenMode() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if !tt.wantErr && !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("getFlattenMode() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user