use of com.emc.storageos.db.client.model.VirtualArray in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method cgPoolsHaveAvailableCapacity.
/**
* Computes if the existing storage pools used have sufficient capacity to satisfy the placement request
*
* @param sourceVolume The Source volume to use for the capacity checks
* @param capabilities Capabilities reference
* @param vpool The vpool being used
* @param protectionVarrays The protection Varrays of the vpool
* @return true if capacity is available, false otherwise.
*/
private boolean cgPoolsHaveAvailableCapacity(Volume sourceVolume, VirtualPoolCapabilityValuesWrapper capabilities, VirtualPool vpool, List<VirtualArray> protectionVarrays) {
boolean cgPoolsHaveAvailableCapacity = true;
Map<URI, Long> storagePoolRequiredCapacity = new HashMap<URI, Long>();
Map<URI, StoragePool> storagePoolCache = new HashMap<URI, StoragePool>();
// Keep a map with some extra info in it so the logs have a better description of
// why we can't reuse a particular pool.
Map<URI, String> storagePoolErrorDetail = new HashMap<URI, String>();
_log.info(String.format("Checking if the existing storage pools used have sufficient capacity to satisfy the placement request..."));
if (sourceVolume != null) {
// TODO: need to update code below to look like the stuff Bharath added for multiple resources
long sourceVolumesRequiredCapacity = getSizeInKB(capabilities.getSize() * capabilities.getResourceCount());
if (RPHelper.isVPlexVolume(sourceVolume, dbClient)) {
if (null == sourceVolume.getAssociatedVolumes() || sourceVolume.getAssociatedVolumes().isEmpty()) {
_log.error("VPLEX volume {} has no backend volumes.", sourceVolume.forDisplay());
throw InternalServerErrorException.internalServerErrors.noAssociatedVolumesForVPLEXVolume(sourceVolume.forDisplay());
}
for (String backingVolumeId : sourceVolume.getAssociatedVolumes()) {
Volume backingVolume = dbClient.queryObject(Volume.class, URI.create(backingVolumeId));
StoragePool backingVolumePool = dbClient.queryObject(StoragePool.class, backingVolume.getPool());
storagePoolCache.put(backingVolumePool.getId(), backingVolumePool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, backingVolumePool.getId(), sourceVolumesRequiredCapacity);
storagePoolErrorDetail.put(backingVolumePool.getId(), sourceVolume.getPersonality());
}
} else {
StoragePool sourcePool = dbClient.queryObject(StoragePool.class, sourceVolume.getPool());
storagePoolCache.put(sourcePool.getId(), sourcePool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, sourcePool.getId(), sourceVolumesRequiredCapacity);
storagePoolErrorDetail.put(sourcePool.getId(), sourceVolume.getPersonality());
}
List<Volume> sourceJournals = RPHelper.findExistingJournalsForCopy(dbClient, sourceVolume.getConsistencyGroup(), sourceVolume.getRpCopyName());
Volume sourceJournal = sourceJournals.get(0);
if (sourceJournal == null) {
_log.error(String.format("No existing source journal found in CG [%s] for copy [%s], returning false", sourceVolume.getConsistencyGroup(), sourceVolume.getRpCopyName()));
throw APIException.badRequests.unableToFindSuitableJournalRecommendation();
}
long sourceJournalSizePerPolicy = RPHelper.getJournalSizeGivenPolicy(String.valueOf(capabilities.getSize()), vpool.getJournalSize(), capabilities.getResourceCount());
long sourceJournalVolumesRequiredCapacity = getSizeInKB(sourceJournalSizePerPolicy);
if (RPHelper.isVPlexVolume(sourceJournal, dbClient)) {
for (String backingVolumeId : sourceJournal.getAssociatedVolumes()) {
Volume backingVolume = dbClient.queryObject(Volume.class, URI.create(backingVolumeId));
StoragePool backingVolumePool = dbClient.queryObject(StoragePool.class, backingVolume.getPool());
storagePoolCache.put(backingVolumePool.getId(), backingVolumePool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, backingVolumePool.getId(), sourceJournalVolumesRequiredCapacity);
storagePoolErrorDetail.put(backingVolumePool.getId(), sourceVolume.getPersonality() + " " + sourceJournal.getPersonality());
}
} else {
StoragePool sourceJournalPool = dbClient.queryObject(StoragePool.class, sourceJournal.getPool());
storagePoolCache.put(sourceJournalPool.getId(), sourceJournalPool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, sourceJournalPool.getId(), sourceJournalVolumesRequiredCapacity);
storagePoolErrorDetail.put(sourceJournalPool.getId(), sourceVolume.getPersonality() + " " + sourceJournal.getPersonality());
}
if (sourceVolume.getRpTargets() != null) {
for (VirtualArray protectionVarray : protectionVarrays) {
// Find the pools that apply to this virtual
VpoolProtectionVarraySettings settings = RPHelper.getProtectionSettings(vpool, protectionVarray, dbClient);
// If there was no vpool specified with the protection settings, use the base vpool for this varray.
VirtualPool protectionVpool = vpool;
if (settings.getVirtualPool() != null) {
protectionVpool = dbClient.queryObject(VirtualPool.class, settings.getVirtualPool());
}
// Find the existing source volume target that corresponds to this protection
// virtual array. We need to see if the storage pool has capacity for another
// target volume.
Volume targetVolume = getTargetVolumeForProtectionVirtualArray(sourceVolume, protectionVarray);
// Target volumes will be the same size as the source
long targetVolumeRequiredCapacity = getSizeInKB(capabilities.getSize());
if (RPHelper.isVPlexVolume(targetVolume, dbClient)) {
for (String backingVolumeId : targetVolume.getAssociatedVolumes()) {
Volume backingVolume = dbClient.queryObject(Volume.class, URI.create(backingVolumeId));
StoragePool backingVolumePool = dbClient.queryObject(StoragePool.class, backingVolume.getPool());
storagePoolCache.put(backingVolumePool.getId(), backingVolumePool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, backingVolumePool.getId(), targetVolumeRequiredCapacity);
storagePoolErrorDetail.put(backingVolumePool.getId(), targetVolume.getPersonality());
}
} else {
StoragePool targetPool = dbClient.queryObject(StoragePool.class, targetVolume.getPool());
storagePoolCache.put(targetPool.getId(), targetPool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, targetPool.getId(), targetVolumeRequiredCapacity);
storagePoolErrorDetail.put(targetPool.getId(), targetVolume.getPersonality());
}
// Account for the target journal volumes.
List<Volume> targetJournals = RPHelper.findExistingJournalsForCopy(dbClient, targetVolume.getConsistencyGroup(), targetVolume.getRpCopyName());
Volume targetJournalVolume = targetJournals.get(0);
if (targetJournalVolume == null) {
_log.error(String.format("No existing target journal found in CG [%s] for copy [%s], returning false", targetVolume.getConsistencyGroup(), targetVolume.getRpCopyName()));
throw APIException.badRequests.unableToFindSuitableJournalRecommendation();
}
long targetJournalSizePerPolicy = RPHelper.getJournalSizeGivenPolicy(String.valueOf(capabilities.getSize()), protectionVpool.getJournalSize(), capabilities.getResourceCount());
long targetJournalVolumeRequiredCapacity = getSizeInKB(targetJournalSizePerPolicy);
if (RPHelper.isVPlexVolume(targetJournalVolume, dbClient)) {
for (String backingVolumeId : targetJournalVolume.getAssociatedVolumes()) {
Volume backingVolume = dbClient.queryObject(Volume.class, URI.create(backingVolumeId));
StoragePool backingVolumePool = dbClient.queryObject(StoragePool.class, backingVolume.getPool());
storagePoolCache.put(backingVolumePool.getId(), backingVolumePool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, backingVolumePool.getId(), targetJournalVolumeRequiredCapacity);
storagePoolErrorDetail.put(backingVolumePool.getId(), targetVolume.getPersonality() + " " + targetJournalVolume.getPersonality());
}
} else {
StoragePool targetJournalPool = dbClient.queryObject(StoragePool.class, targetJournalVolume.getPool());
storagePoolCache.put(targetJournalPool.getId(), targetJournalPool);
updateStoragePoolRequiredCapacityMap(storagePoolRequiredCapacity, targetJournalPool.getId(), targetJournalVolumeRequiredCapacity);
storagePoolErrorDetail.put(targetJournalPool.getId(), targetVolume.getPersonality() + " " + targetJournalVolume.getPersonality());
}
}
}
BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, capabilities.getBlockConsistencyGroup());
for (Map.Entry<URI, Long> storagePoolEntry : storagePoolRequiredCapacity.entrySet()) {
StoragePool storagePool = storagePoolCache.get(storagePoolEntry.getKey());
long freeCapacity = storagePool.getFreeCapacity();
long requiredCapacity = storagePoolEntry.getValue().longValue();
if (requiredCapacity > freeCapacity) {
cgPoolsHaveAvailableCapacity = false;
_log.info(String.format("Unable to fully align placement with existing %s volume from " + "RecoverPoint consistency group [%s]. Required capacity is %s and we can't re-use storage pool [%s] " + "as it only has %s free capacity.", storagePoolErrorDetail.get(storagePool.getId()), sourceVolume.getLabel(), cg.getLabel(), SizeUtil.translateSize(requiredCapacity, SizeUtil.SIZE_GB), storagePool.getLabel(), SizeUtil.translateSize(freeCapacity, SizeUtil.SIZE_GB)));
break;
} else {
_log.info(String.format("Storage pool [%s], used by consistency group [%s], has the required capacity and will be " + "used for this placement request.", storagePool.getLabel(), cg.getLabel()));
}
}
}
return cgPoolsHaveAvailableCapacity;
}
use of com.emc.storageos.db.client.model.VirtualArray in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method swapSrcAndHAIfNeeded.
/**
* This method is driven by the flag on the RP+VPLEX Source Vpool to use HA as RP Source or not.
* When that flag is set we use the HA Varray and HA Vpool as the Sources for placement. Consequently,
* the Source Varray and Source VPool are then used for HA placement.
*
* We may not need to swap if the flag isn't set, but this method returns the RPVPlexVarryVpool object
* regardless so we can then just reference the resources in that object to pass down to the rest of the
* scheduler methods.
*
* @param srcVarray Original src varray
* @param srcVpool Original src vpool
* @return RPVPlexVarryVpool which contains references to the src varray, src vpool, ha varray, ha vpool
*/
private SwapContainer swapSrcAndHAIfNeeded(VirtualArray srcVarray, VirtualPool srcVpool) {
VirtualArray haVarray = null;
VirtualPool haVpool = null;
SwapContainer container = new SwapContainer();
container.setSrcVarray(srcVarray);
container.setSrcVpool(srcVpool);
container.setHaVarray(haVarray);
container.setHaVpool(haVpool);
// Potentially will swap src and ha, returns the container.
container = initializeSwapContainer(container, dbClient);
return container;
}
use of com.emc.storageos.db.client.model.VirtualArray in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method getProtectionVirtualArraysForVirtualPool.
/**
* Gets and verifies that the protection varrays passed in the request are
* accessible to the tenant.
*
* @param project A reference to the project.
* @param vpool class of service, contains protection varrays
* @return A reference to the varrays
* @throws java.net.URISyntaxException
* @throws com.emc.storageos.db.exceptions.DatabaseException
*/
public static List<VirtualArray> getProtectionVirtualArraysForVirtualPool(Project project, VirtualPool vpool, DbClient dbClient, PermissionsHelper permissionHelper) {
List<VirtualArray> protectionVirtualArrays = new ArrayList<VirtualArray>();
if (vpool.getProtectionVarraySettings() != null) {
for (String protectionVirtualArray : vpool.getProtectionVarraySettings().keySet()) {
try {
VirtualArray varray = dbClient.queryObject(VirtualArray.class, new URI(protectionVirtualArray));
protectionVirtualArrays.add(varray);
permissionHelper.checkTenantHasAccessToVirtualArray(project.getTenantOrg().getURI(), varray);
} catch (URISyntaxException e) {
throw APIException.badRequests.invalidURI(protectionVirtualArray);
}
}
}
return protectionVirtualArrays;
}
use of com.emc.storageos.db.client.model.VirtualArray in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method initializeSwapContainer.
/**
* This function will swap src and ha varrays and src and ha vpools IF
* the src vpool has specified this.
*
* @param srcVarray Source varray
* @param srcVpool Source vpool
* @param haVarray HA varray
* @param haVpool HA vpool
* @param dbClient DB Client reference
*/
public static SwapContainer initializeSwapContainer(SwapContainer container, DbClient dbClient) {
// Refresh vpools in case previous activities have changed their temporal representation.
VirtualArray srcVarray = container.getSrcVarray();
VirtualPool srcVpool = dbClient.queryObject(VirtualPool.class, container.getSrcVpool().getId());
VirtualArray haVarray = container.getHaVarray();
VirtualPool haVpool = container.getHaVpool();
// as the RP Source.
if (VirtualPool.isRPVPlexProtectHASide(srcVpool)) {
// Get the HA Varray connected to RP
haVarray = dbClient.queryObject(VirtualArray.class, URI.create(srcVpool.getHaVarrayConnectedToRp()));
_log.info(String.format("Source Vpool[%s] indicates that we should use HA Varray[%s] as RP Source.", srcVpool.getLabel(), haVarray.getLabel()));
String haVpoolId = srcVpool.getHaVarrayVpoolMap().get(srcVpool.getHaVarrayConnectedToRp());
if (haVpoolId != null && !haVpoolId.isEmpty() && !haVpoolId.equals(NullColumnValueGetter.getNullStr())) {
haVpool = dbClient.queryObject(VirtualPool.class, URI.create(haVpoolId));
_log.info(String.format("HA Vpool has been defined [%s]", haVpool.getLabel()));
// Temporarily inherit the HA and Protection Settings/RP specific info from Source Vpool.
// These modifications will not be persisted to the db.
haVpool.setProtectionVarraySettings(srcVpool.getProtectionVarraySettings());
haVpool.setRpCopyMode(srcVpool.getRpCopyMode());
haVpool.setRpRpoType(srcVpool.getRpRpoType());
haVpool.setRpRpoValue(srcVpool.getRpRpoValue());
haVpool.setMultivolumeConsistency(srcVpool.getMultivolumeConsistency());
haVpool.setHighAvailability(srcVpool.getHighAvailability());
haVpool.setMetroPoint(srcVpool.getMetroPoint());
haVpool.setHaVarrayConnectedToRp(srcVarray.getId().toString());
haVpool.setJournalSize(NullColumnValueGetter.isNotNullValue(srcVpool.getJournalSize()) ? srcVpool.getJournalSize() : null);
} else {
_log.info(String.format("HA Vpool has not been defined, using Source Vpool[%s].", srcVpool.getLabel()));
// Use source vpool. That means the source vpool will have to have the HA varray
// added to it, otherwise this will not work. That is done during vpool create via the UI
// by the user.
// This is the same behaviour as VPLEX. So we're just reusing that behaviour.
// If not done, placement will fail.
haVpool = srcVpool;
}
// Ensure that we define the haVarrayVpoolMap on the haVpool to use srcVarray and srcVpool.
StringMap haVarrayVpoolMap = new StringMap();
haVarrayVpoolMap.put(srcVarray.getId().toString(), srcVpool.getId().toString());
haVpool.setHaVarrayVpoolMap(haVarrayVpoolMap);
_log.info(String.format("HA Varray[%s] and HA Vpool[%s] will be used as Source Varray and Source Vpool.", haVarray.getLabel(), haVpool.getLabel()));
_log.info(String.format("Source Varray[%s] and Source Vpool[%s] will be used as HA Varray and HA Vpool.", srcVarray.getLabel(), srcVpool.getLabel()));
// Now HA becomes Source and Source becomes HA.
VirtualArray tempVarray = srcVarray;
VirtualPool tempVpool = srcVpool;
container.setSrcVarray(haVarray);
container.setSrcVpool(haVpool);
container.setHaVarray(tempVarray);
container.setHaVpool(tempVpool);
}
return container;
}
use of com.emc.storageos.db.client.model.VirtualArray in project coprhd-controller by CoprHD.
the class SRDFScheduler method getSRDFPoolMappings.
/**
* This method takes the source varray and a list of possible pools provided by common Bourne
* placement logic and returns a list of source/destination pairs that are capable of SRDF
*
* When this method returns, we have a list of the possible source and destination pools This is
* later used determine which entries in the list share a an SRDF link via the same source
* storage system, and therefore can satisfy the request to protect to ALL virtual arrays.
*
* @param varray
* Source Varray
* @param poolList
* Pool List from common placement logic for source
* @param varrayPoolMap
* Pool List from common placement logic for target varrays
* @return a list of source/destination pools
*/
private Set<SRDFPoolMapping> getSRDFPoolMappings(final VirtualArray varray, final List<StoragePool> poolList, final Map<VirtualArray, List<StoragePool>> varrayPoolMap, final VirtualPool vpool, final Volume vpoolChangeVolume, final long size) {
// Maps to reduce hits on the database for objects we'll need more than one time during
// calculations
Map<StoragePool, StorageSystem> sourcePoolStorageMap = new HashMap<StoragePool, StorageSystem>();
Map<StoragePool, StorageSystem> destPoolStorageMap = new HashMap<StoragePool, StorageSystem>();
for (StoragePool sourcePool : poolList) {
sourcePoolStorageMap.put(sourcePool, _dbClient.queryObject(StorageSystem.class, sourcePool.getStorageDevice()));
}
for (VirtualArray targetVarray : varrayPoolMap.keySet()) {
for (StoragePool destPool : varrayPoolMap.get(targetVarray)) {
destPoolStorageMap.put(destPool, _dbClient.queryObject(StorageSystem.class, destPool.getStorageDevice()));
}
}
Set<SRDFPoolMapping> srcDestPoolList = new TreeSet<SRDFPoolMapping>();
// For each storage pool that is considered a candidate for source...
for (StoragePool sourcePool : sourcePoolStorageMap.keySet()) {
// Go through each target virtual array and attempt to add an entry in the pool mapping
for (VirtualArray targetVarray : varrayPoolMap.keySet()) {
// Add an entry to the mapping if the source and destination storage systems can see
// each other.
populateSRDFPoolList(varray, destPoolStorageMap, srcDestPoolList, sourcePool, targetVarray, vpool, vpoolChangeVolume, size);
}
}
return srcDestPoolList;
}
Aggregations