use of com.emc.storageos.volumecontroller.TaskCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForCreateMirrors.
/**
* <p>
* Here we should have already created any underlying volumes. What remains to be done: 1. Export the underlying Storage Volumes from
* the array to the VPlex. 2. Create the mirror device and attach it as a mirror to the source virtual volume
*
* @param workflow
* The workflow to which the steps are added.
* @param waitFor
* The previous workflow step for which these steps will wait
* @param volumes
* The volume descriptors representing the mirror and the its associated backend volume.
* @param taskId
* The workflow taskId
*/
public String addStepsForCreateMirrors(Workflow workflow, String waitFor, List<VolumeDescriptor> volumes, String taskId) throws ControllerException {
try {
// Get only the VPlex mirrors from the descriptors.
List<VolumeDescriptor> vplexLocalMirrors = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_LOCAL_MIRROR }, new VolumeDescriptor.Type[] {});
// If there are no VPlex mirrors, just return
if (vplexLocalMirrors.isEmpty()) {
return waitFor;
}
// Build some needed maps to get started.
Map<URI, StorageSystem> arrayMap = buildArrayMap(volumes, Type.BLOCK_DATA);
Map<URI, Volume> volumeMap = buildVolumeMap(volumes, Type.BLOCK_DATA);
// Set the project and tenant to those of an underlying volume.
// These are used to set the project and tenant of a new ExportGroup if needed.
Volume firstVolume = volumeMap.values().iterator().next();
URI projectURI = firstVolume.getProject().getURI();
URI tenantURI = firstVolume.getTenant().getURI();
// Segregate the volumes by Device.
Map<URI, List<VolumeDescriptor>> vplexDescMap = VolumeDescriptor.getDeviceMap(vplexLocalMirrors);
// For each VPLEX mirror to be provisioned (there will be only one for Vplex Local
// Volume, Vplex Distributed Volume could have one or two mirrors, two mirrors mean
// one mirror on each leg)
String lastStep = VPLEX_STEP;
for (URI vplexURI : vplexDescMap.keySet()) {
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
try {
// Now we need to do the necessary zoning and export steps to ensure
// the VPlex can see these new backend volumes.
createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, arrayMap, volumeMap, projectURI, tenantURI, waitFor);
} catch (Exception ex) {
_log.error("Could not create volumes for vplex: " + vplexURI, ex);
TaskCompleter completer = new VPlexTaskCompleter(Volume.class, vplexURI, taskId, null);
ServiceError serviceError = VPlexApiException.errors.jobFailed(ex);
completer.error(_dbClient, serviceError);
throw ex;
}
// Now create each of the Vplex Mirror Devices that may be necessary.
List<URI> vplexMirrorURIs = VolumeDescriptor.getVolumeURIs(vplexDescMap.get(vplexURI));
// Now make a Step to create the Mirror.
String mirrorStep = workflow.createStepId();
lastStep = workflow.createStep(VPLEX_STEP, String.format("VPlex %s creating mirrors:%n%s", vplexSystem.getIpAddress(), BlockDeviceController.getVolumesMsg(_dbClient, vplexMirrorURIs)), EXPORT_STEP, vplexURI, vplexSystem.getSystemType(), this.getClass(), createMirrorsMethod(vplexURI, vplexMirrorURIs, taskId), rollbackCreateMirrorsMethod(vplexURI, vplexMirrorURIs, mirrorStep), mirrorStep);
}
return lastStep;
} catch (Exception ex) {
throw VPlexApiException.exceptions.addStepsForCreateMirrors(ex);
}
}
use of com.emc.storageos.volumecontroller.TaskCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method resyncSnapshot.
/**
* {@inheritDoc}
*/
@Override
public void resyncSnapshot(URI vplexURI, URI snapshotURI, String opId) throws InternalException {
// The snapshot target volume could be the source side backend volume for
// a VPLEX volume if a VPLEX volume was created on the snapshot target volume
// for the purpose of exporting the snapshot through the VPLEX rather directly
// through the backend storage system. If this is the case, and that snapshot
// is resynchronized, then we need do some additional steps because the data
// on the VPLEX backend volume will have changed, and the VPLEX volume needs
// to know about that.
BlockSnapshot snapshot = getDataObject(BlockSnapshot.class, snapshotURI, _dbClient);
try {
// Create a new the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, RESYNC_SNAPSHOT_WF_NAME, false, opId);
_log.info("Created resync snapshot workflow with operation id {}", opId);
// Get all snapshots that will be resync'd.
List<BlockSnapshot> snapshotsToResync = new ArrayList<BlockSnapshot>();
URI cgURI = snapshot.getConsistencyGroup();
if (!NullColumnValueGetter.isNullURI(cgURI)) {
snapshotsToResync = ControllerUtils.getSnapshotsPartOfReplicationGroup(snapshot, _dbClient);
} else {
snapshotsToResync.add(snapshot);
}
// Get a list of the VPLEX volumes, if any, that are built
// using the snapshot target volume.
List<Volume> vplexVolumes = VPlexUtil.getVPlexVolumesBuiltOnSnapshots(snapshotsToResync, _dbClient);
// Create the workflow steps.
if (vplexVolumes.isEmpty()) {
// If there are no VPLEX volumes built on the snapshots to be resynchronized,
// then we just need a single step to invoke the block device controller to
// resync the snapshots.
createWorkflowStepForResyncNativeSnapshot(workflow, snapshot, null, null);
} else {
// Maps Vplex volume that needs to be flushed to underlying array volume
Map<Volume, Volume> vplexToArrayVolumesToFlush = new HashMap<Volume, Volume>();
for (Volume vplexVolume : vplexVolumes) {
Volume arrayVolumeToBeResynced = VPlexUtil.getVPLEXBackendVolume(vplexVolume, true, _dbClient);
vplexToArrayVolumesToFlush.put(vplexVolume, arrayVolumeToBeResynced);
}
Map<URI, String> vplexVolumeIdToDetachStep = new HashMap<URI, String>();
String waitFor = null;
// Generate pre restore steps
waitFor = addPreRestoreResyncSteps(workflow, vplexToArrayVolumesToFlush, vplexVolumeIdToDetachStep, waitFor);
// Now create a workflow step to natively resync the snapshot.
// Note that if the snapshot is associated with a CG, then block
// controller will resync all snapshots in the snapshot set. We
// execute this after the invalidate cache.
waitFor = createWorkflowStepForResyncNativeSnapshot(workflow, snapshot, waitFor, rollbackMethodNullMethod());
// Generate post restore steps
waitFor = addPostRestoreResyncSteps(workflow, vplexToArrayVolumesToFlush, vplexVolumeIdToDetachStep, waitFor);
}
// Execute the workflow.
_log.info("Executing workflow plan");
TaskCompleter completer = new BlockSnapshotResyncCompleter(snapshot, opId);
String successMsg = String.format("Resynchronize VPLEX native snapshot %s from volume %s " + "completed successfully", snapshotURI, snapshot.getParent().getURI());
workflow.executePlan(completer, successMsg);
_log.info("Workflow plan executing");
} catch (Exception e) {
String failMsg = String.format("Resynchronize VPLEX native snapshot %s failed", snapshotURI);
_log.error(failMsg, e);
TaskCompleter completer = new BlockSnapshotResyncCompleter(snapshot, opId);
ServiceError serviceError = VPlexApiException.errors.restoreVolumeFailed(snapshotURI.toString(), e);
failStep(completer, opId, serviceError);
}
}
use of com.emc.storageos.volumecontroller.TaskCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewAddVolumesRollback.
/**
* Rollback entry point. This is a wrapper around the exportRemoveVolumes
* operation, which requires that we create a specific completer using the token
* that's passed in. This token is generated by the rollback processing.
*
* @param vplexURI
* [in] - StorageSystem URI
* @param exportGroupURI
* [in] - ExportGroup URI
* @param exportMaskURI
* [in] - ExportMask URI
* @param volumeURIs
* [in] - Impacted volume URIs
* @param initiatorURIs
* [in] - List of Initiator URIs
* @param rollbackContextKey
* [in] - context token
* @param token
* [in] - String token generated by the rollback processing
* @throws ControllerException
*/
public void storageViewAddVolumesRollback(URI vplexURI, URI exportGroupURI, URI exportMaskURI, List<URI> volumeURIs, String rollbackContextKey, String token) throws ControllerException {
TaskCompleter taskCompleter = new ExportMaskRemoveVolumeCompleter(exportGroupURI, exportMaskURI, volumeURIs, token);
// in order to only perform rollback of operations we successfully performed.
try {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(rollbackContextKey);
WorkflowService.getInstance().storeStepData(token, context);
storageViewRemoveVolumes(vplexURI, exportGroupURI, exportMaskURI, volumeURIs, rollbackContextKey, taskCompleter, rollbackContextKey, token);
} catch (Exception e) {
String message = String.format("Failed to remove Volume(s) %s on rollback from ExportGroup %s", Joiner.on(",").join(volumeURIs), exportGroupURI);
_log.error(message, e);
String opName = ResourceOperationTypeEnum.DELETE_EXPORT_VOLUME.getName();
ServiceError serviceError = VPlexApiException.errors.exportGroupRemoveVolumesFailed(Joiner.on(",").join(volumeURIs), exportGroupURI.toString(), opName, e);
taskCompleter.error(_dbClient, serviceError);
}
}
use of com.emc.storageos.volumecontroller.TaskCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method resyncFullCopy.
/**
* {@inheritDoc}
*/
@Override
public void resyncFullCopy(URI vplexURI, List<URI> fullCopyURIs, String opId) throws InternalException {
TaskCompleter completer = null;
try {
completer = new CloneResyncCompleter(fullCopyURIs, opId);
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, RESYNC_FULL_COPY_WF_NAME, false, opId);
_log.info("Created resync full copy workflow with operation id {}", opId);
// add CG to taskCompleter
Volume firstFullCopy = getDataObject(Volume.class, fullCopyURIs.get(0), _dbClient);
BlockObject firstSource = BlockObject.fetch(_dbClient, firstFullCopy.getAssociatedSourceVolume());
if (!NullColumnValueGetter.isNullURI(firstSource.getConsistencyGroup())) {
completer.addConsistencyGroupId(firstSource.getConsistencyGroup());
}
// Get the VPLEX and backend full copy volumes.
URI nativeSystemURI = null;
Map<URI, Volume> vplexFullCopyMap = new HashMap<URI, Volume>();
Map<URI, Volume> nativeFullCopyMap = new HashMap<URI, Volume>();
for (URI fullCopyURI : fullCopyURIs) {
Volume fullCopyVolume = getDataObject(Volume.class, fullCopyURI, _dbClient);
vplexFullCopyMap.put(fullCopyURI, fullCopyVolume);
Volume nativeFullCopyVolume = VPlexUtil.getVPLEXBackendVolume(fullCopyVolume, true, _dbClient);
nativeFullCopyMap.put(nativeFullCopyVolume.getId(), nativeFullCopyVolume);
if (nativeSystemURI == null) {
nativeSystemURI = nativeFullCopyVolume.getStorageController();
}
}
// Get the native system.
StorageSystem nativeSystem = getDataObject(StorageSystem.class, nativeSystemURI, _dbClient);
// We'll need a list of the native full copy URIs.
List<URI> nativeFullCopyURIs = new ArrayList<URI>(nativeFullCopyMap.keySet());
// Maps Vplex volume that needs to be flushed to underlying array volume
Map<Volume, Volume> vplexToArrayVolumesToFlush = new HashMap<Volume, Volume>();
for (Volume vplexFullCopyVolume : vplexFullCopyMap.values()) {
Volume arrayVolumeToBeResynced = VPlexUtil.getVPLEXBackendVolume(vplexFullCopyVolume, true, _dbClient);
vplexToArrayVolumesToFlush.put(vplexFullCopyVolume, arrayVolumeToBeResynced);
}
Map<URI, String> vplexVolumeIdToDetachStep = new HashMap<URI, String>();
// Generate pre restore steps
String waitFor = addPreRestoreResyncSteps(workflow, vplexToArrayVolumesToFlush, vplexVolumeIdToDetachStep, null);
// Now create a workflow step to natively resynchronize the
// backend full copy volumes. We execute this after the
// invalidate cache steps.
createWorkflowStepForResyncNativeFullCopy(workflow, nativeSystem, nativeFullCopyURIs, waitFor, rollbackMethodNullMethod());
// Generate post restore steps
waitFor = addPostRestoreResyncSteps(workflow, vplexToArrayVolumesToFlush, vplexVolumeIdToDetachStep, waitFor);
// Execute the workflow.
_log.info("Executing workflow plan");
String successMsg = String.format("Resynchronize full copy volumes %s completed successfully", fullCopyURIs);
FullCopyOperationCompleteCallback wfCompleteCB = new FullCopyOperationCompleteCallback();
workflow.executePlan(completer, successMsg, wfCompleteCB, new Object[] { fullCopyURIs }, null, null);
_log.info("Workflow plan executing");
} catch (Exception e) {
String failMsg = String.format("Resynchronize full copy volumes %s failed", fullCopyURIs);
_log.error(failMsg, e);
ServiceCoded sc = VPlexApiException.exceptions.resyncFullCopyFailed(fullCopyURIs.toString(), e);
failStep(completer, opId, sc);
}
}
use of com.emc.storageos.volumecontroller.TaskCompleter in project coprhd-controller by CoprHD.
the class VPlexDeviceController method exportGroupUpdate.
@Override
public void exportGroupUpdate(URI storageURI, URI exportGroupURI, Workflow storageWorkflow, String token) throws Exception {
TaskCompleter taskCompleter = null;
try {
_log.info(String.format("exportGroupUpdate start - Array: %s ExportGroup: %s", storageURI.toString(), exportGroupURI.toString()));
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageURI);
taskCompleter = new ExportOrchestrationTask(exportGroupURI, token);
String successMessage = String.format("ExportGroup %s successfully updated for StorageArray %s", exportGroup.getLabel(), storage.getLabel());
storageWorkflow.setService(_workflowService);
storageWorkflow.executePlan(taskCompleter, successMessage);
} catch (Exception ex) {
_log.error("ExportGroupUpdate Orchestration failed.", ex);
if (taskCompleter != null) {
ServiceError serviceError = DeviceControllerException.errors.jobFailed(ex);
failStep(taskCompleter, token, serviceError);
} else {
throw DeviceControllerException.exceptions.exportGroupUpdateFailed(ex);
}
}
}
Aggregations