use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method pauseMigrationStep.
public void pauseMigrationStep(URI vplexURI, URI migrationURI, String stepId) {
WorkflowStepCompleter.stepExecuting(stepId);
try {
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
client.pauseMigrations(Arrays.asList(migration.getLabel()));
migration.setMigrationStatus(VPlexMigrationInfo.MigrationStatus.PAUSED.getStatusValue());
_dbClient.updateObject(migration);
WorkflowStepCompleter.stepSucceded(stepId);
} catch (Exception ex) {
_log.error("Exception pausing migration: ", ex);
String opName = ResourceOperationTypeEnum.PAUSE_MIGRATION.getName();
ServiceError serviceError = VPlexApiException.errors.operateMigrationFailed(opName, ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForChangeVirtualArray.
@Override
public String addStepsForChangeVirtualArray(Workflow workflow, String waitFor, List<VolumeDescriptor> volumes, String taskId) throws InternalException {
try {
URI cgURI = null;
URI currentVarrayURI = null;
URI tgtVarrayURI = null;
URI vplexURI = null;
StorageSystem vplexSystem = null;
List<URI> vplexVolumeURIs = new ArrayList<URI>();
VPlexConsistencyGroupManager cgMgr = null;
// Get all the Virtual Volumes and the new varray URI.
List<VolumeDescriptor> vplexVolumeDescriptors = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
for (VolumeDescriptor vplexVolumeDescriptor : vplexVolumeDescriptors) {
// Add the URI for the VPLEX volume.
URI vplexVolumeURI = vplexVolumeDescriptor.getVolumeURI();
_log.info("Add steps to change virtual array for volume {}", vplexVolumeURI);
vplexVolumeURIs.add(vplexVolumeURI);
// Set the target virtual array if not already set.
if (tgtVarrayURI == null) {
if ((vplexVolumeDescriptor.getParameters() != null) && (!vplexVolumeDescriptor.getParameters().isEmpty())) {
tgtVarrayURI = (URI) vplexVolumeDescriptor.getParameters().get(VolumeDescriptor.PARAM_VARRAY_CHANGE_NEW_VAARAY_ID);
_log.info("Target virtual array for varray change is {}", tgtVarrayURI);
}
}
// migrated when multiple volumes are passed.
if (vplexURI == null) {
Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
vplexURI = vplexVolume.getStorageController();
vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
currentVarrayURI = vplexVolume.getVirtualArray();
cgURI = vplexVolume.getConsistencyGroup();
cgMgr = (VPlexConsistencyGroupManager) getConsistencyGroupManager(vplexVolume);
}
}
// We need to determine if the varray change will migrate the
// volumes to the other cluster of the VPLEX. If so and the
// volumes are in a consistency group, then the volumes must
// first be removed from the consistency group.
String lastStep = waitFor;
boolean volumesRemovedFromCG = false;
if (!NullColumnValueGetter.isNullURI(cgURI)) {
_log.info("Varray change volumes are in CG {}", cgURI);
String currentClusterId = ConnectivityUtil.getVplexClusterForVarray(currentVarrayURI, vplexURI, _dbClient);
String newClusterId = ConnectivityUtil.getVplexClusterForVarray(tgtVarrayURI, vplexURI, _dbClient);
if (!newClusterId.equals(currentClusterId)) {
_log.info("Varray change migrates volumes to cluster {}", newClusterId);
// The volumes are in a consistency group and the
// volumes will change cluster, so the volumes
// must be removed from the CG first.
lastStep = cgMgr.addStepForRemoveVolumesFromCG(workflow, waitFor, vplexSystem, vplexVolumeURIs, cgURI);
volumesRemovedFromCG = true;
}
}
// Create steps to migrate the backend volumes.
String migrateStep = null;
List<URI> localSystemsToRemoveCG = new ArrayList<URI>();
List<VolumeDescriptor> vplexMigrateVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_MIGRATE_VOLUME }, new VolumeDescriptor.Type[] {});
for (URI vplexVolumeURI : vplexVolumeURIs) {
_log.info("Adding migration steps for vplex volume {}", vplexVolumeURI);
// A list of the volumes to which the data on the current
// backend volumes will be migrated.
List<URI> newVolumes = new ArrayList<URI>();
// A Map containing a migration for each new backend
// volume
Map<URI, URI> migrationMap = new HashMap<URI, URI>();
// A map that specifies the storage pool in which
// each new volume should be created.
Map<URI, URI> poolVolumeMap = new HashMap<URI, URI>();
for (VolumeDescriptor desc : vplexMigrateVolumes) {
// Skip migration targets that are not for the VPLEX
// volume being processed.
Migration migration = getDataObject(Migration.class, desc.getMigrationId(), _dbClient);
if (!migration.getVolume().equals(vplexVolumeURI)) {
continue;
}
_log.info("Found migration {} for VPLEX volume", migration.getId());
// Set data required to add the migration steps.
newVolumes.add(desc.getVolumeURI());
migrationMap.put(desc.getVolumeURI(), desc.getMigrationId());
poolVolumeMap.put(desc.getVolumeURI(), desc.getPoolURI());
// If the migration is to a different storage system
// we may need to remove the backend CG on the source
// system after the migration completes.
URI migSrcURI = migration.getSource();
Volume migSrc = getDataObject(Volume.class, migSrcURI, _dbClient);
URI migTgtURI = migration.getTarget();
Volume migTgt = getDataObject(Volume.class, migTgtURI, _dbClient);
if ((!migTgt.getStorageController().equals(migSrc.getStorageController())) && (!localSystemsToRemoveCG.contains(migSrc.getStorageController()))) {
_log.info("Will remove CG on local system {} if volume is in a CG.", migSrc.getStorageController());
localSystemsToRemoveCG.add(migSrc.getStorageController());
}
}
// Note that the migrate step here is a step group associated
// with deleting the migration sources after the migrations
// have completed and committed. This means that anything
// that waits on this, will occur after the migrations have
// completed, been committed, and the migration sources deleted.
migrateStep = addStepsForMigrateVolumes(workflow, vplexURI, vplexVolumeURI, newVolumes, migrationMap, poolVolumeMap, null, tgtVarrayURI, false, false, taskId, lastStep);
_log.info("Added migration steps for vplex volume {}", vplexVolumeURI);
}
// Update last step
if (migrateStep != null) {
lastStep = migrateStep;
}
// If the volumes are in a CG, we add the final CG steps.
if (!NullColumnValueGetter.isNullURI(cgURI)) {
BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, _dbClient);
if (volumesRemovedFromCG) {
// If the volumes were removed from the consistency group, the
// varray change was across clusters. First add a step to delete
// the CG on the old cluster and then add steps to create the
// CG on the other cluster and add the volumes. The remove step
// must be executed first otherwise, when we go to create the CG
// on the other cluster, the create CG code will see that the CG
// already exists on the VPLEX system and it will not create it.
String removeStepId = workflow.createStepId();
StringSet systemCGs = cg.getSystemConsistencyGroups().get(vplexURI.toString());
String clusterCGName = systemCGs.iterator().next();
String clusterName = BlockConsistencyGroupUtils.fetchClusterName(clusterCGName);
String cgName = BlockConsistencyGroupUtils.fetchCgName(clusterCGName);
cgMgr.addStepForRemoveVPlexCG(workflow, removeStepId, lastStep, vplexSystem, cgURI, cgName, clusterName, Boolean.FALSE, null);
lastStep = cgMgr.addStepsForCreateConsistencyGroup(workflow, removeStepId, vplexSystem, vplexVolumeURIs, true);
_log.info("Added steps to remove the CG from the source cluster and add to target cluster.");
}
if (cg.checkForType(Types.LOCAL)) {
_log.info("CG {} has local type", cgURI);
// If the backend volumes are being migrated to a new storage system,
// then we need to add a step to delete the local CG.
boolean localCGDeleted = false;
List<URI> localSystemURIs = BlockConsistencyGroupUtils.getLocalSystems(cg, _dbClient);
for (URI localSystemURI : localSystemURIs) {
_log.info("CG exists on local system {}", localSystemURI);
if (localSystemsToRemoveCG.contains(localSystemURI)) {
localCGDeleted = true;
_log.info("Adding step to remove CG on local system{}", localSystemURI);
StorageSystem localSystem = getDataObject(StorageSystem.class, localSystemURI, _dbClient);
Workflow.Method deleteCGMethod = new Workflow.Method("deleteConsistencyGroup", localSystemURI, cgURI, Boolean.FALSE);
workflow.createStep("deleteLocalCG", String.format("Delete consistency group from storage system: %s", localSystemURI), lastStep, localSystemURI, localSystem.getSystemType(), BlockDeviceController.class, deleteCGMethod, null, null);
}
}
if (localCGDeleted) {
lastStep = "deleteLocalCG";
}
}
}
// Return the last step
return lastStep;
} catch (Exception ex) {
throw VPlexApiException.exceptions.addStepsForChangeVirtualPoolFailed(ex);
}
}
use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method pauseMigration.
@Override
public void pauseMigration(URI vplexURI, URI migrationURI, String opId) {
MigrationOperationTaskCompleter completer = null;
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, PAUSE_MIGRATION_WF_NAME, false, opId);
_log.info("Created pause migration workflow with operation id {}", opId);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
URI volId = migration.getVolume();
completer = new MigrationOperationTaskCompleter(volId, opId);
Workflow.Method pauseMigrationMethod = new Workflow.Method(PAUSE_MIGRATION_METHOD_NAME, vplexURI, migrationURI);
workflow.createStep(PAUSE_MIGRATION_STEP, "Pause migration", null, vplexURI, vplex.getSystemType(), getClass(), pauseMigrationMethod, rollbackMethodNullMethod(), null);
String successMsg = String.format("Migration %s paused successfully", migrationURI);
workflow.executePlan(completer, successMsg);
_log.info("Workflow plan executing");
} catch (Exception e) {
String failMsg = String.format("Pause the migration %s failed", migrationURI);
_log.error(failMsg, e);
String opName = ResourceOperationTypeEnum.PAUSE_MIGRATION.getName();
ServiceError serviceError = VPlexApiException.errors.operateMigrationFailed(opName, e);
failStep(completer, opId, serviceError);
}
}
use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForChangeVirtualPool.
@Override
public String addStepsForChangeVirtualPool(Workflow workflow, String waitFor, List<VolumeDescriptor> volumes, String taskId) throws InternalException {
try {
// Get all the Virtual Volumes.
List<VolumeDescriptor> vplexVirtualVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
if (vplexVirtualVolumes == null || vplexVirtualVolumes.isEmpty()) {
return waitFor;
}
// Find the original change vpool virtual volumes from the descriptors.
URI newVpoolURI = null;
List<URI> changeVpoolVirtualVolumeURIs = new ArrayList<URI>();
for (VolumeDescriptor vplexVirtualVolume : vplexVirtualVolumes) {
if (vplexVirtualVolume.getParameters() != null && !vplexVirtualVolume.getParameters().isEmpty()) {
// Let's check to see if the PARAM_VPOOL_CHANGE_EXISTING_VOLUME_ID was populated
// in the descriptor params map. This would indicate that the descriptor
// has information about the existing volume for the change vpool operation.
Object existingVolumeId = vplexVirtualVolume.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_EXISTING_VOLUME_ID);
if (existingVolumeId != null) {
URI virtualVolumeURI = (URI) existingVolumeId;
_log.info(String.format("Adding steps for change vpool for vplex volume %s", virtualVolumeURI.toString()));
if (newVpoolURI == null) {
newVpoolURI = (URI) vplexVirtualVolume.getParameters().get(VolumeDescriptor.PARAM_VPOOL_CHANGE_NEW_VPOOL_ID);
}
changeVpoolVirtualVolumeURIs.add(virtualVolumeURI);
}
}
}
// Check to see if this is an RP+VPLEX change vpool request
List<VolumeDescriptor> rpExistingSourceVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_EXISTING_SOURCE }, new VolumeDescriptor.Type[] {});
// Check to see if this is an RP+VPLEX change vpool request
List<VolumeDescriptor> rpExistingProtectedSourceVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.RP_EXISTING_PROTECTED_SOURCE }, new VolumeDescriptor.Type[] {});
boolean rpAddProtectionVPoolChange = (rpExistingSourceVolumes != null && !rpExistingSourceVolumes.isEmpty());
boolean rpUpgradeProtectionVPoolChange = (rpExistingProtectedSourceVolumes != null && !rpExistingProtectedSourceVolumes.isEmpty());
// RP+VPLEX change vpool request
if (rpAddProtectionVPoolChange || rpUpgradeProtectionVPoolChange) {
// First let's make a copy of the all the volume descriptors passed in
List<VolumeDescriptor> copyOfVolumeDescriptors = new ArrayList<VolumeDescriptor>();
copyOfVolumeDescriptors.addAll(volumes);
if (rpAddProtectionVPoolChange) {
_log.info("Adding VPLEX steps for RP+VPLEX/MetroPoint add protection vpool change...");
Iterator<VolumeDescriptor> it = copyOfVolumeDescriptors.iterator();
while (it.hasNext()) {
VolumeDescriptor currentVolumeDesc = it.next();
if (changeVpoolVirtualVolumeURIs.contains(currentVolumeDesc.getVolumeURI())) {
// Remove the RP+VPLEX Source Change Vpool Virtual Volume(s) from the copy of the
// descriptors as they do not need to be created (because they already exist!)
it.remove();
break;
}
}
// already)
for (URI virtualVolumeURI : changeVpoolVirtualVolumeURIs) {
Volume changeVpoolVolume = getDataObject(Volume.class, virtualVolumeURI, _dbClient);
changeVpoolVolume.getConsistencyGroup();
// This is a good time to update the vpool on the existing Virtual Volume to the new vpool
changeVpoolVolume.setVirtualPool(newVpoolURI);
_dbClient.updateObject(changeVpoolVolume);
StorageSystem vplex = getDataObject(StorageSystem.class, changeVpoolVolume.getStorageController(), _dbClient);
// Get a handle on the RP consistency group manager
ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(DiscoveredDataObject.Type.rp.name());
// Add step for create CG
waitFor = consistencyGroupManager.addStepsForCreateConsistencyGroup(workflow, waitFor, vplex, Arrays.asList(virtualVolumeURI), false);
_log.info("Added steps for CG creation for vplex volume {}", virtualVolumeURI);
}
} else {
_log.info("Adding VPLEX steps for RP+VPLEX/MetroPoint upgrade protection vpool change...");
}
// Let's now create the virtual volumes for the RP+VPLEX:
// Source Journal, Target(s), and Target Journal.
waitFor = addStepsForCreateVolumes(workflow, waitFor, copyOfVolumeDescriptors, taskId);
}
// Create steps to migrate the backend volumes.
String lastStep = waitFor;
URI cgURI = null;
// With application support, one VPLEX CG could have multiple replication groups from the same local system.
// The localSystemToRemoveCG map key is storagesystemUri, value is the list of replication group names to be removed.
Map<URI, Set<String>> localSystemsToRemoveCG = new HashMap<URI, Set<String>>();
List<VolumeDescriptor> vplexMigrateVolumes = VolumeDescriptor.filterByType(volumes, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_MIGRATE_VOLUME }, new VolumeDescriptor.Type[] {});
if (vplexMigrateVolumes != null && !vplexMigrateVolumes.isEmpty()) {
for (URI virtualVolumeURI : changeVpoolVirtualVolumeURIs) {
_log.info("Adding migration steps for vplex volume {}", virtualVolumeURI);
// A list of the volumes satisfying the new VirtualPool to
// which the data on the current backend volumes
// will be migrated.
List<URI> newVolumes = new ArrayList<URI>();
// A Map containing a migration for each new backend
// volume
Map<URI, URI> migrationMap = new HashMap<URI, URI>();
// A map that specifies the storage pool in which
// each new volume should be created.
Map<URI, URI> poolVolumeMap = new HashMap<URI, URI>();
// The URI of the vplex system
URI vplexURI = null;
for (VolumeDescriptor desc : vplexMigrateVolumes) {
// Skip migration targets that are not for the VPLEX
// volume being processed.
Migration migration = getDataObject(Migration.class, desc.getMigrationId(), _dbClient);
if (!migration.getVolume().equals(virtualVolumeURI)) {
continue;
}
// migrated when multiple volumes are passed.
if (vplexURI == null) {
Volume virtualVolume = getDataObject(Volume.class, virtualVolumeURI, _dbClient);
vplexURI = virtualVolume.getStorageController();
cgURI = virtualVolume.getConsistencyGroup();
}
// Set data required to add the migration steps.
newVolumes.add(desc.getVolumeURI());
migrationMap.put(desc.getVolumeURI(), desc.getMigrationId());
poolVolumeMap.put(desc.getVolumeURI(), desc.getPoolURI());
// If the migration is to a different storage system
// we may need to remove the backend CG on the source
// system after the migration completes. Note that the
// migration source is null for an ingested volume
// being migrated to known storage.
Volume migSrc = null;
URI migSrcURI = migration.getSource();
if (!NullColumnValueGetter.isNullURI(migSrcURI)) {
migSrc = getDataObject(Volume.class, migSrcURI, _dbClient);
}
URI migTgtURI = migration.getTarget();
Volume migTgt = getDataObject(Volume.class, migTgtURI, _dbClient);
if ((migSrc != null) && (!migTgt.getStorageController().equals(migSrc.getStorageController()))) {
// If we have a volume to migrate and the RG field is NOT set on the volume,
// do not remove the RG on the local system.
//
// Volumes that are in RGs that are being migrated are grouped together so otherwise
// we're good as the replication instance will be set on those volumes.
String rgName = migSrc.getReplicationGroupInstance();
if (NullColumnValueGetter.isNotNullValue(rgName)) {
URI storageUri = migSrc.getStorageController();
Set<String> rgNames = localSystemsToRemoveCG.get(storageUri);
if (rgNames == null) {
rgNames = new HashSet<String>();
localSystemsToRemoveCG.put(storageUri, rgNames);
}
rgNames.add(rgName);
_log.info("Will remove CG {} on local system {}", rgName, storageUri);
} else {
_log.info("Will not remove CG on local system {}", migSrc.getStorageController());
}
}
}
// Note that the last step here is a step group associated
// with deleting the migration sources after the migrations
// have completed and committed. This means that anything
// that waits on this, will occur after the migrations have
// completed, been committed, and the migration sources deleted.
lastStep = addStepsForMigrateVolumes(workflow, vplexURI, virtualVolumeURI, newVolumes, migrationMap, poolVolumeMap, newVpoolURI, null, VolumeDescriptor.getMigrationSuspendBeforeCommit(volumes), VolumeDescriptor.getMigrationSuspendBeforeDeleteSource(volumes), taskId, waitFor);
_log.info("Add migration steps for vplex volume {}", virtualVolumeURI);
}
// systemConsistencyGroup specified for the group.
if (!NullColumnValueGetter.isNullURI(cgURI)) {
_log.info("Vpool change volumes are in CG {}", cgURI);
BlockConsistencyGroup cg = getDataObject(BlockConsistencyGroup.class, cgURI, _dbClient);
if (cg.checkForType(Types.LOCAL)) {
_log.info("CG {} has local type", cgURI);
// If any of the VPLEX volumes involved in the vpool change
// is in a VPLEX CG with corresponding local CGs for the backend
// volumes, then it is required that all VPLEX volumes in the
// CG are part of the vpool change. If the backend volumes are being
// migrated to a new storage system, then we need to add a step
// to delete the local CG.
boolean localCGDeleted = false;
for (Map.Entry<URI, Set<String>> entry : localSystemsToRemoveCG.entrySet()) {
localCGDeleted = true;
URI localSystemURI = entry.getKey();
StorageSystem localSystem = getDataObject(StorageSystem.class, localSystemURI, _dbClient);
Set<String> rgNames = entry.getValue();
for (String rgName : rgNames) {
_log.info("Adding step to remove CG {} on local system {}", rgName, localSystemURI);
Workflow.Method deleteCGMethod = new Workflow.Method("deleteReplicationGroupInConsistencyGroup", localSystemURI, cgURI, rgName, false, false, true);
workflow.createStep("deleteLocalCG", String.format("Delete consistency group from storage system: %s", localSystemURI), lastStep, localSystemURI, localSystem.getSystemType(), BlockDeviceController.class, deleteCGMethod, null, null);
}
}
if (localCGDeleted) {
lastStep = "deleteLocalCG";
}
}
}
}
// Return the last step
return lastStep;
} catch (Exception ex) {
throw VPlexApiException.exceptions.addStepsForChangeVirtualPoolFailed(ex);
}
}
use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method rollbackMigrateVirtualVolume.
/**
* Called when a migration cannot be created and started or the data
* migration is terminated prior to completing successfully. The function
* tries to cancel the migration and cleanup the remnants of the migration
* on the VPLEX.
*
* @param vplexURI
* The URI of the VPLex storage system.
* @param migrationURI
* The URI of the migration.
* @param migrateStepId
* The migration step id.
* @param stepId
* The rollback step id.
* @throws WorkflowException
*/
public void rollbackMigrateVirtualVolume(URI vplexURI, URI migrationURI, String migrateStepId, String stepId) throws WorkflowException {
Migration migration = null;
String migrationVolumeLabel = null;
try {
// Update step state to executing.
WorkflowStepCompleter.stepExecuting(stepId);
// Was the migration created and started? If so, then
// we'll try and cancel the migration and clean up.
// Otherwise, there is nothing to do.
Boolean migrationStarted = (Boolean) _workflowService.loadStepData(migrateStepId);
if (!migrationStarted.booleanValue()) {
// The migration was not successfully started.
WorkflowStepCompleter.stepSucceded(stepId);
return;
}
// Get the migration.
migration = _dbClient.queryObject(Migration.class, migrationURI);
// Get the VPLEX volume for the migration.
Volume migrationVolume = _dbClient.queryObject(Volume.class, migration.getVolume());
if (migrationVolume != null) {
migrationVolumeLabel = migrationVolume.getLabel();
}
// cancel it now.
if (!VPlexMigrationInfo.MigrationStatus.CANCELLED.getStatusValue().equals(migration.getMigrationStatus())) {
_log.info("Cancel migration {}", migrationURI);
// Get the VPlex API client.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexSystem, _dbClient);
_log.info("Got VPlex API client for VPlex {}", vplexURI);
// Try to cancel the migration and cleanup and remove any
// remnants of the migration.
client.cancelMigrations(Arrays.asList(migration.getLabel()), true, true);
_log.info("Migration cancelled");
}
WorkflowStepCompleter.stepSucceded(stepId);
} catch (VPlexApiException vae) {
// Do not allow rollback to go any further COP-21257
_workflowService.setWorkflowRollbackContOnError(stepId, false);
_log.error("Error during rollback of start migration: {}", vae.getMessage(), vae);
if (migration != null) {
setOrClearVolumeInternalFlag(migration.getVolume(), true);
vae = VPlexApiException.exceptions.migrationRollbackFailureContactEMC(migration.getVolume().toString(), migrationVolumeLabel, migration.getLabel());
}
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception e) {
_log.error("Error during rollback of start migration: {}", e.getMessage());
// Do not allow rollback to go any further COP-21257
_workflowService.setWorkflowRollbackContOnError(stepId, false);
if (migration != null) {
setOrClearVolumeInternalFlag(migration.getVolume(), true);
e = VPlexApiException.exceptions.migrationRollbackFailureContactEMC(migration.getVolume().toString(), migrationVolumeLabel, migration.getLabel());
}
WorkflowStepCompleter.stepFailed(stepId, VPlexApiException.exceptions.rollbackMigrateVolume(migrationURI.toString(), e));
}
}
Aggregations