Search in sources :

Example 11 with Step

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);
        }
    }
}
Also used : Step(com.emc.storageos.workflow.Workflow.Step) HashSet(java.util.HashSet)

Example 12 with Step

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;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) StepStatus(com.emc.storageos.workflow.Workflow.StepStatus) Step(com.emc.storageos.workflow.Workflow.Step) List(java.util.List) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList)

Aggregations

Step (com.emc.storageos.workflow.Workflow.Step)12 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)5 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)5 LockRetryException (com.emc.storageos.locking.LockRetryException)5 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)5 ControllerException (com.emc.storageos.volumecontroller.ControllerException)5 StepStatus (com.emc.storageos.workflow.Workflow.StepStatus)4 HashSet (java.util.HashSet)4 DataObject (com.emc.storageos.db.client.model.DataObject)2 InterProcessLock (org.apache.curator.framework.recipes.locks.InterProcessLock)2 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)1 WorkflowStepData (com.emc.storageos.db.client.model.WorkflowStepData)1 StepState (com.emc.storageos.workflow.Workflow.StepState)1 URI (java.net.URI)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Set (java.util.Set)1 Stat (org.apache.zookeeper.data.Stat)1