Search in sources :

Example 1 with WorkflowTaskCompleter

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

the class VPlexDeviceController method deleteMigrationSources.

/**
 * This step is executed after a virtual volume is successfully migrated to
 * delete the old source volumes. We create a sub workflow to perform this
 * task. We do this in a sub workflow because we don't want any of the steps
 * required to delete the sources to initiate rollback in the main workflow
 * if it fails.
 *
 * We also update the class of service, if required, for the virtual
 * volume when the migration is the result of a CoS change. When this
 * step is executed we know that the migrations have been committed and
 * the new CoS now applies to the virtual volume.
 *
 * @param vplexURI
 *            The URI of the VPlex storage system.
 * @param virtualVolumeURI
 *            The URI of the virtual volume.
 * @param newVpoolURI
 *            The CoS to be assigned to the virtual volume
 *            upon successful commit of the migration or null when not
 *            specified.
 * @param newVarrayURI
 *            The varray to be assigned to the virtual volume
 *            upon successful commit of the migration or null when not
 *            specified.
 * @param migrationSources
 *            The migration sources to delete.
 * @param stepId
 *            The workflow step id.
 * @throws WorkflowException
 */
public void deleteMigrationSources(URI vplexURI, URI virtualVolumeURI, URI newVpoolURI, URI newVarrayURI, List<URI> migrationSources, String stepId) throws WorkflowException {
    try {
        WorkflowStepCompleter.stepExecuting(stepId);
        // First update the virtual volume CoS, if necessary.
        Volume volume = _dbClient.queryObject(Volume.class, virtualVolumeURI);
        // or create a new exportGroup
        if (newVarrayURI != null && volume.isVolumeExported(_dbClient)) {
            URIQueryResultList exportGroupURIs = new URIQueryResultList();
            _dbClient.queryByConstraint(ContainmentConstraint.Factory.getBlockObjectExportGroupConstraint(virtualVolumeURI), exportGroupURIs);
            Iterator<URI> iterator = exportGroupURIs.iterator();
            while (iterator.hasNext()) {
                URI egUri = iterator.next();
                ExportGroup eg = _dbClient.queryObject(ExportGroup.class, egUri);
                if (eg != null) {
                    StringMap volumesMap = eg.getVolumes();
                    String lun = volumesMap.get(virtualVolumeURI.toString());
                    if (lun == null || lun.isEmpty()) {
                        lun = ExportGroup.LUN_UNASSIGNED_DECIMAL_STR;
                    }
                    List<URI> initiators = StringSetUtil.stringSetToUriList(eg.getInitiators());
                    ExportGroup newEg = null;
                    if (initiators != null && !initiators.isEmpty()) {
                        URI initiatorUri = initiators.get(0);
                        AlternateIdConstraint constraint = AlternateIdConstraint.Factory.getExportGroupInitiatorConstraint(initiatorUri.toString());
                        URIQueryResultList egUris = new URIQueryResultList();
                        _dbClient.queryByConstraint(constraint, egUris);
                        Iterator<URI> egIt = egUris.iterator();
                        while (egIt.hasNext()) {
                            ExportGroup theEg = _dbClient.queryObject(ExportGroup.class, egIt.next());
                            if (theEg.getVirtualArray().equals(newVarrayURI)) {
                                List<URI> theEgInits = StringSetUtil.stringSetToUriList(theEg.getInitiators());
                                if (theEgInits.containsAll(initiators) && theEgInits.size() == initiators.size()) {
                                    _log.info(String.format("Found existing exportGroup %s", theEg.getId().toString()));
                                    newEg = theEg;
                                    break;
                                }
                            }
                        }
                    }
                    if (newEg != null) {
                        // add the volume to the export group
                        newEg.addVolume(virtualVolumeURI, Integer.valueOf(lun));
                        _dbClient.updateObject(newEg);
                    } else {
                        // create a new export group
                        _log.info("Creating new ExportGroup");
                        createExportGroup(eg, volume, Integer.valueOf(lun));
                    }
                    eg.removeVolume(virtualVolumeURI);
                    _dbClient.updateObject(eg);
                }
            }
        }
        if (!migrationSources.isEmpty()) {
            final String workflowKey = "deleteOriginalSources";
            if (!WorkflowService.getInstance().hasWorkflowBeenCreated(stepId, workflowKey)) {
                // Now create and execute the sub workflow to delete the
                // migration source volumes if we have any. If the volume
                // migrated was ingested VPLEX volume we will not have
                // the sources.
                String subTaskId = stepId;
                Workflow subWorkflow = _workflowService.getNewWorkflow(this, DELETE_MIGRATION_SOURCES_WF_NAME, true, subTaskId);
                WorkflowTaskCompleter completer = new WorkflowTaskCompleter(subWorkflow.getWorkflowURI(), subTaskId);
                // Creates steps to remove the migration source volumes from all
                // export groups containing them and delete them.
                boolean unexportStepsAdded = vplexAddUnexportVolumeWfSteps(subWorkflow, null, migrationSources, null);
                // Only need to wait for unexport if there was a step for it added
                // to the workflow.
                String waitFor = null;
                if (unexportStepsAdded) {
                    waitFor = UNEXPORT_STEP;
                    // If the migration sources are unexported, Add a step to
                    // forget these backend volumes.
                    addStepToForgetVolumes(subWorkflow, vplexURI, migrationSources, waitFor);
                }
                // Add steps to delete the volumes.
                Iterator<URI> migrationSourcesIter = migrationSources.iterator();
                while (migrationSourcesIter.hasNext()) {
                    URI migrationSourceURI = migrationSourcesIter.next();
                    _log.info("Migration source URI is {}", migrationSourceURI);
                    Volume migrationSource = _dbClient.queryObject(Volume.class, migrationSourceURI);
                    URI sourceSystemURI = migrationSource.getStorageController();
                    _log.info("Source storage system URI is {}", sourceSystemURI);
                    StorageSystem sourceSystem = _dbClient.queryObject(StorageSystem.class, sourceSystemURI);
                    String subWFStepId = subWorkflow.createStepId();
                    Workflow.Method deleteVolumesMethod = new Workflow.Method(DELETE_VOLUMES_METHOD_NAME, sourceSystemURI, Arrays.asList(migrationSourceURI));
                    _log.info("Creating workflow step to delete source");
                    subWorkflow.createStep(MIGRATION_VOLUME_DELETE_STEP, String.format("Delete volume from storage system: %s", sourceSystemURI), waitFor, sourceSystemURI, sourceSystem.getSystemType(), BlockDeviceController.class, deleteVolumesMethod, null, subWFStepId);
                    _log.info("Created workflow step to delete source");
                }
                // Execute this sub workflow.
                subWorkflow.executePlan(completer, "Deleted migration sources");
                // Mark this workflow as created/executed so we don't do it again on retry/resume
                WorkflowService.getInstance().markWorkflowBeenCreated(stepId, workflowKey);
            }
        } else {
            // No sources to delete. Must have migrated an ingested volume.
            WorkflowStepCompleter.stepSucceded(stepId);
            _log.info("Updated workflow step to success");
        }
    } catch (Exception ex) {
        // Log the error.
        _log.error("Error deleting migration sources", ex);
        // Always return success. This is a cleanup step after a
        // successfully committed migration. We don't want rollback,
        // so we return success.
        WorkflowStepCompleter.stepSucceded(stepId);
    }
}
Also used : StringMap(com.emc.storageos.db.client.model.StringMap) Workflow(com.emc.storageos.workflow.Workflow) NamedURI(com.emc.storageos.db.client.model.NamedURI) URI(java.net.URI) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint) InternalException(com.emc.storageos.svcs.errorhandling.resources.InternalException) VPlexApiException(com.emc.storageos.vplex.api.VPlexApiException) ControllerException(com.emc.storageos.volumecontroller.ControllerException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) InternalServerErrorException(com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException) WorkflowException(com.emc.storageos.workflow.WorkflowException) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) ExportGroup(com.emc.storageos.db.client.model.ExportGroup) Volume(com.emc.storageos.db.client.model.Volume) WorkflowTaskCompleter(com.emc.storageos.workflow.WorkflowTaskCompleter) StorageSystem(com.emc.storageos.db.client.model.StorageSystem)

Aggregations

AlternateIdConstraint (com.emc.storageos.db.client.constraint.AlternateIdConstraint)1 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)1 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)1 NamedURI (com.emc.storageos.db.client.model.NamedURI)1 StorageSystem (com.emc.storageos.db.client.model.StorageSystem)1 StringMap (com.emc.storageos.db.client.model.StringMap)1 Volume (com.emc.storageos.db.client.model.Volume)1 DatabaseException (com.emc.storageos.db.exceptions.DatabaseException)1 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)1 InternalException (com.emc.storageos.svcs.errorhandling.resources.InternalException)1 InternalServerErrorException (com.emc.storageos.svcs.errorhandling.resources.InternalServerErrorException)1 ControllerException (com.emc.storageos.volumecontroller.ControllerException)1 VPlexApiException (com.emc.storageos.vplex.api.VPlexApiException)1 Workflow (com.emc.storageos.workflow.Workflow)1 WorkflowException (com.emc.storageos.workflow.WorkflowException)1 WorkflowTaskCompleter (com.emc.storageos.workflow.WorkflowTaskCompleter)1 IOException (java.io.IOException)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1