-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PLAT-14303][dr] Support rollback of switchover operation
Summary: This diff adds the rollback api `POST /customers/:cUUID/tasks/:tUUID/rollback` with empty body. Then it reads the task params associated with task uuid `:tUUID` from the YBA database and creates a task to roll it back. It also adds the rollback button for the task in the UI. This diff specifically utilizes the above api to implement the rollback support for a failed switchover task. During swtichover a new xCluster config in the reverse direction is created and the old xCluster config is deleted. The rollback of a switchover is doable if the previous xCluster config is not yet deleted, otherwise, the user has to retry the failed task. This diff makes sure the right error is shown to the user in this case. Test Plan: - Aborted the switchover task in the middle and called the rollback api on the task and made sure the rollback task is created properly and the DR config end up in the right state after the rollback task finishes. ...TBD more tests... Reviewers: #yba-api-review!, nsingh, cwang, jmak, yshchetinin, nbhatia Reviewed By: cwang Subscribers: yugaware Differential Revision: https://phorge.dev.yugabyte.com/D40514
- Loading branch information
1 parent
c15f41e
commit 3c52b9e
Showing
28 changed files
with
645 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
managed/src/main/java/com/yugabyte/yw/commissioner/tasks/SwitchoverDrConfigRollback.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* | ||
* Copyright 2024 YugaByte, Inc. and Contributors | ||
* | ||
* Licensed under the Polyform Free Trial License 1.0.0 (the "License"); you | ||
* may not use this file except in compliance with the License. You | ||
* may obtain a copy of the License at | ||
* | ||
* http://github.com/YugaByte/yugabyte-db/blob/master/licenses/POLYFORM-FREE-TRIAL-LICENSE-1.0.0.txt | ||
*/ | ||
|
||
package com.yugabyte.yw.commissioner.tasks; | ||
|
||
import com.yugabyte.yw.commissioner.BaseTaskDependencies; | ||
import com.yugabyte.yw.commissioner.ITask.Abortable; | ||
import com.yugabyte.yw.commissioner.ITask.Retryable; | ||
import com.yugabyte.yw.commissioner.UserTaskDetails; | ||
import com.yugabyte.yw.common.DrConfigStates.SourceUniverseState; | ||
import com.yugabyte.yw.common.DrConfigStates.State; | ||
import com.yugabyte.yw.common.DrConfigStates.TargetUniverseState; | ||
import com.yugabyte.yw.common.XClusterUniverseService; | ||
import com.yugabyte.yw.models.Restore; | ||
import com.yugabyte.yw.models.Universe; | ||
import com.yugabyte.yw.models.XClusterConfig; | ||
import com.yugabyte.yw.models.XClusterConfig.ConfigType; | ||
import com.yugabyte.yw.models.XClusterTableConfig; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
import java.util.UUID; | ||
import javax.inject.Inject; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.yb.cdc.CdcConsumer.XClusterRole; | ||
|
||
/** | ||
* Task to perform a roll back a switchover task of the DR config that has failed or aborted. This | ||
* task will make sure the old xCluster config is in Running statue while the new xCluster config is | ||
* deleted. | ||
*/ | ||
@Slf4j | ||
@Retryable | ||
@Abortable | ||
public class SwitchoverDrConfigRollback extends SwitchoverDrConfig { | ||
|
||
@Inject | ||
protected SwitchoverDrConfigRollback( | ||
BaseTaskDependencies baseTaskDependencies, XClusterUniverseService xClusterUniverseService) { | ||
super(baseTaskDependencies, xClusterUniverseService); | ||
} | ||
|
||
@Override | ||
public void run() { | ||
log.info("Running {}", getName()); | ||
|
||
XClusterConfig currentXClusterConfig = taskParams().getOldXClusterConfig(); | ||
XClusterConfig switchoverXClusterConfig = getXClusterConfigFromTaskParams(); | ||
UUID sourceUniverseUUID; | ||
UUID targetUniverseUUID; | ||
if (Objects.nonNull(currentXClusterConfig)) { | ||
sourceUniverseUUID = currentXClusterConfig.getSourceUniverseUUID(); | ||
targetUniverseUUID = currentXClusterConfig.getTargetUniverseUUID(); | ||
} else if (Objects.nonNull(switchoverXClusterConfig)) { | ||
// In switchoverXClusterConfig, the source and target universes are swapped. | ||
sourceUniverseUUID = switchoverXClusterConfig.getTargetUniverseUUID(); | ||
targetUniverseUUID = switchoverXClusterConfig.getSourceUniverseUUID(); | ||
} else { | ||
throw new IllegalStateException("Both old and new xCluster configs are null"); | ||
} | ||
Universe sourceUniverse = Universe.getOrBadRequest(sourceUniverseUUID); | ||
Universe targetUniverse = Universe.getOrBadRequest(targetUniverseUUID); | ||
try { | ||
// Lock the source universe. | ||
lockAndFreezeUniverseForUpdate( | ||
sourceUniverse.getUniverseUUID(), sourceUniverse.getVersion(), null /* Txn callback */); | ||
try { | ||
// Lock the target universe. | ||
lockAndFreezeUniverseForUpdate( | ||
targetUniverse.getUniverseUUID(), targetUniverse.getVersion(), null /* Txn callback */); | ||
|
||
// The previous xCluster config is already in Running state, we only need to delete the new | ||
// switchover xCluster config. | ||
if (Objects.nonNull(switchoverXClusterConfig)) { | ||
createDeleteXClusterConfigSubtasks( | ||
switchoverXClusterConfig, | ||
false /* keepEntry */, | ||
false /* forceDelete */, | ||
false /* deleteSourcePitrConfigs */, | ||
false /* deleteTargetPitrConfigs */); | ||
} | ||
|
||
if (currentXClusterConfig.getType() == ConfigType.Txn) { | ||
// Set the target universe role to Standby. | ||
createChangeXClusterRoleTask( | ||
currentXClusterConfig, | ||
null /* sourceRole */, | ||
XClusterRole.STANDBY /* targetRole */, | ||
false /* ignoreErrors */) | ||
.setSubTaskGroupType(UserTaskDetails.SubTaskGroupType.ConfigureUniverse); | ||
} | ||
|
||
createPromoteSecondaryConfigToMainConfigTask(currentXClusterConfig); | ||
|
||
createSetDrStatesTask( | ||
currentXClusterConfig, | ||
State.Replicating, | ||
SourceUniverseState.ReplicatingData, | ||
TargetUniverseState.ReceivingData, | ||
null /* keyspacePending */) | ||
.setSubTaskGroupType(UserTaskDetails.SubTaskGroupType.ConfigureUniverse); | ||
|
||
createMarkUniverseUpdateSuccessTasks(targetUniverse.getUniverseUUID()) | ||
.setSubTaskGroupType(UserTaskDetails.SubTaskGroupType.ConfigureUniverse); | ||
|
||
createMarkUniverseUpdateSuccessTasks(sourceUniverse.getUniverseUUID()) | ||
.setSubTaskGroupType(UserTaskDetails.SubTaskGroupType.ConfigureUniverse); | ||
|
||
getRunnableTask().runSubTasks(); | ||
} catch (Exception e) { | ||
log.error("{} hit error : {}", getName(), e.getMessage()); | ||
// Set tables in updating status to failed. | ||
Set<String> tablesInPendingStatus = | ||
switchoverXClusterConfig.getTableIdsInStatus( | ||
getTableIds(taskParams().getTableInfoList()), | ||
X_CLUSTER_TABLE_CONFIG_PENDING_STATUS_LIST); | ||
switchoverXClusterConfig.updateStatusForTables( | ||
tablesInPendingStatus, XClusterTableConfig.Status.Failed); | ||
// Set backup and restore status to failed and alter load balanced. | ||
boolean isLoadBalancerAltered = false; | ||
for (Restore restore : restoreList) { | ||
isLoadBalancerAltered = isLoadBalancerAltered || restore.isAlterLoadBalancer(); | ||
} | ||
handleFailedBackupAndRestore( | ||
backupList, restoreList, false /* isAbort */, isLoadBalancerAltered); | ||
throw new RuntimeException(e); | ||
} finally { | ||
// Unlock the target universe. | ||
unlockUniverseForUpdate(targetUniverse.getUniverseUUID()); | ||
} | ||
} finally { | ||
// Unlock the source universe. | ||
unlockUniverseForUpdate(sourceUniverse.getUniverseUUID()); | ||
} | ||
|
||
log.info("Completed {}", getName()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.