use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.
the class VPlexDeviceController method importVolume.
/**
* Updated importVolume code to create underlying volumes using other controllers.
*
* @param volumeDescriptors
* -- Contains the VPLEX_VIRTUAL volume, and optionally,
* a protection BLOCK_DATA volume to be created.
* @param vplexSystemProject
* @param vplexSystemTenant
* @param importedVolumeURI
* -- For the import use case, will give the URI of the existing
* storage array volume to be imported.
* @param newCosURI
* @param opId
* @throws ControllerException
*/
@Override
public void importVolume(URI vplexURI, List<VolumeDescriptor> volumeDescriptors, URI vplexSystemProject, URI vplexSystemTenant, URI newCosURI, String newLabel, String setTransferSpeed, Boolean markInactive, String opId) throws ControllerException {
// Figure out the various arguments.
List<VolumeDescriptor> vplexDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
// must be one VPLEX volume
Assert.isTrue(vplexDescriptors.size() == 1);
VolumeDescriptor vplexDescriptor = vplexDescriptors.get(0);
URI vplexVolumeURI = vplexDescriptor.getVolumeURI();
List<URI> volumeURIs = new ArrayList<URI>();
volumeURIs.add(vplexVolumeURI);
// See if there are any volumes to be created.
List<VolumeDescriptor> blockDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.BLOCK_DATA }, new VolumeDescriptor.Type[] {});
URI createdVolumeURI = null;
if (blockDescriptors.size() == 1) {
createdVolumeURI = blockDescriptors.get(0).getVolumeURI();
}
Map<URI, StorageSystem> arrayMap = buildArrayMap(null, blockDescriptors, null);
Map<URI, Volume> volumeMap = buildVolumeMap(null, blockDescriptors, null);
if (!blockDescriptors.isEmpty()) {
volumeURIs.addAll(VolumeDescriptor.getVolumeURIs(blockDescriptors));
}
// See if there is a Volume to be imported.
List<VolumeDescriptor> importDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.VPLEX_IMPORT_VOLUME }, new VolumeDescriptor.Type[] {});
URI importedVolumeURI = null;
if (!importDescriptors.isEmpty()) {
importedVolumeURI = importDescriptors.get(0).getVolumeURI();
volumeURIs.add(importedVolumeURI);
}
// Get the VPlex storage system and the volumes.
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
Volume vplexVolume = getDataObject(Volume.class, vplexVolumeURI, _dbClient);
// If there is a volume to be imported, we're creating a new Virtual Volume from
// the imported volume. Otherwise, we're upgrading an existing Virtual Volume to be
// distributed.
StorageSystem importedArray = null;
Volume importedVolume = null;
if (importedVolumeURI != null) {
importedVolume = getDataObject(Volume.class, importedVolumeURI, _dbClient);
importedArray = getDataObject(StorageSystem.class, importedVolume.getStorageController(), _dbClient);
arrayMap.put(importedArray.getId(), importedArray);
volumeMap.put(importedVolumeURI, importedVolume);
}
try {
// Generate the Workflow.
Workflow workflow = _workflowService.getNewWorkflow(this, IMPORT_VOLUMES_WF_NAME, false, opId);
String waitFor = null;
// Add a rollback step to remove the Virtual Volume if we are
// importing and therefore creating a new virtual volume.
List<URI> vplexVolumeURIs = new ArrayList<URI>();
vplexVolumeURIs.add(vplexVolumeURI);
if (importedVolumeURI != null) {
Workflow.Method nullMethod = rollbackMethodNullMethod();
Workflow.Method virtVolInactiveMethod = markVolumesInactiveMethod(vplexVolumeURIs);
waitFor = workflow.createStep(null, "Mark virtual volume inactive on rollback", waitFor, vplexURI, vplexSystem.getSystemType(), this.getClass(), nullMethod, virtVolInactiveMethod, null);
}
// to which the data for the virtual volume will saved (if used).
if (createdVolumeURI != null) {
waitFor = _blockDeviceController.addStepsForCreateVolumes(workflow, waitFor, volumeDescriptors, opId);
}
// Set the project and tenant to those of an underlying volume.
Volume firstVolume = volumeMap.values().iterator().next();
URI projectURI = firstVolume.getProject().getURI();
URI tenantURI = firstVolume.getTenant().getURI();
Project project = _dbClient.queryObject(Project.class, projectURI);
// the VPlex can see these new backend volumes.
if (!project.checkInternalFlags(Flag.INTERNAL_OBJECT) && vplexSystemProject != null && vplexSystemTenant != null) {
// If project is not set as an INTERAL_OBJECT then this is the case
// where native volume is moved into VPLEX.
// vplexSystemProject and vplexSystemTenant are passed in this case
// and we need to use that else backend export group gets visible
// in UI as the native volume project at this point is not a VPLEX
// project.
createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, arrayMap, volumeMap, vplexSystemProject, vplexSystemTenant, waitFor);
} else {
createWorkflowStepsForBlockVolumeExport(workflow, vplexSystem, arrayMap, volumeMap, projectURI, tenantURI, waitFor);
}
String transferSize = null;
// "rebuild set-transfer-speed" command.
if (setTransferSpeed != null) {
transferSize = migrationSpeedToTransferSizeMap.get(setTransferSpeed);
if (transferSize == null) {
_log.info("Transfer speed parameter {} is invalid", setTransferSpeed);
}
}
if (transferSize == null) {
String speed = customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.MIGRATION_SPEED, vplexSystem.getSystemType(), null);
_log.info("Migration speed is {}", speed);
transferSize = migrationSpeedToTransferSizeMap.get(speed);
}
// Now make a Step to create the VPlex Virtual volumes.
// This will be done from this controller.
String stepId = workflow.createStepId();
Workflow.Method vplexExecuteMethod = createVirtualVolumeFromImportMethod(vplexVolume.getStorageController(), vplexVolumeURI, importedVolumeURI, createdVolumeURI, vplexSystemProject, vplexSystemTenant, newCosURI, newLabel, transferSize);
Workflow.Method vplexRollbackMethod = null;
if (importedVolumeURI != null) {
// If importing to a local/distributed virtual volume, then
// rollback the VPlex create virtual volumes operation.
// We will restore the original volume.
vplexRollbackMethod = deleteVirtualVolumesMethod(vplexURI, vplexVolumeURIs, null);
} else {
// COP-16861: If rolling back an upgrade from local to distributed, then
// try to detach remote mirror and delete new artifacts created on VPLEX
// and clean up backend array volume.
// Without this rollback method with original code, if we failed to clean-up
// on VPLEX it used to still clean-up backed volume which would leave VPLEX
// volume in bad state. With this rollback we will clean-up backend array only
// if we were successful in clean-up on VPLEX.
// We will restore the VPlex local volume.
vplexRollbackMethod = rollbackUpgradeVirtualVolumeLocalToDistributedMethod(vplexURI, vplexVolume.getDeviceLabel(), vplexVolume.getNativeId(), stepId);
}
workflow.createStep(VPLEX_STEP, String.format("VPlex %s creating virtual volume", vplexSystem.getId().toString()), EXPORT_STEP, vplexURI, vplexSystem.getSystemType(), this.getClass(), vplexExecuteMethod, vplexRollbackMethod, stepId);
// simply trying to wait until the rebuild completes.
if (createdVolumeURI != null) {
createWorkflowStepForWaitOnRebuild(workflow, vplexSystem, vplexVolumeURI, VPLEX_STEP);
}
if (importedVolume != null && importedVolume.getConsistencyGroup() != null) {
// Add virtual volume to a Vplex consistency group.
ConsistencyGroupManager consistencyGroupManager = getConsistencyGroupManager(vplexVolume);
List<URI> volsForCG = Arrays.asList(vplexVolumeURI);
consistencyGroupManager.addStepsForCreateConsistencyGroup(workflow, VPLEX_STEP, vplexSystem, volsForCG, false);
}
// Finish up and execute the plan.
// The Workflow will handle the TaskCompleter
String successMessage;
if (importedVolumeURI != null) {
successMessage = "Import volume to VPLEX virtual volume successful for: " + vplexVolumeURIs.toString();
} else {
successMessage = "Upgrade local VPLEX volume to distributed successful for: " + vplexVolumeURIs.toString();
}
TaskCompleter completer = new VPlexTaskCompleter(Volume.class, volumeURIs, opId, null);
ImportRollbackHandler importRollbackHandler = new ImportRollbackHandler();
Object[] importRollbackHandlerArgs = new Object[] { importedVolumeURI, createdVolumeURI, vplexVolumeURI };
// TODO DUPP CWF COP-22431: This is a child workflow, needs idempotent check (1 of three flows seems like a
// subflow)
workflow.executePlan(completer, successMessage, null, null, importRollbackHandler, importRollbackHandlerArgs);
} catch (Exception ex) {
ServiceError serviceError;
if (importedVolumeURI != null) {
_log.error("Could not import volume for vplex: " + vplexURI, ex);
String opName = ResourceOperationTypeEnum.IMPORT_BLOCK_VOLUME.getName();
serviceError = VPlexApiException.errors.importVolumeFailedException(opName, ex);
} else {
_log.error("Could not upgrade volume for vplex: " + vplexURI, ex);
String opName = ResourceOperationTypeEnum.UPGRADE_VPLEX_LOCAL_TO_DISTRIBUTED.getName();
serviceError = VPlexApiException.errors.upgradeLocalToDistributedFailedException(opName, ex);
}
TaskCompleter completer = new VPlexTaskCompleter(Volume.class, volumeURIs, opId, null);
failStep(completer, opId, serviceError);
// here.
if (markInactive) {
// operation, rather than an upgrade of a local volume to distributed.
if ((importedVolumeURI != null) && (vplexVolume != null)) {
_dbClient.removeObject(vplexVolume);
}
// the VPLEX volume for deletion.
if (createdVolumeURI != null) {
Volume createdVolume = _dbClient.queryObject(Volume.class, createdVolumeURI);
if (createdVolume != null) {
_dbClient.removeObject(createdVolume);
}
}
// a non-VPLEX volume to VPLEX, this will be a public volume.
if ((importedVolume != null) && (importedVolume.checkInternalFlags(DataObject.Flag.INTERNAL_OBJECT))) {
_dbClient.removeObject(importedVolume);
}
}
}
}
use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.
the class VPlexDeviceController method prepareVolumeDescriptor.
/**
* Create a volume instance and VolumeDescriptor using the characteristics of the passed in source volume.
*
* @param source
* - The volume will be used to create the volume instance
* @param name
* - The new volume label
* @param type
* - VolumeDescriptor type
* @param size
* - The volume size
* @param isInternal
* -If the volume is internal
* @return - The newly created VolumeDescriptor
*/
private VolumeDescriptor prepareVolumeDescriptor(Volume source, String name, VolumeDescriptor.Type type, long size, boolean isInternal) {
Volume volume = new Volume();
volume.setId(URIUtil.createId(Volume.class));
volume.setLabel(name);
volume.setCapacity(size);
URI vpoolUri = source.getVirtualPool();
VirtualPool vpool = getDataObject(VirtualPool.class, vpoolUri, _dbClient);
volume.setThinlyProvisioned(VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(vpool.getSupportedProvisioningType()));
volume.setVirtualPool(vpool.getId());
URI projectId = source.getProject().getURI();
Project project = getDataObject(Project.class, projectId, _dbClient);
volume.setProject(new NamedURI(projectId, volume.getLabel()));
volume.setTenant(new NamedURI(project.getTenantOrg().getURI(), volume.getLabel()));
volume.setVirtualArray(source.getVirtualArray());
volume.setPool(source.getPool());
volume.setProtocol(source.getProtocol());
volume.setStorageController(source.getStorageController());
volume.setSystemType(source.getSystemType());
if (isInternal) {
volume.addInternalFlags(Flag.INTERNAL_OBJECT);
}
_dbClient.createObject(volume);
VirtualPoolCapabilityValuesWrapper capabilities = getCapabilities(source, size);
return new VolumeDescriptor(type, volume.getStorageController(), volume.getId(), volume.getPool(), capabilities);
}
use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.
the class VPlexDeviceController method promoteMirror.
/**
* This method creates the virtual volume from the detached mirror device.
*
* @param vplexURI
* The vplex storage system URI
* @param vplexMirrorURI
* The URI of the vplex mirror that needs to be promoted to the virtual volume
* @param promoteVolumeURI
* The URI of the volume will be used as a promoted vplex volume
* @param stepId
* The worflow stepId
*
* @throws WorkflowException
* When an error occurs updating the workflow step
* state.
*/
public void promoteMirror(URI vplexURI, URI vplexMirrorURI, URI promoteVolumeURI, String stepId) throws WorkflowException {
try {
WorkflowStepCompleter.stepExecuting(stepId);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplexURI, _dbClient);
VplexMirror vplexMirror = getDataObject(VplexMirror.class, vplexMirrorURI, _dbClient);
Volume sourceVplexVolume = getDataObject(Volume.class, vplexMirror.getSource().getURI(), _dbClient);
Volume promoteVolume = _dbClient.queryObject(Volume.class, promoteVolumeURI);
// Find virtual volume that should have been created when we did detach mirror.
// Virtual volume is created with the same name as the device name.
VPlexVirtualVolumeInfo vvInfo = client.findVirtualVolume(vplexMirror.getDeviceLabel(), null);
// Get the backend volume for this promoted VPLEX volume.
StringSet assocVolumes = vplexMirror.getAssociatedVolumes();
// Get the ViPR label for the promoted VPLEX volume.
String promotedLabel = String.format("%s-%s", sourceVplexVolume.getLabel(), vplexMirror.getLabel());
// Rename the vplex volume created using device detach mirror. If custom naming is enabled
// generate the custom name, else the name follows the default naming convention and must
// be renamed to append the "_vol" suffix.
String newVolumeName = null;
try {
if (CustomVolumeNamingUtils.isCustomVolumeNamingEnabled(customConfigHandler, DiscoveredDataObject.Type.vplex.name())) {
String customConfigName = CustomConfigConstants.CUSTOM_VOLUME_NAME;
Project project = _dbClient.queryObject(Project.class, promoteVolume.getProject().getURI());
TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, promoteVolume.getTenant().getURI());
DataSource customNameDataSource = CustomVolumeNamingUtils.getCustomConfigDataSource(project, tenant, promotedLabel, vvInfo.getWwn(), null, dataSourceFactory, customConfigName, _dbClient);
if (customNameDataSource != null) {
newVolumeName = CustomVolumeNamingUtils.getCustomName(customConfigHandler, customConfigName, customNameDataSource, DiscoveredDataObject.Type.vplex.name());
}
// Rename the vplex volume created using device detach mirror,
vvInfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(vvInfo, newVolumeName, client);
promotedLabel = newVolumeName;
} else {
// Build the name for volume so as to rename the vplex volume that is created
// with the same name as the device name to follow the name pattern _vol
// as the suffix for the vplex volumes
StringBuilder volumeNameBuilder = new StringBuilder();
volumeNameBuilder.append(vplexMirror.getDeviceLabel());
volumeNameBuilder.append(VPlexApiConstants.VIRTUAL_VOLUME_SUFFIX);
newVolumeName = volumeNameBuilder.toString();
// Rename the vplex volume created using device detach mirror,
vvInfo = CustomVolumeNamingUtils.renameVolumeOnVPlex(vvInfo, newVolumeName, client);
}
} catch (Exception e) {
_log.warn(String.format("Error renaming promoted VPLEX volume %s", promoteVolumeURI), e);
}
_log.info(String.format("Renamed promoted virtual volume: %s path: %s", vvInfo.getName(), vvInfo.getPath()));
// Fill in the details for the promoted vplex volume
promoteVolume.setLabel(promotedLabel);
promoteVolume.setNativeId(vvInfo.getPath());
promoteVolume.setNativeGuid(vvInfo.getPath());
promoteVolume.setDeviceLabel(vvInfo.getName());
promoteVolume.setThinlyProvisioned(vvInfo.isThinEnabled());
promoteVolume.setWWN(vvInfo.getWwn());
// For Vplex virtual volumes set allocated capacity to 0 (cop-18608)
promoteVolume.setAllocatedCapacity(0L);
promoteVolume.setCapacity(vplexMirror.getCapacity());
promoteVolume.setProvisionedCapacity(vplexMirror.getProvisionedCapacity());
promoteVolume.setVirtualPool(vplexMirror.getVirtualPool());
promoteVolume.setVirtualArray(vplexMirror.getVirtualArray());
promoteVolume.setStorageController(vplexMirror.getStorageController());
promoteVolume.setSystemType(DiscoveredDataObject.Type.vplex.name());
promoteVolume.setPool(NullColumnValueGetter.getNullURI());
promoteVolume.setAssociatedVolumes(new StringSet(assocVolumes));
promoteVolume.setThinlyProvisioned(vplexMirror.getThinlyProvisioned());
promoteVolume.setThinVolumePreAllocationSize(vplexMirror.getThinPreAllocationSize());
// VPLEX volumes created by VIPR have syncActive set to true hence setting same value for promoted vplex
// volumes
promoteVolume.setSyncActive(true);
// Also, we update the name portion of the project and tenant URIs
// to reflect the new name. This is necessary because the API
// to search for volumes by project, extracts the name portion of the
// project URI to get the volume name.
NamedURI namedURI = promoteVolume.getProject();
namedURI.setName(promotedLabel);
promoteVolume.setProject(namedURI);
namedURI = promoteVolume.getTenant();
namedURI.setName(promotedLabel);
promoteVolume.setTenant(namedURI);
// Remove mirror from the source VPLEX volume
sourceVplexVolume.getMirrors().remove(vplexMirror.getId().toString());
_dbClient.updateObject(sourceVplexVolume);
// Delete the mirror object
_dbClient.removeObject(vplexMirror);
// Persist changes for the newly promoted volume
_dbClient.updateObject(promoteVolume);
WorkflowStepCompleter.stepSucceded(stepId);
} catch (VPlexApiException vae) {
_log.error("Exception promoting mirror volume: " + vae.getMessage(), vae);
WorkflowStepCompleter.stepFailed(stepId, vae);
} catch (Exception ex) {
_log.error("Exception promoting mirror volume: " + ex.getMessage(), ex);
ServiceError serviceError = VPlexApiException.errors.promoteMirrorFailed(ex);
WorkflowStepCompleter.stepFailed(stepId, serviceError);
}
}
use of com.emc.storageos.db.client.model.Project 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);
}
}
use of com.emc.storageos.db.client.model.Project in project coprhd-controller by CoprHD.
the class ProtectionSetToBlockConsistencyGroupMigration method createRpBlockConsistencyGroups.
/**
* Create RP BlockConsistencyGroup objects for each ProtectionSet.
*/
private void createRpBlockConsistencyGroups() {
DbClient dbClient = this.getDbClient();
List<URI> protectionSetURIs = dbClient.queryByType(ProtectionSet.class, false);
Iterator<ProtectionSet> protectionSets = dbClient.queryIterativeObjects(ProtectionSet.class, protectionSetURIs);
while (protectionSets.hasNext()) {
ProtectionSet ps = protectionSets.next();
Project project = dbClient.queryObject(Project.class, ps.getProject());
BlockConsistencyGroup cg = new BlockConsistencyGroup();
cg.setId(URIUtil.createId(BlockConsistencyGroup.class));
cg.setLabel(ps.getLabel());
cg.setDeviceName(ps.getLabel());
cg.setType(BlockConsistencyGroup.Types.RP.toString());
cg.setProject(new NamedURI(project.getId(), project.getLabel()));
cg.setTenant(project.getTenantOrg());
dbClient.createObject(cg);
log.debug("Created ConsistencyGroup (id={}) based on ProtectionSet (id={})", cg.getId().toString(), ps.getId().toString());
// Organize the volumes by replication set
for (String protectionVolumeID : ps.getVolumes()) {
URI uri = URI.create(protectionVolumeID);
Volume protectionVolume = dbClient.queryObject(Volume.class, uri);
protectionVolume.addConsistencyGroup(cg.getId().toString());
dbClient.persistObject(protectionVolume);
log.debug("Volume (id={}) added to ConsistencyGroup (id={})", protectionVolume.getId().toString(), cg.getId().toString());
}
}
}
Aggregations