Search in sources :

Example 6 with Workflow

use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.

the class RPDeviceController method updateConsistencyGroupPolicy.

@Override
public void updateConsistencyGroupPolicy(URI protectionDevice, URI consistencyGroup, List<URI> volumeURIs, URI newVpoolURI, String task) throws InternalException {
    _log.info(String.format("Request to update consistency group policy for volumes %s through virtual pool change to %s", volumeURIs, newVpoolURI));
    VolumeVpoolChangeTaskCompleter taskCompleter = null;
    URI oldVpoolURI = null;
    List<Volume> volumes = new ArrayList<Volume>();
    List<Volume> vplexBackendVolumes = new ArrayList<Volume>();
    try {
        // Get all CG source volumes. The entire CG policy is being updated so we
        // need to capture the existing vpools for all the source volumes before
        // changing them.
        List<Volume> cgVolumes = RPHelper.getCgSourceVolumes(consistencyGroup, _dbClient);
        VirtualPool newVpool = _dbClient.queryObject(VirtualPool.class, newVpoolURI);
        Map<URI, URI> oldVpools = new HashMap<URI, URI>();
        for (Volume volume : cgVolumes) {
            // Save the old virtual pool
            oldVpoolURI = volume.getVirtualPool();
            oldVpools.put(volume.getId(), oldVpoolURI);
            // Update to the new virtual pool
            volume.setVirtualPool(newVpoolURI);
            volumes.add(volume);
            // If this is a VPlex volume, there will be
            StringSet associatedVolumeIds = volume.getAssociatedVolumes();
            // Perform additional tasks if this volume is a VPlex volume
            if (associatedVolumeIds != null && !associatedVolumeIds.isEmpty()) {
                Volume backendSrc = null;
                Volume backendHa = null;
                for (String associatedVolumeId : associatedVolumeIds) {
                    Volume associatedVolume = _dbClient.queryObject(Volume.class, URI.create(associatedVolumeId));
                    // Assign the associated volumes to either be the source or HA
                    if (associatedVolume != null) {
                        if (associatedVolume.getVirtualArray().equals(volume.getVirtualArray())) {
                            backendSrc = associatedVolume;
                        } else {
                            backendHa = associatedVolume;
                        }
                    }
                }
                if (backendSrc != null) {
                    // Change the back end volume's vPool too
                    backendSrc.setVirtualPool(newVpoolURI);
                    vplexBackendVolumes.add(backendSrc);
                    _log.info(String.format("Changing VirtualPool for VPLEX backend source volume %s (%s) from %s to %s", backendSrc.getLabel(), backendSrc.getId(), oldVpoolURI, newVpoolURI));
                    if (backendHa != null) {
                        VirtualPool newHAVpool = VirtualPool.getHAVPool(newVpool, _dbClient);
                        if (newHAVpool == null) {
                            // it may not be set
                            newHAVpool = newVpool;
                        }
                        backendHa.setVirtualPool(newHAVpool.getId());
                        vplexBackendVolumes.add(backendHa);
                    }
                }
            }
        }
        _dbClient.updateObject(volumes);
        _dbClient.updateObject(vplexBackendVolumes);
        // The VolumeVpoolChangeTaskCompleter will restore the old Virtual Pool
        taskCompleter = new VolumeVpoolChangeTaskCompleter(volumeURIs, oldVpools, task);
    } catch (Exception ex) {
        _log.error("Unexpected exception reading volume or generating taskCompleter: ", ex);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
        VolumeWorkflowCompleter completer = new VolumeWorkflowCompleter(volumeURIs, task);
        completer.error(_dbClient, serviceError);
    }
    try {
        Workflow workflow = _workflowService.getNewWorkflow(this, "updateReplicationMode", false, task);
        ProtectionSystem protectionSystem = _dbClient.queryObject(ProtectionSystem.class, protectionDevice);
        if (!volumes.isEmpty()) {
            VirtualPool newVirtualPool = _dbClient.queryObject(VirtualPool.class, newVpoolURI);
            // Add workflow step
            addUpdateConsistencyGroupPolicyStep(workflow, protectionSystem, consistencyGroup, newVirtualPool.getRpCopyMode());
        }
        if (!workflow.getAllStepStatus().isEmpty()) {
            _log.info("The updateAutoTieringPolicy workflow has {} step(s). Starting the workflow.", workflow.getAllStepStatus().size());
            workflow.executePlan(taskCompleter, "Updated the consistency group policy successfully.");
        } else {
            taskCompleter.ready(_dbClient);
        }
    } catch (Exception ex) {
        _log.error("Unexpected exception: ", ex);
        ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
        taskCompleter.error(_dbClient, serviceError);
    }
}
Also used : ServiceError(com.emc.storageos.svcs.errorhandling.model.ServiceError) HashMap(java.util.HashMap) VolumeWorkflowCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeWorkflowCompleter) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) VirtualPool(com.emc.storageos.db.client.model.VirtualPool) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) LockRetryException(com.emc.storageos.locking.LockRetryException) FunctionalAPIActionFailedException_Exception(com.emc.fapiclient.ws.FunctionalAPIActionFailedException_Exception) URISyntaxException(java.net.URISyntaxException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) FunctionalAPIInternalError_Exception(com.emc.fapiclient.ws.FunctionalAPIInternalError_Exception) CoordinatorException(com.emc.storageos.coordinator.exceptions.CoordinatorException) RecoverPointException(com.emc.storageos.recoverpoint.exceptions.RecoverPointException) VolumeVpoolChangeTaskCompleter(com.emc.storageos.volumecontroller.impl.block.taskcompleter.VolumeVpoolChangeTaskCompleter) Volume(com.emc.storageos.db.client.model.Volume) StringSet(com.emc.storageos.db.client.model.StringSet)

Example 7 with Workflow

use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.

the class RPDeviceController method addPreRestoreVolumeSteps.

/**
 * Adds the necessary RecoverPoint controller steps that need to be executed prior
 * to restoring a volume from snapshot. The pre-restore step is required if we
 * are restoring a native array snapshot of the following parent volumes:
 * <ul>
 * <li>A BlockSnapshot parent volume that is a regular RP source/target residing on a VMAX.</li>
 * <li>A BlockSnapshot parent volume that is a backing volume to a VPlex distributed volume.</li>
 * </ul>
 *
 * @param workflow
 *            the Workflow being constructed
 * @param storageSystemURI
 *            the URI of storage controller
 * @param volumeURI
 *            the URI of volume to be restored
 * @param snapshotURI
 *            the URI of snapshot used for restoration
 * @param taskId
 *            the top level operation's taskId
 * @return A waitFor key that can be used by subsequent controllers to wait on
 */
public String addPreRestoreVolumeSteps(Workflow workflow, URI storageSystemURI, URI volumeURI, URI snapshotURI, String taskId) {
    String waitFor = null;
    BlockSnapshot snapshot = _dbClient.queryObject(BlockSnapshot.class, snapshotURI);
    // Only consider native snapshots
    if (snapshot != null && NullColumnValueGetter.isNotNullValue(snapshot.getTechnologyType()) && snapshot.getTechnologyType().equals(TechnologyType.NATIVE.toString())) {
        Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
        StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, storageSystemURI);
        if (volume != null && storageSystem != null) {
            boolean vplexDistBackingVolume = false;
            URI cgId = volume.getConsistencyGroup();
            Volume associatedVPlexVolume = Volume.fetchVplexVolume(_dbClient, volume);
            if (associatedVPlexVolume != null && associatedVPlexVolume.getAssociatedVolumes() != null && associatedVPlexVolume.getAssociatedVolumes().size() == 2) {
                vplexDistBackingVolume = true;
            }
            if (vplexDistBackingVolume) {
                volume = associatedVPlexVolume;
            }
            // before performing the native block restore.
            if (!NullColumnValueGetter.isNullURI(volume.getProtectionController()) && (vplexDistBackingVolume || (storageSystem != null && NullColumnValueGetter.isNotNullValue(storageSystem.getSystemType()) && storageSystem.getSystemType().equals(SystemType.vmax.toString())))) {
                ProtectionSystem rpSystem = null;
                rpSystem = _dbClient.queryObject(ProtectionSystem.class, volume.getProtectionController());
                if (rpSystem == null) {
                    // Verify non-null storage device returned from the database client.
                    throw DeviceControllerExceptions.recoverpoint.failedConnectingForMonitoring(volume.getProtectionController());
                }
                List<URI> volumeURIs = getVolumesForRestore(snapshot, volume);
                // Validate the replication sets for all volumes to restore. Must ensure the source
                // volume size is not greater than the target volume size
                List<Volume> volumes = _dbClient.queryObject(Volume.class, volumeURIs);
                RPHelper.validateRSetVolumeSizes(_dbClient, volumes);
                Map<String, RecreateReplicationSetRequestParams> rsetParams = new HashMap<String, RecreateReplicationSetRequestParams>();
                // Lock CG
                List<String> locks = new ArrayList<String>();
                String lockName = ControllerLockingUtil.getConsistencyGroupStorageKey(_dbClient, cgId, rpSystem.getId());
                if (null != lockName) {
                    locks.add(lockName);
                    acquireWorkflowLockOrThrow(workflow, locks);
                }
                for (URI volumeId : volumeURIs) {
                    Volume vol = _dbClient.queryObject(Volume.class, volumeId);
                    RecreateReplicationSetRequestParams rsetParam = getReplicationSettings(rpSystem, vol.getId());
                    rsetParams.put(RPHelper.getRPWWn(vol.getId(), _dbClient), rsetParam);
                }
                String stepId = workflow.createStepId();
                Workflow.Method deleteRsetExecuteMethod = new Workflow.Method(METHOD_DELETE_RSET_STEP, rpSystem.getId(), volumeURIs);
                Workflow.Method recreateRSetExecuteMethod = new Workflow.Method(METHOD_RECREATE_RSET_STEP, rpSystem.getId(), volumeURIs, rsetParams);
                waitFor = workflow.createStep(STEP_PRE_VOLUME_RESTORE, "Pre volume restore from snapshot, delete replication set step for RP: " + volumeURI.toString(), null, rpSystem.getId(), rpSystem.getSystemType(), this.getClass(), deleteRsetExecuteMethod, recreateRSetExecuteMethod, stepId);
                _log.info(String.format("Created workflow step to delete replication set for volume %s.", volume.getId().toString()));
            }
        }
    }
    return waitFor;
}
Also used : HashMap(java.util.HashMap) BlockSnapshot(com.emc.storageos.db.client.model.BlockSnapshot) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) RecreateReplicationSetRequestParams(com.emc.storageos.recoverpoint.requests.RecreateReplicationSetRequestParams) Volume(com.emc.storageos.db.client.model.Volume) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Example 8 with Workflow

use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.

the class RPDeviceController method addPostVolumeExpandSteps.

/**
 * RP specific workflow steps after volume expansion are added here in this method
 * RP CG replication sets that were removed during pre expand are reconstructed with the new expanded volumes.
 *
 * @param workflow
 * @param waitFor
 * @param volume
 *            descriptors
 * @param taskId
 * @return
 * @throws WorkflowException
 */
public String addPostVolumeExpandSteps(Workflow workflow, String waitFor, List<VolumeDescriptor> volumeDescriptors, String taskId) throws WorkflowException {
    // Get only the RP volumes from the descriptors.
    List<VolumeDescriptor> volumeDescriptorsTypeFilter = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_SOURCE, VolumeDescriptor.Type.RP_EXISTING_SOURCE, VolumeDescriptor.Type.RP_VPLEX_VIRT_SOURCE }, new VolumeDescriptor.Type[] {});
    // If there are no RP volumes, just return
    if (volumeDescriptorsTypeFilter.isEmpty()) {
        return waitFor;
    }
    for (VolumeDescriptor descriptor : volumeDescriptorsTypeFilter) {
        Volume volume = _dbClient.queryObject(Volume.class, descriptor.getVolumeURI());
        ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, volume.getProtectionController());
        Map<String, RecreateReplicationSetRequestParams> rsetParams = new HashMap<String, RecreateReplicationSetRequestParams>();
        RecreateReplicationSetRequestParams rsetParam = getReplicationSettings(rpSystem, volume.getId());
        rsetParams.put(RPHelper.getRPWWn(volume.getId(), _dbClient), rsetParam);
        String stepId = workflow.createStepId();
        Workflow.Method recreateRSetExecuteMethod = new Workflow.Method(METHOD_RECREATE_RSET_STEP, rpSystem.getId(), Arrays.asList(volume.getId()), rsetParams);
        workflow.createStep(STEP_POST_VOLUME_EXPAND, "Post volume Expand, Recreate replication set subtask for RP: " + volume.toString(), waitFor, rpSystem.getId(), rpSystem.getSystemType(), this.getClass(), recreateRSetExecuteMethod, null, stepId);
        _log.info("Recreate Replication Set in workflow");
    }
    return STEP_POST_VOLUME_EXPAND;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) HashMap(java.util.HashMap) Workflow(com.emc.storageos.workflow.Workflow) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) RecreateReplicationSetRequestParams(com.emc.storageos.recoverpoint.requests.RecreateReplicationSetRequestParams)

Example 9 with Workflow

use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.

the class RPDeviceController method addPostRestoreFromFullcopySteps.

/**
 * Adds the necessary RecoverPoint controller steps that need to be executed after
 * restoring a volume from full copy. The post-restore step is required if we
 * are restoring a VPLEX full copy, whoes source volume is a distributed VPLEX volume
 * or a VMAX volume
 *
 * @param workflow
 *            the Workflow being constructed
 * @param waitFor
 *            the step that the newly created steps will wait for.
 * @param storageSystemURI
 *            the URI of storage controller
 * @param fullCopies
 *            the URI of full copies to restore
 * @param taskId
 *            the top level operation's taskId
 * @return A waitFor key that can be used by subsequent controllers to wait on
 */
public String addPostRestoreFromFullcopySteps(Workflow workflow, String waitFor, URI storageSystemURI, List<URI> fullCopies, String taskId) {
    if (fullCopies != null && !fullCopies.isEmpty()) {
        List<Volume> sourceVolumes = checkIfDistributedVplexOrVmaxFullCopies(fullCopies);
        if (!sourceVolumes.isEmpty()) {
            Map<String, RecreateReplicationSetRequestParams> rsetParams = new HashMap<String, RecreateReplicationSetRequestParams>();
            List<URI> volumeURIs = new ArrayList<URI>();
            URI rpSystemId = sourceVolumes.get(0).getProtectionController();
            ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
            for (Volume vol : sourceVolumes) {
                RecreateReplicationSetRequestParams rsetParam = getReplicationSettings(rpSystem, vol.getId());
                rsetParams.put(RPHelper.getRPWWn(vol.getId(), _dbClient), rsetParam);
                volumeURIs.add(vol.getId());
            }
            String stepId = workflow.createStepId();
            Workflow.Method recreateRSetExecuteMethod = new Workflow.Method(METHOD_RECREATE_RSET_STEP, rpSystemId, volumeURIs, rsetParams);
            waitFor = workflow.createStep(STEP_PRE_VOLUME_RESTORE, "Post volume restore from full copy, add replication set step for RP", waitFor, rpSystemId, rpSystem.getSystemType(), this.getClass(), recreateRSetExecuteMethod, rollbackMethodNullMethod(), stepId);
            _log.info("Created workflow step to recreate replication set for volumes");
        }
    }
    return waitFor;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem) RecreateReplicationSetRequestParams(com.emc.storageos.recoverpoint.requests.RecreateReplicationSetRequestParams) Volume(com.emc.storageos.db.client.model.Volume)

Example 10 with Workflow

use of com.emc.storageos.workflow.Workflow in project coprhd-controller by CoprHD.

the class RPDeviceController method addRemoveProtectionOnVolumeStep.

/**
 * Step to remove protection on RP Source volumes
 *
 * @param workflow
 *            The current WF
 * @param waitFor
 *            The previous waitFor step ID or Group
 * @param volumeDescriptors
 *            RP Source volume descriptors
 * @param taskId
 *            The Task ID
 * @param blockDeviceController
 *            Reference to a BlockDeviceController, used for specific steps on
 *            the volumes not covered by RP but required for the operation to be complete.
 * @return The next waitFor step ID or Group
 */
private String addRemoveProtectionOnVolumeStep(Workflow workflow, String waitFor, List<VolumeDescriptor> volumeDescriptors, String taskId, BlockDeviceController blockDeviceController) {
    List<URI> volumeURIs = new ArrayList<URI>();
    URI newVpoolURI = null;
    // Filter to get only the RP Source volumes.
    List<VolumeDescriptor> rpSourceDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_SOURCE, VolumeDescriptor.Type.RP_VPLEX_VIRT_SOURCE }, new VolumeDescriptor.Type[] {});
    for (VolumeDescriptor descriptor : rpSourceDescriptors) {
        if (descriptor.getParameters().get(VolumeDescriptor.PARAM_DO_NOT_DELETE_VOLUME) != null) {
            // This is a rollback protection operation. We do not want to delete the volume but we do
            // want to remove protection from it.
            newVpoolURI = (URI) descriptor.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_NEW_VPOOL_ID);
            _log.info(String.format("Adding step to remove protection from Volume (%s) and move it to vpool (%s)", descriptor.getVolumeURI(), newVpoolURI));
            volumeURIs.add(descriptor.getVolumeURI());
        }
    }
    if (volumeURIs.isEmpty()) {
        return waitFor;
    }
    // Filter to get only the Block Data volumes
    List<VolumeDescriptor> blockDataDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.BLOCK_DATA }, new VolumeDescriptor.Type[] {});
    // Check to see if there are any BLOCK_DATA volumes flagged to not be fully deleted.
    // These volumes could potentially need to have some untag operation performed
    // on the underlying array even though they won't be deleted.
    List<VolumeDescriptor> doNotDeleteDescriptors = VolumeDescriptor.getDoNotDeleteDescriptors(blockDataDescriptors);
    // Breakup the descriptors further into RP and RP+VPLEX descriptors
    List<VolumeDescriptor> rpDescriptors = new ArrayList<VolumeDescriptor>();
    List<VolumeDescriptor> rpVPlexDescriptors = new ArrayList<VolumeDescriptor>();
    for (VolumeDescriptor descr : doNotDeleteDescriptors) {
        Volume volume = _dbClient.queryObject(Volume.class, descr.getVolumeURI());
        // Check to see if this volume is associated to a RP+VPLEX Source volume.
        if (RPHelper.isAssociatedToRpVplexType(volume, _dbClient, PersonalityTypes.SOURCE)) {
            rpVPlexDescriptors.add(descr);
        } else {
            rpDescriptors.add(descr);
        }
    }
    if (doNotDeleteDescriptors != null && !doNotDeleteDescriptors.isEmpty()) {
        // Call the BlockDeviceController to perform untag operations on the volumes.
        // NOTE: Only needed for RP volumes.
        waitFor = blockDeviceController.addStepsForUntagVolumes(workflow, waitFor, rpDescriptors, taskId);
        // Call the BlockDeviceController to remove the volumes from any backend array CGs.
        // NOTE: Only needed for RP+VPLEX/MP volumes.
        waitFor = blockDeviceController.addStepsForUpdateConsistencyGroup(workflow, waitFor, null, rpVPlexDescriptors);
    }
    // Grab any volume from the list so we can grab the protection system. This
    // request could be over multiple protection systems but we don't really
    // care at this point. We just need this reference to pass into the
    // WorkFlow.
    Volume volume = _dbClient.queryObject(Volume.class, volumeURIs.get(0));
    ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, volume.getProtectionController());
    String stepId = workflow.createStepId();
    Workflow.Method removeProtectionExecuteMethod = new Workflow.Method(METHOD_REMOVE_PROTECTION_STEP, volumeURIs, newVpoolURI);
    workflow.createStep(STEP_REMOVE_PROTECTION, "Remove RP protection on volume(s)", waitFor, rpSystem.getId(), rpSystem.getSystemType(), this.getClass(), removeProtectionExecuteMethod, null, stepId);
    return STEP_REMOVE_PROTECTION;
}
Also used : VolumeDescriptor(com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor) Volume(com.emc.storageos.db.client.model.Volume) ArrayList(java.util.ArrayList) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) ProtectionSystem(com.emc.storageos.db.client.model.ProtectionSystem)

Aggregations

Workflow (com.emc.storageos.workflow.Workflow)285 URI (java.net.URI)204 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)171 ServiceError (com.emc.storageos.svcs.errorhandling.model.ServiceError)127 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)126 ControllerException (com.emc.storageos.volumecontroller.ControllerException)126 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)124 ArrayList (java.util.ArrayList)123 WorkflowException (com.emc.storageos.workflow.WorkflowException)119 NamedURI (com.emc.storageos.db.client.model.NamedURI)102 Volume (com.emc.storageos.db.client.model.Volume)76 TaskCompleter (com.emc.storageos.volumecontroller.TaskCompleter)72 HashMap (java.util.HashMap)66 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)65 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)61 ExportMask (com.emc.storageos.db.client.model.ExportMask)54 ExportTaskCompleter (com.emc.storageos.volumecontroller.impl.block.taskcompleter.ExportTaskCompleter)54 List (java.util.List)54 BlockObject (com.emc.storageos.db.client.model.BlockObject)41 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)41