use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method getDescriptorsForFullCopySrcVolumes.
/**
* Finds the volume descriptors in the passed list of volume descriptors that
* represents the VPLEX volumes to be copied.
*
* @param volumeDescriptors
* A list of volume descriptors.
*
* @return The volume descriptors that represents the VPLEX volumes to be
* copied.
*/
private List<VolumeDescriptor> getDescriptorsForFullCopySrcVolumes(List<VolumeDescriptor> volumeDescriptors) {
List<VolumeDescriptor> vplexSrcVolumeDescrs = new ArrayList<VolumeDescriptor>();
_log.info("Got all descriptors for VPLEX volumes");
Iterator<VolumeDescriptor> volumeDescrIter = volumeDescriptors.iterator();
while (volumeDescrIter.hasNext()) {
VolumeDescriptor descriptor = volumeDescrIter.next();
_log.info("Got descriptor for VPLEX volume {}", descriptor.getVolumeURI());
Object decriptorParam = descriptor.getParameters().get(VolumeDescriptor.PARAM_IS_COPY_SOURCE_ID);
if (decriptorParam != null) {
_log.info("Copy source param is not null");
boolean isCopySource = Boolean.parseBoolean(decriptorParam.toString());
if (isCopySource) {
_log.info("Found descriptor for VPLEX volume being copied");
vplexSrcVolumeDescrs.add(descriptor);
}
}
}
return vplexSrcVolumeDescrs;
}
use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method createDescriptorForBlockVolumeCreation.
/**
* Create a descriptor for the passed volume.
*
* @param storagePoolURI
* URI of the storage pool.
* @param volumeURI
* URI of the volume.
* @param storageSystemMap
* An OUT parameters specifying the list of storage
* systems on which volumes are created.
* @param volumeMap
* An OUT parameter specifying the full list volumes to be
* created.
*
* @return The descriptor for the pool volume.
*
* @throws IOException
* When an error occurs.
* @throws WorkflowException
*/
private VolumeDescriptor createDescriptorForBlockVolumeCreation(URI storagePoolURI, URI volumeURI, Map<URI, StorageSystem> storageSystemMap, Map<URI, Volume> volumeMap) throws IOException, WorkflowException {
// Get the storage pool to hold the backend block volumes.
StoragePool storagePool = _dbClient.queryObject(StoragePool.class, storagePoolURI);
// Get the storage system for this pool. Check the map
// as we cache the storage systems in the passed map, so
// we don't retrieve them multiple times from the database.
URI storageSystemURI = storagePool.getStorageDevice();
StorageSystem storageSystem = null;
if (storageSystemMap.containsKey(storageSystemURI)) {
storageSystem = storageSystemMap.get(storageSystemURI);
} else {
storageSystem = _dbClient.queryObject(StorageSystem.class, storageSystemURI);
storageSystemMap.put(storageSystemURI, storageSystem);
}
// Get the volume.
Volume volume = _dbClient.queryObject(Volume.class, volumeURI);
// Cache the volumes, like the storage systems, in the
// passed volume map so that we don't access the database
// multiple time.
volumeMap.put(volumeURI, volume);
// Create a descriptor for the volume.
URI cgURI = null;
if (!NullColumnValueGetter.isNullURI(volume.getConsistencyGroup())) {
cgURI = volume.getConsistencyGroup();
}
VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();
capabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, volume.getCapacity());
capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
return new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, storageSystemURI, volumeURI, storagePoolURI, cgURI, capabilities);
}
use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForExpandVolume.
/*
* (non-Javadoc)
* Method to add workflow steps for VPLEX volume expansion
*/
@Override
public String addStepsForExpandVolume(Workflow workflow, String waitFor, List<VolumeDescriptor> volumeDescriptors, String taskId) throws InternalException {
List<VolumeDescriptor> vplexVolumeDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, VolumeDescriptor.Type.RP_VPLEX_VIRT_SOURCE, VolumeDescriptor.Type.RP_VPLEX_VIRT_TARGET, VolumeDescriptor.Type.RP_EXISTING_SOURCE }, new VolumeDescriptor.Type[] {});
if (vplexVolumeDescriptors == null || vplexVolumeDescriptors.isEmpty()) {
return waitFor;
}
for (VolumeDescriptor descriptor : vplexVolumeDescriptors) {
Volume vplexVolume = _dbClient.queryObject(Volume.class, descriptor.getVolumeURI());
URI vplexURI = vplexVolume.getStorageController();
StorageSystem vplexSystem = getDataObject(StorageSystem.class, vplexURI, _dbClient);
Workflow.Method expandVolumeNativelyMethod = new Workflow.Method(EXPAND_VOLUME_NATIVELY_METHOD_NAME, vplexURI, vplexVolume.getId(), descriptor.getVolumeSize());
String createStepId = workflow.createStepId();
workflow.createStep(VIRTUAL_VOLUME_EXPAND_STEP, String.format("Expand virtual volume %s for VPlex volume %s", vplexVolume.getId(), vplexVolume.getId()), waitFor, vplexURI, vplexSystem.getSystemType(), this.getClass(), expandVolumeNativelyMethod, null, createStepId);
}
return VIRTUAL_VOLUME_EXPAND_STEP;
}
use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor 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.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForCreateFullCopy.
/*
* (non-Javadoc)
*
* @see
* com.emc.storageos.blockorchestrationcontroller.BlockOrchestrationInterface#addStepsForCreateFullCopy(com.emc.
* storageos.workflow.Workflow, java.lang.String, java.util.List, java.lang.String)
*/
@Override
public String addStepsForCreateFullCopy(Workflow workflow, String waitFor, List<VolumeDescriptor> volumeDescriptors, String taskId) throws InternalException {
List<VolumeDescriptor> blockVolmeDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { VolumeDescriptor.Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
// If no volumes to create, just return
if (blockVolmeDescriptors.isEmpty()) {
return waitFor;
}
URI vplexUri = null;
for (VolumeDescriptor descriptor : blockVolmeDescriptors) {
Volume volume = _dbClient.queryObject(Volume.class, descriptor.getVolumeURI());
if (volume != null && !volume.getInactive()) {
vplexUri = volume.getStorageController();
break;
}
}
String stepId = workflow.createStepId();
// Now add the steps to create the block snapshot on the storage system
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, vplexUri);
Workflow.Method createFullCopyMethod = new Workflow.Method(CREATE_FULL_COPY_METHOD_NAME, vplexUri, volumeDescriptors);
Workflow.Method nullRollbackMethod = new Workflow.Method(ROLLBACK_METHOD_NULL);
waitFor = workflow.createStep(CREATE_FULL_COPY_METHOD_NAME, "Create Block Full Copy for VPlex", waitFor, storageSystem.getId(), storageSystem.getSystemType(), this.getClass(), createFullCopyMethod, nullRollbackMethod, stepId);
_log.info(String.format("Added %s step [%s] in workflow", CREATE_FULL_COPY_METHOD_NAME, stepId));
return waitFor;
}
Aggregations