@@ -108,10 +108,35 @@ func (d *DRPCInstance) startProcessing() bool {
108108func (d * DRPCInstance ) processPlacement () (bool , error ) {
109109 d .log .Info ("Process DRPC Placement" , "DRAction" , d .instance .Spec .Action )
110110
111+ // Handle test failover cleanup when switching away from test failover to another action
111112 if d .instance .Spec .Action != rmn .ActionTestFailover {
112113 rmnutil .AddAnnotation (d .instance , "ramendr.openshift.io/last-action" , string (d .instance .Spec .Action ))
114+
115+ // If we're exiting a test failover (were in TestingFailover progression), clean up placement
116+ // decisions that were retained during the test, then requeue for the new action.
117+ if d .instance .Status .Progression == rmn .ProgressionTestingFailover {
118+ for clusterName , vrg := range d .vrgs {
119+ // Find the primary VRG that was used for testing and clean up after it
120+ if isVRGPrimary (vrg ) && vrg .Spec .Action == rmn .VRGActionTestFailover {
121+ // Remove cluster decision that was retained during test failover
122+ if err := d .reconciler .removeClusterDecisionAfterTestFailover (d .ctx , d .userPlacement , clusterName ); err != nil {
123+ return false , err
124+ }
125+
126+ // Reset progression state back to completed for the new action
127+ d .setProgression (rmn .ProgressionCompleted )
128+
129+ // Requeue to process the new action with a clean slate (placement decisions reset)
130+ return false , nil
131+ }
132+ }
133+ }
113134 }
114135
136+ return d .executeAction ()
137+ }
138+
139+ func (d * DRPCInstance ) executeAction () (bool , error ) {
115140 switch d .instance .Spec .Action {
116141 case rmn .ActionFailover :
117142 return d .RunFailover ()
@@ -150,13 +175,7 @@ func (d *DRPCInstance) RunInitialDeployment() (bool, error) {
150175 // Check if we already deployed in the homeCluster or elsewhere
151176 deployed , clusterName := d .isDeployed (homeCluster )
152177 if deployed && clusterName != homeCluster {
153- err := d .ensureVRGManifestWork (clusterName )
154- if err != nil {
155- return ! done , err
156- }
157-
158- // IF deployed on cluster that is not the preferred HomeCluster, then we are done
159- return done , nil
178+ return d .ensureInitialDeployActionCompleted (homeCluster )
160179 }
161180
162181 // Ensure that initial deployment is complete
@@ -398,8 +417,7 @@ func (d *DRPCInstance) RunFailover() (bool, error) {
398417 if d .instance .Spec .Action == rmn .ActionTestFailover {
399418 d .setProgression (rmn .ProgressionTestingFailover )
400419
401- err := d .ensurePlacement (failoverCluster )
402- if err != nil {
420+ if err := d .ensurePlacement (failoverCluster ); err != nil {
403421 return ! done , err
404422 }
405423
@@ -967,6 +985,14 @@ func (d *DRPCInstance) ensureFailoverActionCompleted(srcCluster string) (bool, e
967985 return d .ensureActionCompleted (srcCluster )
968986}
969987
988+ func (d * DRPCInstance ) ensureInitialDeployActionCompleted (srcCluster string ) (bool , error ) {
989+ // This function was added to handle cleanup in case test failover was initiated while VRG was still
990+ // in the initial deployment state. It ensures proper finalization anc cleanup if necessary.
991+ d .setProgression (rmn .ProgressionCleaningUp )
992+
993+ return d .ensureActionCompleted (srcCluster )
994+ }
995+
970996func isDiscoveredApp (drpc * rmn.DRPlacementControl ) bool {
971997 return drpc .Spec .ProtectedNamespaces != nil && len (* drpc .Spec .ProtectedNamespaces ) > 0
972998}
@@ -1150,10 +1176,12 @@ func (d *DRPCInstance) runFinalSync(homeCluster string) (bool, error) {
11501176}
11511177
11521178func (d * DRPCInstance ) areMultipleVRGsPrimary () bool {
1179+ // Count actual primaries, excluding test failover primaries which are temporary and can coexist
1180+ // with the original primary during testing without being considered a conflicting state.
11531181 numOfPrimaries := 0
11541182
11551183 for _ , vrg := range d .vrgs {
1156- if isVRGPrimary (vrg ) {
1184+ if isVRGPrimary (vrg ) && vrg . Spec . Action != rmn . VRGActionTestFailover {
11571185 numOfPrimaries ++
11581186 }
11591187 }
@@ -1927,6 +1955,8 @@ func vrgAction(drpcAction rmn.DRAction) rmn.VRGAction {
19271955 return rmn .VRGActionFailover
19281956 case rmn .ActionRelocate :
19291957 return rmn .VRGActionRelocate
1958+ case rmn .ActionTestFailover :
1959+ return rmn .VRGActionTestFailover
19301960 default :
19311961 return ""
19321962 }
0 commit comments