use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor 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.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method addStepsForImportClonesOfApplicationVolumes.
/**
* This method will add steps to import the clone of the source backend volumes,
* create clone VPlex virtual volumes
* create HA backend volume for clone virtual volume if distributed.
*
* @param workflow
* @param waitFor
* @param sourceVolumes
* @param opId
* @return
*/
public void addStepsForImportClonesOfApplicationVolumes(Workflow workflow, String waitFor, List<URI> sourceVolumes, String opId) {
_log.info("Creating steps for importing clones");
for (URI vplexSrcUri : sourceVolumes) {
Volume vplexSrcVolume = getDataObject(Volume.class, vplexSrcUri, _dbClient);
Volume backendSrc = VPlexUtil.getVPLEXBackendVolume(vplexSrcVolume, true, _dbClient);
long size = backendSrc.getProvisionedCapacity();
Volume backendHASrc = VPlexUtil.getVPLEXBackendVolume(vplexSrcVolume, false, _dbClient);
StringSet backSrcCopies = backendSrc.getFullCopies();
if (backSrcCopies != null && !backSrcCopies.isEmpty()) {
for (String copy : backSrcCopies) {
List<VolumeDescriptor> vplexVolumeDescriptors = new ArrayList<VolumeDescriptor>();
List<VolumeDescriptor> blockDescriptors = new ArrayList<VolumeDescriptor>();
Volume backCopy = getDataObject(Volume.class, URI.create(copy), _dbClient);
String name = backCopy.getLabel();
_log.info(String.format("Creating steps for import clone %s.", name));
VolumeDescriptor vplexCopyVolume = prepareVolumeDescriptor(vplexSrcVolume, name, VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, size, false);
Volume vplexCopy = getDataObject(Volume.class, vplexCopyVolume.getVolumeURI(), _dbClient);
vplexCopy.setAssociatedVolumes(new StringSet());
StringSet assVol = vplexCopy.getAssociatedVolumes();
if (null == assVol) {
assVol = new StringSet();
vplexCopy.setAssociatedVolumes(assVol);
}
assVol.add(backCopy.getId().toString());
VirtualPoolCapabilityValuesWrapper capabilities = getCapabilities(backCopy, size);
VolumeDescriptor backCopyDesc = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_IMPORT_VOLUME, backCopy.getStorageController(), backCopy.getId(), backCopy.getPool(), capabilities);
blockDescriptors.add(backCopyDesc);
if (backendHASrc != null) {
// distributed volume
name = name + "-ha";
VolumeDescriptor haDesc = prepareVolumeDescriptor(backendHASrc, name, VolumeDescriptor.Type.BLOCK_DATA, size, true);
blockDescriptors.add(haDesc);
assVol.add(haDesc.getVolumeURI().toString());
}
vplexCopy.setFullCopySetName(backCopy.getFullCopySetName());
vplexCopy.setAssociatedSourceVolume(vplexSrcUri);
StringSet srcClones = vplexSrcVolume.getFullCopies();
if (srcClones == null) {
srcClones = new StringSet();
}
srcClones.add(vplexCopy.getId().toString());
backCopy.setFullCopySetName(NullColumnValueGetter.getNullStr());
backCopy.addInternalFlags(Flag.INTERNAL_OBJECT);
_dbClient.updateObject(backCopy);
_dbClient.updateObject(vplexCopy);
_dbClient.updateObject(vplexSrcVolume);
vplexVolumeDescriptors.add(vplexCopyVolume);
createStepsForFullCopyImport(workflow, vplexSrcVolume.getStorageController(), vplexVolumeDescriptors, blockDescriptors, waitFor);
}
}
}
_log.info("Created workflow steps to import the backend full copies");
}
use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor 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.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method groupDescriptorsByReplicationGroup.
/**
* Group the given volume descriptors by backend Array Replication Group.
*
* Volume descriptors contains
* 1. VPLEX v-volume to be copied (source),
* 2. VPLEX copy v-volume to be created,
* 3. backend source volume to be created as clone for (1)'s backend volume
* 4. Empty volume to be created as HA backend volume for (2) in case of Distributed
*
* @param volumeDescriptors
* the volume descriptors
* @return the replication group to volume desciptors map
*/
private Map<String, List<VolumeDescriptor>> groupDescriptorsByReplicationGroup(List<VolumeDescriptor> volumeDescriptors) {
_log.info("Group the given desciptors based on backend Replication Group");
Map<String, List<VolumeDescriptor>> repGroupToVolumeDescriptors = new HashMap<String, List<VolumeDescriptor>>();
List<VolumeDescriptor> vplexVolumeDescriptors = VolumeDescriptor.filterByType(volumeDescriptors, new VolumeDescriptor.Type[] { Type.VPLEX_VIRT_VOLUME }, new VolumeDescriptor.Type[] {});
List<VolumeDescriptor> vplexSrcVolumeDescrs = getDescriptorsForFullCopySrcVolumes(vplexVolumeDescriptors);
// has only copy v-volumes
vplexVolumeDescriptors.removeAll(vplexSrcVolumeDescrs);
List<URI> vplexSrcVolumeURIs = VolumeDescriptor.getVolumeURIs(vplexSrcVolumeDescrs);
if (!vplexSrcVolumeURIs.isEmpty()) {
List<Volume> vplexSrcVolumes = ControllerUtils.queryVolumesByIterativeQuery(_dbClient, vplexSrcVolumeURIs);
// group volumes by Array Group
Map<String, List<Volume>> arrayGroupToVolumesMap = ControllerUtils.groupVolumesByArrayGroup(vplexSrcVolumes, _dbClient);
/**
* If only one entry of array replication group, put all descriptors
* Else group them according to array group
*/
if (arrayGroupToVolumesMap.size() == 1) {
String arrayGroupName = arrayGroupToVolumesMap.keySet().iterator().next();
_log.info("Single entry: Replication Group {}, Volume descriptors {}", arrayGroupName, Joiner.on(',').join(VolumeDescriptor.getVolumeURIs(volumeDescriptors)));
repGroupToVolumeDescriptors.put(arrayGroupName, volumeDescriptors);
} else {
for (String arrayGroupName : arrayGroupToVolumesMap.keySet()) {
// AG - Array Replication Group
_log.debug("Processing Replication Group {}", arrayGroupName);
List<Volume> vplexSrcVolumesAG = arrayGroupToVolumesMap.get(arrayGroupName);
List<VolumeDescriptor> descriptorsForAG = new ArrayList<VolumeDescriptor>();
// add VPLEX src volumes to descriptor list
Collection<URI> vplexSrcVolumesUrisAG = transform(vplexSrcVolumesAG, fctnDataObjectToID());
descriptorsForAG.addAll(getDescriptorsForURIsFromGivenList(vplexSrcVolumeDescrs, vplexSrcVolumesUrisAG));
for (VolumeDescriptor vplexCopyVolumeDesc : vplexVolumeDescriptors) {
URI vplexCopyVolumeURI = vplexCopyVolumeDesc.getVolumeURI();
Volume vplexCopyVolume = getDataObject(Volume.class, vplexCopyVolumeURI, _dbClient);
if (vplexSrcVolumesUrisAG.contains(vplexCopyVolume.getAssociatedSourceVolume())) {
_log.debug("Adding VPLEX copy volume descriptor for {}", vplexCopyVolumeURI);
// add VPLEX Copy volumes to descriptor list
descriptorsForAG.add(vplexCopyVolumeDesc);
// add Copy associated volumes to desciptor list
List<VolumeDescriptor> assocDescriptors = getDescriptorsForAssociatedVolumes(vplexCopyVolumeURI, volumeDescriptors);
descriptorsForAG.addAll(assocDescriptors);
}
}
_log.info("Entry: Replication Group {}, Volume descriptors {}", arrayGroupName, Joiner.on(',').join(VolumeDescriptor.getVolumeURIs(descriptorsForAG)));
repGroupToVolumeDescriptors.put(arrayGroupName, descriptorsForAG);
}
}
} else {
// non-application & clone for Snapshot
_log.info("Request is not for VPLEX volume, returning all.");
repGroupToVolumeDescriptors.put("SNAPSHOT_GROUP", volumeDescriptors);
}
return repGroupToVolumeDescriptors;
}
use of com.emc.storageos.blockorchestrationcontroller.VolumeDescriptor in project coprhd-controller by CoprHD.
the class VPlexDeviceController method buildVolumeMap.
/**
* Build a map of URI to cached Volumes for the underlying Storage Volumes that
* should be already present (and created).
*
* @param vplexSystem
* Only return Volume associated with this VPlex
* @param descriptors
* VolumeDescriptors
* @param VolmeDescriptor.Type
* used to filter descriptors
* @return Map<volumeURI, Volume>
*/
private Map<URI, Volume> buildVolumeMap(StorageSystem vplexSystem, List<VolumeDescriptor> descriptors, VolumeDescriptor.Type type) {
Map<URI, Volume> volumeMap = new HashMap<URI, Volume>();
// Get only the descriptors for the type if specified.
if (type != null) {
descriptors = VolumeDescriptor.filterByType(descriptors, new VolumeDescriptor.Type[] { type }, new VolumeDescriptor.Type[] {});
}
// Loop through all the descriptors / filtered descriptors
for (VolumeDescriptor desc : descriptors) {
// Check to see if the volumeMap already contains the volume URI.
if (volumeMap.containsKey(desc.getVolumeURI()) == false) {
// Load the volume from the descriptor
Volume volume = getDataObject(Volume.class, desc.getVolumeURI(), _dbClient);
if (vplexSystem == null) {
// If the vplexSystem hasn't been passed in, just add the volume the volumeMap.
volumeMap.put(desc.getVolumeURI(), volume);
} else {
// Check the storage controller of this Virtual Volume
if (desc.getType().equals(VolumeDescriptor.Type.VPLEX_VIRT_VOLUME) && volume.getStorageController().toString().equals(vplexSystem.getId().toString())) {
StringSet backingVolumes = volume.getAssociatedVolumes();
if (null == backingVolumes || backingVolumes.isEmpty()) {
_log.warn("VPLEX volume {} has no backend volumes.", volume.forDisplay());
} else {
// Add all backing volumes found to the volumeMap
for (String backingVolumeId : backingVolumes) {
URI backingVolumeURI = URI.create(backingVolumeId);
Volume backingVolume = getDataObject(Volume.class, backingVolumeURI, _dbClient);
volumeMap.put(backingVolumeURI, backingVolume);
}
}
}
}
}
}
return volumeMap;
}
Aggregations