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);
}
}
Aggregations