use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method cancelMigration.
@Override
public void cancelMigration(URI vplexURI, URI migrationURI, String opId) {
MigrationOperationTaskCompleter completer = null;
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, CANCEL_MIGRATION_WF_NAME, false, opId);
_log.info("Created cancel 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 cancelMigrationMethod = new Workflow.Method(CANCEL_MIGRATION_METHOD_NAME, vplexURI, migrationURI);
workflow.createStep(CANCEL_MIGRATION_STEP, "Cancel migration", null, vplexURI, vplex.getSystemType(), getClass(), cancelMigrationMethod, rollbackMethodNullMethod(), null);
String successMsg = String.format("Migration %s cancelled 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.CANCEL_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 deleteMigration.
@Override
public void deleteMigration(URI vplexURI, URI migrationURI, String opId) {
MigrationOperationTaskCompleter completer = null;
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, DELETE_MIGRATION_WF_NAME, false, opId);
_log.info("Created delete 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 deleteMigrationMethod = new Workflow.Method(DELETE_MIGRATION_METHOD_NAME, vplexURI, migrationURI);
workflow.createStep(DELETE_MIGRATION_STEP, "Delete migration", null, vplexURI, vplex.getSystemType(), getClass(), deleteMigrationMethod, rollbackMethodNullMethod(), null);
String successMsg = String.format("Migration %s deleted 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.DELETE_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 resumeMigration.
@Override
public void resumeMigration(URI vplexURI, URI migrationURI, String opId) {
MigrationOperationTaskCompleter completer = null;
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, RESUME_MIGRATION_WF_NAME, false, opId);
_log.info("Created resume 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 resumeMigrationMethod = new Workflow.Method(RESUME_MIGRATION_METHOD_NAME, vplexURI, migrationURI);
workflow.createStep(RESUME_MIGRATION_STEP, "Resume migration", null, vplexURI, vplex.getSystemType(), getClass(), resumeMigrationMethod, rollbackMethodNullMethod(), null);
String successMsg = String.format("Migration %s resumed 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.RESUME_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 rollbackCommitMigration.
/**
* Rollback when a migration commit fails.
*
* @param migrationURIs
* The URIs for all migrations.
* @param newVpoolURI
* The URI of the new Vpool after migration commit
* @param newVarrayURI
* The URI of the new Varray after migration commit
* @param commitStepId
* The commit step id.
* @param stepId
* The rollback step id.
*
* @throws WorkflowException
*/
public void rollbackCommitMigration(List<URI> migrationURIs, URI newVpoolURI, URI newVarrayURI, String commitStepId, String stepId) throws WorkflowException {
// Update step state to executing.
WorkflowStepCompleter.stepExecuting(stepId);
try {
// Determine if any migration was successfully committed.
boolean migrationCommitted = false;
Iterator<URI> migrationIter = migrationURIs.iterator();
while (migrationIter.hasNext()) {
URI migrationURI = migrationIter.next();
Migration migration = _dbClient.queryObject(Migration.class, migrationURI);
Volume volume = _dbClient.queryObject(Volume.class, migration.getVolume());
// Check migration database record for committed state
if (VPlexMigrationInfo.MigrationStatus.COMMITTED.getStatusValue().equals(migration.getMigrationStatus())) {
migrationCommitted = true;
updateMigratedVirtualVolumeVpoolAndVarray(volume, newVpoolURI, newVarrayURI);
_dbClient.updateObject(volume);
inventoryDeleteMigrationSource(migration.getSource(), volume);
continue;
}
// Check vplex hardware migration records for committed state
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, volume.getStorageController(), _dbClient);
VPlexMigrationInfo migrationInfo = client.getMigrationInfo(migration.getLabel());
if (migrationInfo.getStatus().equalsIgnoreCase(VPlexMigrationInfo.MigrationStatus.COMMITTED.name())) {
migrationCommitted = true;
migration.setMigrationStatus(VPlexMigrationInfo.MigrationStatus.COMMITTED.name());
_dbClient.updateObject(migration);
associateVplexVolumeWithMigratedTarget(migration, migration.getVolume());
updateMigratedVirtualVolumeVpoolAndVarray(volume, newVpoolURI, newVarrayURI);
_dbClient.updateObject(volume);
inventoryDeleteMigrationSource(migration.getSource(), volume);
continue;
}
}
// creation step will cancel the migration.
if (migrationCommitted) {
_log.info("The migration has already been committed or the migration state can not be determined, failing rollback");
// Don't allow rollback to go further than the first error.
_workflowService.setWorkflowRollbackContOnError(stepId, false);
ServiceError serviceError = VPlexApiException.errors.cantRollbackCommittedMigration();
WorkflowStepCompleter.stepFailed(stepId, serviceError);
} else {
_log.info("No Migrations are not committed");
WorkflowStepCompleter.stepSucceded(stepId);
}
} catch (Exception e) {
_log.info("Exception determining commit rollback state", e);
// Don't allow rollback to go further than the first error.
_workflowService.setWorkflowRollbackContOnError(stepId, false);
ServiceError serviceError = VPlexApiException.errors.cantRollbackExceptionDeterminingCommitState(e);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.db.client.model.Migration in project coprhd-controller by CoprHD.
the class VPlexDeviceController method migrateVolumes.
/**
* Deprecating this for now, should be using the migrateVolumes call with the WF passed in from
* the BlockOrchestrator.
*
* {@inheritDoc}
*/
@Override
public void migrateVolumes(URI vplexURI, URI virtualVolumeURI, List<URI> targetVolumeURIs, Map<URI, URI> migrationsMap, Map<URI, URI> poolVolumeMap, URI newCoSURI, URI newNhURI, String successMsg, String failMsg, OperationTypeEnum opType, String opId, String wfStepId) throws ControllerException {
List<URI> migrationURIs = new ArrayList<URI>(migrationsMap.values());
try {
_log.info("VPlex controller migrate volume {} on VPlex {}", virtualVolumeURI, vplexURI);
// Get the VPlex storage system
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
_log.info("Got VPlex system");
// If a workflow step id is passed, then this is being called
// from a step in a "parent" workflow. In that case, this
// sub-workflow takes the name of the step.
String wfId = (wfStepId != null ? wfStepId : opId);
// Get a new workflow to execute the migrations.
Workflow workflow = _workflowService.getNewWorkflow(this, MIGRATE_VOLUMES_WF_NAME, false, wfId);
_log.info("Created new workflow with operation id {}", wfId);
// Create a step to validate the volume and prevent migration if the
// the ViPR DB does not properly reflect the actual backend volumes.
// A successful migration will delete the backend source volumes. If
// the ViPR DB does not correctly reflect the actual backend volume,
// we could delete a backend volume used by some other VPLEX volume.
String waitFor = createWorkflowStepToValidateVPlexVolume(workflow, vplexSystem, virtualVolumeURI, null);
// We first need to create steps in the workflow to create the new
// backend volume(s) to which the data for the virtual volume will
// be migrated.
List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
Map<URI, StorageSystem> storageSystemMap = new HashMap<URI, StorageSystem>();
Map<URI, Volume> volumeMap = new HashMap<URI, Volume>();
Iterator<URI> storagePoolIter = poolVolumeMap.keySet().iterator();
while (storagePoolIter.hasNext()) {
URI storagePoolURI = storagePoolIter.next();
URI volumeURI = poolVolumeMap.get(storagePoolURI);
_log.info("Creating descriptor for volume{} in pool {}", volumeURI, storagePoolURI);
descriptors.add(createDescriptorForBlockVolumeCreation(storagePoolURI, volumeURI, storageSystemMap, volumeMap));
_log.info("Created descriptor for volume");
}
// Add steps in the block device controller to create the target
// volumes.
waitFor = _blockDeviceController.addStepsForCreateVolumes(workflow, waitFor, descriptors, wfId);
// Set the project and tenant. We prefer a project created for the Vplex system,
// but will fallback to the volume's project if there isn't a project for the VPlex.
Volume firstVolume = volumeMap.values().iterator().next();
Project vplexProject = VPlexUtil.lookupVplexProject(firstVolume, vplexSystem, _dbClient);
URI tenantURI = vplexProject.getTenantOrg().getURI();
_log.info("Project is {}, Tenant is {}", vplexProject.getId(), tenantURI);
// Now we need to do the necessary zoning and export steps to ensure
// the VPlex can see these new backend volumes.
createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, storageSystemMap, volumeMap, vplexProject.getId(), tenantURI, waitFor);
_log.info("Created workflow steps for volume export.");
// Now make a migration Step for each passed target to which data
// for the passed virtual volume will be migrated. The migrations
// will be done from this controller.
Iterator<URI> targetVolumeIter = targetVolumeURIs.iterator();
while (targetVolumeIter.hasNext()) {
URI targetVolumeURI = targetVolumeIter.next();
_log.info("Target volume is {}", targetVolumeURI);
URI migrationURI = migrationsMap.get(targetVolumeURI);
_log.info("Migration is {}", migrationURI);
String stepId = workflow.createStepId();
_log.info("Migration opId is {}", stepId);
Workflow.Method vplexExecuteMethod = new Workflow.Method(MIGRATE_VIRTUAL_VOLUME_METHOD_NAME, vplexURI, virtualVolumeURI, targetVolumeURI, migrationURI, newNhURI);
Workflow.Method vplexRollbackMethod = new Workflow.Method(RB_MIGRATE_VIRTUAL_VOLUME_METHOD_NAME, vplexURI, migrationURI, stepId);
_log.info("Creating workflow migration step");
workflow.createStep(MIGRATION_CREATE_STEP, String.format("VPlex %s migrating to target volume %s.", vplexSystem.getId().toString(), targetVolumeURI.toString()), EXPORT_STEP, vplexSystem.getId(), vplexSystem.getSystemType(), getClass(), vplexExecuteMethod, vplexRollbackMethod, stepId);
_log.info("Created workflow migration step");
}
// Once the migrations complete, we will commit the migrations.
// So, now we create the steps to commit the migrations.
String waitForStep = MIGRATION_CREATE_STEP;
List<URI> migrationSources = new ArrayList<URI>();
Iterator<URI> migrationsIter = migrationsMap.values().iterator();
while (migrationsIter.hasNext()) {
URI migrationURI = migrationsIter.next();
_log.info("Migration is {}", migrationURI);
Migration migration = getDataObject(Migration.class, migrationURI, _dbClient);
// The migration source volume may be null for ingested volumes
// for which we do not know anything about the backend volumes.
// If we don't know the source, we know we are migrating an
// ingested volume and we will not want to do any renaming
// after the commit as we do when migration ViPR create volumes,
// which adhere to a standard naming convention.
Boolean rename = Boolean.TRUE;
if (migration.getSource() != null) {
migrationSources.add(migration.getSource());
} else {
rename = Boolean.FALSE;
}
_log.info("Added migration source {}", migration.getSource());
String stepId = workflow.createStepId();
_log.info("Commit operation id is {}", stepId);
Workflow.Method vplexExecuteMethod = new Workflow.Method(COMMIT_MIGRATION_METHOD_NAME, vplexURI, virtualVolumeURI, migrationURI, rename, newCoSURI, newNhURI);
Workflow.Method vplexRollbackMethod = new Workflow.Method(RB_COMMIT_MIGRATION_METHOD_NAME, migrationURIs, newCoSURI, newNhURI, stepId);
_log.info("Creating workflow step to commit migration");
waitForStep = workflow.createStep(MIGRATION_COMMIT_STEP, String.format("VPlex %s committing volume migration", vplexSystem.getId().toString()), waitForStep, vplexSystem.getId(), vplexSystem.getSystemType(), getClass(), vplexExecuteMethod, vplexRollbackMethod, stepId);
_log.info("Created workflow step to commit migration");
}
// Create a step that creates a sub workflow to delete the old
// migration source volumes, which are no longer used by the
// virtual volume. We also update the virtual volume CoS. If
// we make it to this step, then all migrations were committed.
// We do this in a sub workflow because we don't won't to
// initiate rollback regardless of success or failure.
String stepId = workflow.createStepId();
Workflow.Method vplexExecuteMethod = new Workflow.Method(DELETE_MIGRATION_SOURCES_METHOD, vplexURI, virtualVolumeURI, newCoSURI, newNhURI, migrationSources);
workflow.createStep(DELETE_MIGRATION_SOURCES_STEP, String.format("Creating workflow to delete migration sources"), MIGRATION_COMMIT_STEP, vplexSystem.getId(), vplexSystem.getSystemType(), getClass(), vplexExecuteMethod, null, stepId);
_log.info("Created workflow step to create sub workflow for source deletion");
// Finish up and execute the plan. The Workflow will handle the
// TaskCompleter
List<URI> volumes = new ArrayList<URI>();
volumes.add(virtualVolumeURI);
volumes.addAll(targetVolumeURIs);
TaskCompleter completer = new MigrationWorkflowCompleter(volumes, migrationURIs, opId, wfStepId);
_log.info("Executing workflow plan");
workflow.executePlan(completer, successMsg);
_log.info("Workflow plan executed");
} catch (Exception e) {
_log.error(failMsg, e);
List<URI> volumes = new ArrayList<URI>();
volumes.add(virtualVolumeURI);
volumes.addAll(targetVolumeURIs);
TaskCompleter completer = new MigrationWorkflowCompleter(volumes, migrationURIs, opId, wfStepId);
ServiceError serviceError = VPlexApiException.errors.jobFailed(e);
serviceError.setMessage(failMsg);
failStep(completer, opId, serviceError);
}
}
Aggregations