Search in sources :

Example 26 with InterProcessLock

use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.

the class WorkflowService method associateToParentWorkflow.

/**
 * Associates workflow to a parent (outer) workflow (if any), i.e.
 * this Workflow is nested within the outer one.
 * Depends on the Workflow's orchestration task id being a step in the outer workflow.
 *
 * @param workflow
 *            -- potential nested Workflow
 * @return true if a parent association was made.
 */
private boolean associateToParentWorkflow(Workflow workflow) {
    try {
        String parentPath = getZKStep2WorkflowPath(workflow.getOrchTaskId());
        if (_dataManager.checkExists(parentPath) != null) {
            // Record our workflow URI as a child in the parent Workflow URI.
            // Get the parent workflow path from ZK
            parentPath = (String) _dataManager.getData(parentPath, false);
            // Load the Workflow state from ZK
            if (parentPath != null) {
                InterProcessLock parentLock = null;
                Workflow parentWorkflow = (Workflow) _dataManager.getData(parentPath, false);
                try {
                    parentLock = lockWorkflow(parentWorkflow);
                    parentWorkflow = (Workflow) _dataManager.getData(parentPath, false);
                    parentWorkflow._childWorkflows.add(workflow.getWorkflowURI());
                    persistWorkflow(parentWorkflow);
                } finally {
                    unlockWorkflow(parentWorkflow, parentLock);
                }
            }
            return true;
        }
    } catch (Exception ex) {
        _log.error(ex.getMessage(), ex);
    }
    return false;
}
Also used : InterProcessLock(org.apache.curator.framework.recipes.locks.InterProcessLock) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) LockRetryException(com.emc.storageos.locking.LockRetryException)

Example 27 with InterProcessLock

use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.

the class WorkflowService method executePlan.

/**
 * Execute the workflow. It is saved here and control is passed to WorkflowExecutor.
 *
 * @param workflow
 */
public void executePlan(Workflow workflow) throws WorkflowException {
    InterProcessLock lock = null;
    try {
        if (!workflow.getStepMap().isEmpty()) {
            _log.info("Executing workflow plan: " + workflow.getWorkflowURI() + " " + workflow.getOrchTaskId());
            workflow.setWorkflowState(WorkflowState.RUNNING);
            // Mark steps that should be suspended in the workflow for later.
            suspendStepsMatchingProperty(workflow);
            // Make sure parent/child relationship is refreshed in case child workflow was created
            // before parent was executed
            workflow._nested = associateToParentWorkflow(workflow);
            persistWorkflow(workflow);
            for (Step step : workflow.getStepMap().values()) {
                persistWorkflowStep(workflow, step);
            }
            // Check suspended state and modify states
            if (checkSuspendedSteps(workflow)) {
                _log.info("Workflow is suspended: " + workflow.getWorkflowURI());
                // release any workflow locks
                for (Step step : workflow.getStepMap().values()) {
                    if (step.status.state == StepState.SUSPENDED_NO_ERROR) {
                        completerStepSuspendedNoError(step.stepId);
                    }
                }
            } else {
                /**
                 * Lock the workflow.
                 */
                lock = lockWorkflow(workflow);
                /**
                 * Queue any steps that have not been queued.
                 */
                for (Step step : workflow.getStepMap().values()) {
                    if (step.status.state == StepState.CREATED) {
                        queueWorkflowStep(workflow, step);
                    }
                }
            }
        } else {
            _log.info("Workflow executed with no steps: " + workflow.getWorkflowURI());
            // release any workflow locks
            releaseAllWorkflowLocks(workflow);
            // If no steps are to process, then just exit properly
            if (workflow._taskCompleter != null) {
                workflow._taskCompleter.ready(_dbClient);
            }
        }
    } finally {
        unlockWorkflow(workflow, lock);
    }
}
Also used : InterProcessLock(org.apache.curator.framework.recipes.locks.InterProcessLock) Step(com.emc.storageos.workflow.Workflow.Step)

Example 28 with InterProcessLock

use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.

the class WorkflowService method rollbackWorkflow.

/**
 * Roll back the workflow
 *
 * @param uri
 *            - The workflow URI
 */
private void rollbackWorkflow(URI uri) {
    _log.info(String.format("Rollback requested workflow: %s", uri));
    Workflow workflow = loadWorkflowFromUri(uri);
    if (workflow == null) {
        throw WorkflowException.exceptions.workflowNotFound(uri.toString());
    }
    if (workflow.getWorkflowURI() == null) {
        workflow.setWorkflowURI(uri);
        logWorkflow(workflow, false);
        persistWorkflow(workflow);
    }
    removeRollbackSteps(workflow);
    // See if there are child Workflows that need to be rolled back.
    // These are roll-backed first.
    Map<String, com.emc.storageos.db.client.model.Workflow> childWFMap = getChildWorkflowsMap(workflow);
    for (Entry<String, com.emc.storageos.db.client.model.Workflow> entry : childWFMap.entrySet()) {
        String parentStepId = entry.getKey();
        Workflow child = loadWorkflowFromUri(entry.getValue().getId());
        WorkflowState state = child.getWorkflowState();
        switch(state) {
            case SUSPENDED_ERROR:
            case SUSPENDED_NO_ERROR:
                _dbClient.pending(com.emc.storageos.db.client.model.Workflow.class, child.getWorkflowURI(), parentStepId, "rolling back sub-workflow");
                rollbackWorkflow(child.getWorkflowURI());
                Status status = waitOnOperationComplete(com.emc.storageos.db.client.model.Workflow.class, child.getWorkflowURI(), parentStepId);
                _log.info(String.format("Child rollback task %s completed with state %s", child.getWorkflowURI(), status.name()));
                break;
            default:
                continue;
        }
    }
    // Now try to start rollback of top level Workflow
    _dbClient.pending(com.emc.storageos.db.client.model.Workflow.class, uri, workflow.getOrchTaskId(), "rolling back top-level-workflow");
    InterProcessLock workflowLock = null;
    try {
        workflowLock = lockWorkflow(workflow);
        workflow.setRollingBackFromSuspend(true);
        boolean rollBackStarted = initiateRollback(workflow);
        if (rollBackStarted) {
            _log.info(String.format("Rollback initiated workflow %s", uri));
        } else {
            // We were unable to initiate rollback, probably because there is no rollback handler somehwere
            // Initiate end processing on the workflow, which will release the workflowLock.
            doWorkflowEndProcessing(workflow, false, workflowLock);
            workflowLock = null;
        }
    } finally {
        unlockWorkflow(workflow, workflowLock);
    }
}
Also used : StepStatus(com.emc.storageos.workflow.Workflow.StepStatus) Status(com.emc.storageos.db.client.model.Operation.Status) InterProcessLock(org.apache.curator.framework.recipes.locks.InterProcessLock)

Example 29 with InterProcessLock

use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.

the class WorkflowService method updateStepStatus.

/**
 * Given a ZK path to a Callback node, get the data which is a StatusUpdateMessage
 * and update the appropriate step status.
 *
 * @param stepId
 *            -- The Step Id of the step.
 * @param state
 * @param code
 * @param message
 * @param automaticRollback
 *            whether to rollback in case of error at the end of workflow
 * @throws WorkflowException
 */
private void updateStepStatus(String stepId, StepState state, ServiceCode code, String message, boolean automaticRollback) throws WorkflowException {
    // String path = getZKCallbackPath(stepId);
    String workflowPath = getZKStep2WorkflowPath(stepId);
    Workflow workflow = null;
    boolean workflowDeleted = false;
    InterProcessLock lock = null;
    try {
        // Get the workflow path from ZK
        workflowPath = (String) _dataManager.getData(workflowPath, false);
        // It is not an error to try and update using a non-existent stepId
        if (workflowPath == null) {
            return;
        }
        // Load the Workflow state from ZK
        workflow = (Workflow) _dataManager.getData(workflowPath, false);
        if (workflow == null) {
            WorkflowException ex = WorkflowException.exceptions.workflowNotFound(workflowPath);
            _log.info("Workflow not found: " + workflowPath, ex);
            throw ex;
        }
        // Lock the Workflow
        lock = lockWorkflow(workflow);
        // Load the entire workflow state including the steps
        workflow = loadWorkflow(workflow);
        if (workflow == null) {
            WorkflowException ex = WorkflowException.exceptions.workflowNotFound(workflowPath);
            _log.info("Workflow not found: " + workflowPath, ex);
            throw ex;
        }
        synchronized (workflow) {
            // Update the StepState structure
            StepStatus status = workflow.getStepStatus(stepId);
            // something else. There is an exception as WorkflowService calls this for SUSPENDED_NO_ERROR.
            if (status.isTerminalState() && !(status.state == StepState.SUSPENDED_NO_ERROR || status.state == StepState.CANCELLED)) {
                WorkflowException ex = WorkflowException.exceptions.workflowStepInTerminalState(stepId, status.state.name(), state.name());
                _log.error(String.format("Step %s is already in terminal state %s, trying to change to %s which will be ignored", stepId, status.state.toString(), state.toString()), ex);
                // are called out of a completer called from the WorkflowService.doWorkflowEndProcessing
                return;
            }
            // If an error is reported, and we're supposed to suspend on error, suspend
            // Don't put a workflow in suspended state if we're already in rollback.
            Step step = workflow.getStepMap().get(stepId);
            if (StepState.ERROR == state && workflow.isSuspendOnError() && !step.isRollbackStep()) {
                state = StepState.SUSPENDED_ERROR;
                step.suspendStep = false;
            }
            // SUSPENDED_ERROR step to ERROR
            if (step.isRollbackStep()) {
                if (step.foundingStepId != null) {
                    if (workflow.getStepMap().get(step.foundingStepId) != null) {
                        Step foundingStep = workflow.getStepMap().get(step.foundingStepId);
                        StepStatus foundingStatus = workflow.getStepStatus(step.foundingStepId);
                        if (StepState.SUSPENDED_ERROR.equals(foundingStatus.state)) {
                            foundingStatus.updateState(StepState.ERROR, code, message);
                            persistWorkflowStep(workflow, foundingStep);
                        }
                    }
                }
            }
            _log.info(String.format("Updating workflow step: %s state %s : %s", stepId, state, message));
            status.updateState(state, code, message);
            // Persist the updated step state
            persistWorkflowStep(workflow, step);
            // to initiate a totally separate rollback.
            try {
                if (workflow.allStatesTerminal() && !workflow.isRollbackState() && (workflow._childWorkflows == null || workflow._childWorkflows.isEmpty())) {
                    InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_004);
                }
            } catch (NullPointerException npe) {
                // Overwrite the status of the final state
                _log.error("Overwriting the state of the final step of a workflow due to artificial failure request", npe);
                StepStatus ss = workflow.getStepStatus(stepId);
                ss.state = StepState.ERROR;
                ss.description = "Artificially thrown exception: " + InvokeTestFailure.ARTIFICIAL_FAILURE_004;
                ss.message = "The final step in the workflow was successful, but an artificial failure request is configured to fail the final step to invoke full rollback.";
                workflow.getStepStatusMap().put(stepId, ss);
                _log.info(String.format("Updating workflow step: %s state %s : %s", stepId, state, ss.message));
                WorkflowException ex = WorkflowException.exceptions.workflowInvokedFailure(ss.description);
                status.updateState(ss.state, ex.getServiceCode(), ss.message);
                step.status = ss;
                // Persist the updated step state
                persistWorkflowStep(workflow, step);
            }
            if (status.isTerminalState()) {
                // release any step level locks held.
                boolean releasedLocks = _ownerLocker.releaseLocks(stepId);
                if (!releasedLocks) {
                    _log.info("Unable to release StepLocks for step: " + stepId);
                }
                // Check for any blocked steps and unblock them
                checkBlockedSteps(workflow, stepId);
            }
            // Check to see if the workflow might be finished, or need a rollback.
            if (workflow.allStatesTerminal()) {
                workflowDeleted = doWorkflowEndProcessing(workflow, automaticRollback, lock);
                if (workflowDeleted) {
                    // lock is released by end processing if the workflow is deleted
                    lock = null;
                }
            }
        }
    } catch (Exception ex) {
        String exMsg = "Exception processing updateStepStatus stepId: " + stepId + ": " + ex.getMessage();
        _log.error(exMsg, ex);
        throw new WorkflowException(exMsg, ex);
    } finally {
        unlockWorkflow(workflow, lock);
        if (workflowDeleted) {
            deleteWorkflowLock(workflow);
        }
    }
}
Also used : InterProcessLock(org.apache.curator.framework.recipes.locks.InterProcessLock) StepStatus(com.emc.storageos.workflow.Workflow.StepStatus) Step(com.emc.storageos.workflow.Workflow.Step) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) LockRetryException(com.emc.storageos.locking.LockRetryException)

Example 30 with InterProcessLock

use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.

the class InterProcessLockHolder method acquire.

public static InterProcessLockHolder acquire(CoordinatorClient client, String lockName, Logger log, int timeoutMillis) throws Exception {
    InterProcessLock lock = client.getLock(lockName);
    if (!lock.acquire(timeoutMillis, TimeUnit.MILLISECONDS)) {
        if (log != null) {
            log.info("Failed to take lock {} in {} ms", lockName, timeoutMillis);
        }
        return null;
    }
    if (log != null) {
        log.info("Acquired lock: {}", lockName);
    }
    InterProcessLockHolder holder = new InterProcessLockHolder();
    holder.lock = lock;
    holder.name = lockName;
    holder.log = log;
    return holder;
}
Also used : InterProcessLock(org.apache.curator.framework.recipes.locks.InterProcessLock)

Aggregations

InterProcessLock (org.apache.curator.framework.recipes.locks.InterProcessLock)98 APIException (com.emc.storageos.svcs.errorhandling.resources.APIException)25 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)21 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)15 IOException (java.io.IOException)15 ControllerException (com.emc.storageos.volumecontroller.ControllerException)14 Configuration (com.emc.storageos.coordinator.common.Configuration)12 CoordinatorException (com.emc.storageos.coordinator.exceptions.CoordinatorException)12 UnknownHostException (java.net.UnknownHostException)12 Site (com.emc.storageos.coordinator.client.model.Site)11 RetryableCoordinatorException (com.emc.storageos.coordinator.exceptions.RetryableCoordinatorException)11 NetworkDeviceControllerException (com.emc.storageos.networkcontroller.exceptions.NetworkDeviceControllerException)10 CheckPermission (com.emc.storageos.security.authorization.CheckPermission)9 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)9 BiosCommandResult (com.emc.storageos.volumecontroller.impl.BiosCommandResult)9 ArrayList (java.util.ArrayList)9 POST (javax.ws.rs.POST)9 NetworkSystem (com.emc.storageos.db.client.model.NetworkSystem)8 Path (javax.ws.rs.Path)8 ConfigurationImpl (com.emc.storageos.coordinator.common.impl.ConfigurationImpl)6