use of com.emc.storageos.workflow.Workflow.Step in project coprhd-controller by CoprHD.
the class WorkflowService method removeRollbackSteps.
/**
* Removes all rollback steps from the Workflow. Used in resuming a workflow.
*
* @param workflow
* Workflow
*/
private void removeRollbackSteps(Workflow workflow) {
Set<String> rollbackStepIds = new HashSet<String>();
Map<String, Step> stepMap = workflow.getStepMap();
// Determine rollback steps
for (Step step : stepMap.values()) {
if (step.isRollbackStep) {
rollbackStepIds.add(step.stepId);
if (!NullColumnValueGetter.isNullURI(step.workflowStepURI)) {
// Remove the rollback step from the database
com.emc.storageos.db.client.model.WorkflowStep dbStep = _dbClient.queryObject(com.emc.storageos.db.client.model.WorkflowStep.class, step.workflowStepURI);
if (dbStep != null)
_dbClient.markForDeletion(dbStep);
}
}
}
// Remove each rollback step from StepMap, StepStatusMap, StepGroupMap members
for (String stepId : rollbackStepIds) {
workflow.getStepMap().remove(stepId);
workflow.getStepStatusMap().remove(stepId);
for (String stepGroup : workflow.getStepGroupMap().keySet()) {
workflow.getStepGroupMap().get(stepGroup).remove(stepId);
}
}
}
use of com.emc.storageos.workflow.Workflow.Step in project coprhd-controller by CoprHD.
the class WorkflowService method initiateRollback.
/**
* Initiate a rollback of the entire workflow.
*
* @param workflow
* - The workflow to be rolled back.
* @return true if rollback initiated, false if suspended.
*/
public boolean initiateRollback(Workflow workflow) throws WorkflowException {
// Verify all existing steps are in a terminal state.
Map<String, StepStatus> statusMap = workflow.getAllStepStatus();
for (StepStatus status : statusMap.values()) {
if (false == status.isTerminalState()) {
throw new WorkflowException("Step: " + status.stepId + " is not in a terminal state: " + status.state);
}
}
// Make sure all non-cancelled nodes have a rollback method.
// TODO: handle null rollback methods better.
boolean norollback = false;
for (Step step : workflow.getStepMap().values()) {
// Suspended no error steps have not run, treat them as cancelled
if (step.status.state == StepState.SUSPENDED_NO_ERROR) {
step.status.updateState(StepState.CANCELLED, ServiceCode.WORKFLOW_STEP_CANCELLED, "Step cancelled because rollback was initiated");
persistWorkflowStep(workflow, step);
continue;
}
if (step.status.state != StepState.CANCELLED && step.rollbackMethod == null) {
_log.error(String.format("Cannot rollback step %s because it does not have a rollback method", step.stepId));
norollback = true;
}
}
if (norollback) {
return false;
}
_log.info("Generating rollback steps for workflow: " + workflow.getWorkflowURI());
// Going to try and initiate the rollback.
if (workflow._rollbackHandler != null) {
workflow._rollbackHandler.initiatingRollback(workflow, workflow._rollbackHandlerArgs);
}
// Determine the steps that need to be rolled back.
// Maps step original stepId to rollback Step.
Map<String, Step> rollbackStepMap = new HashMap<String, Step>();
// Contains dependencies for the rollback Steps organized into Step Groups..
Map<String, Set<String>> rollbackStepGroupMap = new HashMap<String, Set<String>>();
// Map of step ids or stepGroups names to execution step ids having a dependence on this step/group
Map<String, List<String>> dependenceMap = new HashMap<String, List<String>>();
for (Step step : workflow.getStepMap().values()) {
// Don't process cancelled nodes, they don't need to be rolled back.
if (step.status.state == StepState.CANCELLED) {
continue;
}
// If we have a dependence, put it in the dependence map
if (step.waitFor != null) {
if (dependenceMap.get(step.waitFor) == null) {
dependenceMap.put(step.waitFor, new ArrayList<String>());
}
// Step is dependent on the indicated waitFor
dependenceMap.get(step.waitFor).add(step.stepId);
}
// Compute the corresponding rollback node.
Step rb = step.generateRollbackStep();
rollbackStepMap.put(step.stepId, rb);
}
// or it can be dependent on the stepGroup containing es1.
for (Step executeStep : workflow.getStepMap().values()) {
if (executeStep.status.state == StepState.CANCELLED) {
continue;
}
Step rollbackStep = rollbackStepMap.get(executeStep.stepId);
String stepGroupKey = "_rollback_" + rollbackStep.stepId;
rollbackStepGroupMap.put(stepGroupKey, new HashSet<String>());
// rollback nodes corresponding to the direct dependents of executeStep
List<String> dependentList = dependenceMap.get(executeStep.stepId);
if (dependentList != null) {
for (String dependentId : dependentList) {
Step dependentRollbackStep = rollbackStepMap.get(dependentId);
if (dependentRollbackStep == null) {
continue;
}
rollbackStepGroupMap.get(stepGroupKey).add(dependentRollbackStep.stepId);
}
}
// rollback nodes corresponding to the dependents in the executeStep's stepGroup
dependentList = dependenceMap.get(executeStep.stepGroup);
if (dependentList != null) {
for (String dependentId : dependentList) {
Step dependentRollbackStep = rollbackStepMap.get(dependentId);
if (dependentRollbackStep == null) {
continue;
}
rollbackStepGroupMap.get(stepGroupKey).add(dependentRollbackStep.stepId);
}
}
// If we have dependencies, then set the waitFor to point to our group.
if (false == rollbackStepGroupMap.get(stepGroupKey).isEmpty()) {
rollbackStep.waitFor = stepGroupKey;
}
}
// Print what is being added.
for (Step step : rollbackStepMap.values()) {
_log.info(String.format("Adding rollback node %s (%s) waitFor: %s", step.stepId, step.description, step.waitFor));
}
for (String key : rollbackStepGroupMap.keySet()) {
_log.info(String.format("Adding group %s members %s", key, rollbackStepGroupMap.get(key)));
}
// Add all the rollback Steps and new dependence Groups
for (Step rollbackStep : rollbackStepMap.values()) {
StepStatus status = new StepStatus();
status.stepId = rollbackStep.stepId;
status.state = StepState.CREATED;
status.description = rollbackStep.description;
rollbackStep.status = status;
workflow.getStepMap().put(rollbackStep.stepId, rollbackStep);
workflow.getStepStatusMap().put(rollbackStep.stepId, status);
}
workflow.getStepGroupMap().putAll(rollbackStepGroupMap);
workflow.setRollbackState(true);
workflow.setWorkflowState(WorkflowState.ROLLING_BACK);
// Persist the workflow since we added the rollback groups
persistWorkflow(workflow);
logWorkflow(workflow, true);
// Now queue all the new steps.
for (Step step : rollbackStepMap.values()) {
queueWorkflowStep(workflow, step);
}
return true;
}
Aggregations