-
Notifications
You must be signed in to change notification settings - Fork 57
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
Delete secondary VRG before primary #1689
base: main
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
|
@@ -119,7 +119,7 @@ func (r *DRPlacementControlReconciler) SetupWithManager(mgr ctrl.Manager) error | |
// For more details, check Reconcile and its Result here: | ||
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile | ||
// | ||
//nolint:funlen,gocognit,gocyclo,cyclop | ||
//nolint:funlen,gocognit,gocyclo,cyclop,nestif | ||
func (r *DRPlacementControlReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { | ||
logger := r.Log.WithValues("DRPC", req.NamespacedName, "rid", uuid.New()) | ||
|
||
|
@@ -166,13 +166,21 @@ func (r *DRPlacementControlReconciler) Reconcile(ctx context.Context, req ctrl.R | |
// then the DRPC should be deleted as well. The least we should do here is to clean up DPRC. | ||
err := r.processDeletion(ctx, drpc, placementObj, logger) | ||
if err != nil { | ||
logger.Info(fmt.Sprintf("Error in deleting DRPC: (%v)", err)) | ||
|
||
statusErr := r.setDeletionStatusAndUpdate(ctx, drpc) | ||
if statusErr != nil { | ||
err = fmt.Errorf("drpc deletion failed: %w and status update failed: %w", err, statusErr) | ||
|
||
return ctrl.Result{}, err | ||
} | ||
|
||
// Is this an expected condition? | ||
if rmnutil.IsOperationInProgress(err) { | ||
logger.Info("Deleting DRPC in progress", "reason", err) | ||
|
||
return ctrl.Result{Requeue: true}, nil | ||
} | ||
|
||
// Unexpected error. | ||
return ctrl.Result{}, err | ||
} | ||
|
||
|
@@ -724,19 +732,19 @@ func (r *DRPlacementControlReconciler) cleanupVRGs( | |
return fmt.Errorf("failed to retrieve VRGs. We'll retry later. Error (%w)", err) | ||
} | ||
|
||
if !ensureVRGsManagedByDRPC(r.Log, mwu, vrgs, drpc, vrgNamespace) { | ||
return fmt.Errorf("VRG adoption in progress") | ||
// We have to ensure the seconrary VRG is deleted before deleting the primary VRG. This will fail until there | ||
// is no secondary VRG in the vrgs list. | ||
if err := r.ensureVRGsDeleted(mwu, vrgs, drpc, vrgNamespace, rmn.Secondary); err != nil { | ||
return err | ||
} | ||
|
||
// delete VRG manifestwork | ||
for _, drClusterName := range rmnutil.DRPolicyClusterNames(drPolicy) { | ||
if err := mwu.DeleteManifestWork(mwu.BuildManifestWorkName(rmnutil.MWTypeVRG), drClusterName); err != nil { | ||
return fmt.Errorf("%w", err) | ||
} | ||
// This will fail until there is no primary VRG in the vrgs list. | ||
if err := r.ensureVRGsDeleted(mwu, vrgs, drpc, vrgNamespace, rmn.Primary); err != nil { | ||
return err | ||
} | ||
|
||
if len(vrgs) != 0 { | ||
return fmt.Errorf("waiting for VRGs count to go to zero") | ||
return rmnutil.OperationInProgress("waiting for VRGs count to go to zero") | ||
} | ||
|
||
// delete MCVs | ||
|
@@ -747,6 +755,38 @@ func (r *DRPlacementControlReconciler) cleanupVRGs( | |
return nil | ||
} | ||
|
||
// ensureVRGsDeleted ensure that seconrary or primary VRGs are deleted. Return an error if a vrg could not be deleted, | ||
// or deletion is in progress. Return nil if vrg of specified type was not found. | ||
func (r *DRPlacementControlReconciler) ensureVRGsDeleted( | ||
mwu rmnutil.MWUtil, | ||
vrgs map[string]*rmn.VolumeReplicationGroup, | ||
drpc *rmn.DRPlacementControl, | ||
vrgNamespace string, | ||
replicationState rmn.ReplicationState, | ||
) error { | ||
var inProgress bool | ||
|
||
for cluster, vrg := range vrgs { | ||
if vrg.Spec.ReplicationState == replicationState { | ||
if !ensureVRGsManagedByDRPC(r.Log, mwu, vrgs, drpc, vrgNamespace) { | ||
return rmnutil.OperationInProgress(fmt.Sprintf("%s VRG adoption in progress", replicationState)) | ||
} | ||
|
||
if err := mwu.DeleteManifestWork(mwu.BuildManifestWorkName(rmnutil.MWTypeVRG), cluster); err != nil { | ||
return fmt.Errorf("failed to delete %s VRG manifestwork for cluster %q: %w", replicationState, cluster, err) | ||
} | ||
|
||
inProgress = true | ||
} | ||
} | ||
|
||
if inProgress { | ||
return rmnutil.OperationInProgress(fmt.Sprintf("%s VRG manifestwork deletion in progress", replicationState)) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (r *DRPlacementControlReconciler) deleteAllManagedClusterViews( | ||
drpc *rmn.DRPlacementControl, clusterNames []string, | ||
) error { | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// SPDX-FileCopyrightText: The RamenDR authors | ||
// SPDX-License-Identifier: Apache-2.0package util | ||
|
||
package util | ||
|
||
import "errors" | ||
|
||
// OperationInProgress error is return when an operation is in progress and we wait for the desired state. The error | ||
// string should describe the operation for logging the error. | ||
type OperationInProgress string | ||
|
||
func (e OperationInProgress) Error() string { return string(e) } | ||
|
||
// Called by errors.Is() to match target. | ||
func (OperationInProgress) Is(target error) bool { | ||
_, ok := target.(OperationInProgress) | ||
|
||
return ok | ||
} | ||
|
||
// IsOperationInProgress returns true if err or error wrapped by it is an OperationInProgress error. | ||
func IsOperationInProgress(err error) bool { | ||
return errors.Is(err, OperationInProgress("")) | ||
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. One question though, is this call going to propagate back to line 15? I doubt it. errors.Is(...) is a free function. 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, see errors.Is() implementation: 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. I think it does here:
All good |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// SPDX-FileCopyrightText: The RamenDR authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package util_test | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
"github.com/ramendr/ramen/internal/controller/util" | ||
) | ||
|
||
var _ = Describe("OperationInProgress", func() { | ||
Context("comparing errors", func() { | ||
err := util.OperationInProgress("this operation") | ||
|
||
It("is not equal", func() { | ||
Expect(err == util.OperationInProgress("other operation")).To(Equal(false)) | ||
}) | ||
It("match error", func() { | ||
Expect(util.IsOperationInProgress(err)).To(Equal(true)) | ||
}) | ||
It("match wrapped error", func() { | ||
wrapped := fmt.Errorf("wrapping operation in progress: %w", err) | ||
Expect(util.IsOperationInProgress(wrapped)).To(Equal(true)) | ||
}) | ||
It("does not match other errors", func() { | ||
Expect(util.IsOperationInProgress(errors.New("other error"))).To(Equal(false)) | ||
}) | ||
}) | ||
}) |
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.
I mean just let this be returned and remove the block starting from line 189 to 195 inclusive.
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 result will be ERROR log with a stacktrace - we see 18 of these for every delete operation. Since this is an expected condition, it is wrong to treat this as an error.
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.
Same as my comment above