rbd: split mirror functions off into rbdMrror type

Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
Niels de Vos 2025-04-15 14:15:53 +02:00 committed by mergify[bot]
parent af4431f60b
commit b0994a5356
3 changed files with 63 additions and 43 deletions

View File

@ -1024,7 +1024,14 @@ func (cs *ControllerServer) DeleteVolume(
func cleanupRBDImage(ctx context.Context, func cleanupRBDImage(ctx context.Context,
rbdVol *rbdVolume, cr *util.Credentials, rbdVol *rbdVolume, cr *util.Credentials,
) (*csi.DeleteVolumeResponse, error) { ) (*csi.DeleteVolumeResponse, error) {
info, err := rbdVol.GetMirroringInfo(ctx) rm, err := rbdVol.ToMirror()
if err != nil {
log.ErrorLog(ctx, err.Error())
return nil, status.Error(codes.Internal, err.Error())
}
info, err := rm.GetMirroringInfo(ctx)
if err != nil { if err != nil {
log.ErrorLog(ctx, err.Error()) log.ErrorLog(ctx, err.Error())
@ -1043,7 +1050,7 @@ func cleanupRBDImage(ctx context.Context,
// the image on all the remote (secondary) clusters will get // the image on all the remote (secondary) clusters will get
// auto-deleted. This helps in garbage collecting the OMAP, PVC and PV // auto-deleted. This helps in garbage collecting the OMAP, PVC and PV
// objects after failback operation. // objects after failback operation.
sts, rErr := rbdVol.GetGlobalMirroringStatus(ctx) sts, rErr := rm.GetGlobalMirroringStatus(ctx)
if rErr != nil { if rErr != nil {
return nil, status.Error(codes.Internal, rErr.Error()) return nil, status.Error(codes.Internal, rErr.Error())
} }

View File

@ -101,7 +101,3 @@ func (rv *rbdVolume) GetVolumeGroupID(ctx context.Context, resolver types.Volume
return resolver.MakeVolumeGroupID(ctx, info.PoolID, info.Name) return resolver.MakeVolumeGroupID(ctx, info.PoolID, info.Name)
} }
func (rv *rbdVolume) ToMirror() (types.Mirror, error) {
return rv, nil
}

View File

@ -66,82 +66,99 @@ func (rv *rbdVolume) HandleParentImageExistence(
if err != nil { if err != nil {
return fmt.Errorf("failed to get parent of image %s: %w", rv, err) return fmt.Errorf("failed to get parent of image %s: %w", rv, err)
} }
parentMirroringInfo, err := parent.GetMirroringInfo(ctx)
pm, err := parent.ToMirror()
if err != nil {
return fmt.Errorf("failed to convert parent image %s to mirror type: %w", parent, err)
}
parentMirroringInfo, err := pm.GetMirroringInfo(ctx)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"failed to get mirroring info of parent %q of image %q: %w", "failed to get mirroring info of parent %q of image %q: %w",
parent, rv, err) pm, rv, err)
} }
if parentMirroringInfo.GetState() != librbd.MirrorImageEnabled.String() { if parentMirroringInfo.GetState() != librbd.MirrorImageEnabled.String() {
return fmt.Errorf("%w: failed to enable mirroring on image %q: "+ return fmt.Errorf("%w: failed to enable mirroring on image %q: "+
"parent image %q is not enabled for mirroring", "parent image %q is not enabled for mirroring",
rbderrors.ErrFailedPrecondition, rv, parent) rbderrors.ErrFailedPrecondition, rv, pm)
} }
return nil return nil
} }
// rbdMirror is an extended rbdImage type that implements the types.Mirror interface.
type rbdMirror struct {
rbdImage
}
// check that rbdVolume implements the types.Mirror interface. // check that rbdVolume implements the types.Mirror interface.
var _ types.Mirror = &rbdVolume{} var _ types.Mirror = &rbdMirror{}
func (ri *rbdImage) ToMirror() (types.Mirror, error) {
return &rbdMirror{
rbdImage: *ri,
}, nil
}
// EnableMirroring enables mirroring on an image. // EnableMirroring enables mirroring on an image.
func (ri *rbdImage) EnableMirroring(_ context.Context, mode librbd.ImageMirrorMode) error { func (rm *rbdMirror) EnableMirroring(_ context.Context, mode librbd.ImageMirrorMode) error {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return fmt.Errorf("failed to open image %q with error: %w", ri, err) return fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
err = image.MirrorEnable(mode) err = image.MirrorEnable(mode)
if err != nil { if err != nil {
return fmt.Errorf("failed to enable mirroring on %q with error: %w", ri, err) return fmt.Errorf("failed to enable mirroring on %q with error: %w", rm, err)
} }
return nil return nil
} }
// DisableMirroring disables mirroring on an image. // DisableMirroring disables mirroring on an image.
func (ri *rbdImage) DisableMirroring(_ context.Context, force bool) error { func (rm *rbdMirror) DisableMirroring(_ context.Context, force bool) error {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return fmt.Errorf("failed to open image %q with error: %w", ri, err) return fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
err = image.MirrorDisable(force) err = image.MirrorDisable(force)
if err != nil { if err != nil {
return fmt.Errorf("failed to disable mirroring on %q with error: %w", ri, err) return fmt.Errorf("failed to disable mirroring on %q with error: %w", rm, err)
} }
return nil return nil
} }
// GetMirroringInfo gets mirroring information of an image. // GetMirroringInfo gets mirroring information of an image.
func (ri *rbdImage) GetMirroringInfo(_ context.Context) (types.MirrorInfo, error) { func (rm *rbdMirror) GetMirroringInfo(_ context.Context) (types.MirrorInfo, error) {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open image %q with error: %w", ri, err) return nil, fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
info, err := image.GetMirrorImageInfo() info, err := image.GetMirrorImageInfo()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get mirroring info of %q with error: %w", ri, err) return nil, fmt.Errorf("failed to get mirroring info of %q with error: %w", rm, err)
} }
return ImageStatus{MirrorImageInfo: info}, nil return ImageStatus{MirrorImageInfo: info}, nil
} }
// Promote promotes image to primary. // Promote promotes image to primary.
func (ri *rbdImage) Promote(_ context.Context, force bool) error { func (rm *rbdMirror) Promote(_ context.Context, force bool) error {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return fmt.Errorf("failed to open image %q with error: %w", ri, err) return fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
err = image.MirrorPromote(force) err = image.MirrorPromote(force)
if err != nil { if err != nil {
return fmt.Errorf("failed to promote image %q with error: %w", ri, err) return fmt.Errorf("failed to promote image %q with error: %w", rm, err)
} }
return nil return nil
@ -150,13 +167,13 @@ func (ri *rbdImage) Promote(_ context.Context, force bool) error {
// ForcePromote promotes image to primary with force option with 2 minutes // ForcePromote promotes image to primary with force option with 2 minutes
// timeout. If there is no response within 2 minutes,the rbd CLI process will be // timeout. If there is no response within 2 minutes,the rbd CLI process will be
// killed and an error is returned. // killed and an error is returned.
func (rv *rbdVolume) ForcePromote(ctx context.Context, cr *util.Credentials) error { func (rm *rbdMirror) ForcePromote(ctx context.Context, cr *util.Credentials) error {
promoteArgs := []string{ promoteArgs := []string{
"mirror", "image", "promote", "mirror", "image", "promote",
rv.String(), rm.String(),
"--force", "--force",
"--id", cr.ID, "--id", cr.ID,
"-m", rv.Monitors, "-m", rm.Monitors,
"--keyfile=" + cr.KeyFile, "--keyfile=" + cr.KeyFile,
} }
_, stderr, err := util.ExecCommandWithTimeout( _, stderr, err := util.ExecCommandWithTimeout(
@ -167,41 +184,41 @@ func (rv *rbdVolume) ForcePromote(ctx context.Context, cr *util.Credentials) err
promoteArgs..., promoteArgs...,
) )
if err != nil { if err != nil {
return fmt.Errorf("failed to promote image %q with error: %w", rv, err) return fmt.Errorf("failed to promote image %q with error: %w", rm, err)
} }
if stderr != "" { if stderr != "" {
return fmt.Errorf("failed to promote image %q with stderror: %s", rv, stderr) return fmt.Errorf("failed to promote image %q with stderror: %s", rm, stderr)
} }
return nil return nil
} }
// Demote demotes image to secondary. // Demote demotes image to secondary.
func (ri *rbdImage) Demote(_ context.Context) error { func (rm *rbdMirror) Demote(_ context.Context) error {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return fmt.Errorf("failed to open image %q with error: %w", ri, err) return fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
err = image.MirrorDemote() err = image.MirrorDemote()
if err != nil { if err != nil {
return fmt.Errorf("failed to demote image %q with error: %w", ri, err) return fmt.Errorf("failed to demote image %q with error: %w", rm, err)
} }
return nil return nil
} }
// Resync resync image to correct the split-brain. // Resync resync image to correct the split-brain.
func (ri *rbdImage) Resync(_ context.Context) error { func (rm *rbdMirror) Resync(_ context.Context) error {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return fmt.Errorf("failed to open image %q with error: %w", ri, err) return fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
err = image.MirrorResync() err = image.MirrorResync()
if err != nil { if err != nil {
return fmt.Errorf("failed to resync image %q with error: %w", ri, err) return fmt.Errorf("failed to resync image %q with error: %w", rm, err)
} }
// If we issued a resync, return a non-final error as image needs to be recreated // If we issued a resync, return a non-final error as image needs to be recreated
@ -211,15 +228,15 @@ func (ri *rbdImage) Resync(_ context.Context) error {
} }
// GetGlobalMirroringStatus get the mirroring status of an image. // GetGlobalMirroringStatus get the mirroring status of an image.
func (ri *rbdImage) GetGlobalMirroringStatus(_ context.Context) (types.GlobalStatus, error) { func (rm *rbdMirror) GetGlobalMirroringStatus(_ context.Context) (types.GlobalStatus, error) {
image, err := ri.open() image, err := rm.open()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open image %q with error: %w", ri, err) return nil, fmt.Errorf("failed to open image %q with error: %w", rm, err)
} }
defer image.Close() defer image.Close()
statusInfo, err := image.GetGlobalMirrorStatus() statusInfo, err := image.GetGlobalMirrorStatus()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get image mirroring status %q with error: %w", ri, err) return nil, fmt.Errorf("failed to get image mirroring status %q with error: %w", rm, err)
} }
return GlobalMirrorStatus{GlobalMirrorImageStatus: statusInfo}, nil return GlobalMirrorStatus{GlobalMirrorImageStatus: statusInfo}, nil