use of com.emc.storageos.db.client.model.VpoolProtectionVarraySettings in project coprhd-controller by CoprHD.
the class RPUnManagedObjectDiscoverer method filterProtectedVpools.
/**
* Filter vpools from the qualified list.
* rpSource true: Filter out anything other than RP source vpools
* rpSource false: Filter out RP and SRDF source vpools
*
* @param dbClient dbclient
* @param unManagedVolume unmanaged volume
* @param personality SOURCE, TARGET, or METADATA
*/
private void filterProtectedVpools(DbClient dbClient, UnManagedVolume unManagedVolume, String personality) {
if (unManagedVolume.getSupportedVpoolUris() != null && !unManagedVolume.getSupportedVpoolUris().isEmpty()) {
Iterator<VirtualPool> vpoolItr = dbClient.queryIterativeObjects(VirtualPool.class, URIUtil.toURIList(unManagedVolume.getSupportedVpoolUris()));
while (vpoolItr.hasNext()) {
boolean remove = false;
VirtualPool vpool = vpoolItr.next();
// If this is an SRDF source vpool, we can filter out since we're dealing with an RP volume
if (vpool.getProtectionRemoteCopySettings() != null) {
remove = true;
}
// The vpool is an RP vpool (has settings) and target vpools are non-null
if (vpool.getProtectionVarraySettings() != null && ((Volume.PersonalityTypes.TARGET.name().equalsIgnoreCase(personality)) || Volume.PersonalityTypes.METADATA.name().equalsIgnoreCase(personality))) {
boolean foundEmptyTargetVpool = false;
Map<URI, VpoolProtectionVarraySettings> settings = VirtualPool.getProtectionSettings(vpool, dbClient);
for (Map.Entry<URI, VpoolProtectionVarraySettings> setting : settings.entrySet()) {
if (NullColumnValueGetter.isNullURI(setting.getValue().getVirtualPool())) {
foundEmptyTargetVpool = true;
break;
}
}
// If this is a journal volume, also check the journal vpools. If they're not set, we cannot filter out this vpool.
if (Volume.PersonalityTypes.METADATA.name().equalsIgnoreCase(personality) && (NullColumnValueGetter.isNullValue(vpool.getJournalVpool()) || NullColumnValueGetter.isNullValue(vpool.getStandbyJournalVpool()))) {
foundEmptyTargetVpool = true;
}
// you would never assign your target volume to this source vpool, so filter it out.
if (!foundEmptyTargetVpool) {
remove = true;
}
}
if (Volume.PersonalityTypes.SOURCE.name().equalsIgnoreCase(personality)) {
if (!VirtualPool.vPoolSpecifiesProtection(vpool)) {
// If this an RP source, the vpool must be an RP vpool
remove = true;
} else if (unManagedVolume.getVolumeInformation().containsKey(SupportedVolumeInformation.RP_STANDBY_INTERNAL_SITENAME.toString()) && !VirtualPool.vPoolSpecifiesMetroPoint(vpool)) {
// Since this is a Source volume with the presence of RP_STANDBY_INTERNAL_SITENAME
// it indicates that this volume is MetroPoint, if we get here, this is vpool
// must be filtered out since it's not MP.
remove = true;
}
}
if (remove) {
log.info("Removing virtual pool " + vpool.getLabel() + " from supported vpools for unmanaged volume: " + unManagedVolume.getLabel());
unManagedVolume.getSupportedVpoolUris().remove(vpool.getId().toString());
}
}
}
}
use of com.emc.storageos.db.client.model.VpoolProtectionVarraySettings in project coprhd-controller by CoprHD.
the class PlacementManager method hasHaRpCopyTarget.
/**
* Determines if any of the RP targets has HA (VPlex local/distributed)
* specified. This method should be called in determining if the
* rpvplex scheduler should be used, specifically for non-virtual to
* virtual protection. This is currently not supported and is why the
* condition was removed from getBlockServiceImpl().
*
* @return true if there is at least 1 HA RP copy target.
*/
private boolean hasHaRpCopyTarget(VirtualPool vpool) {
// Check if any of the RP copies contains a protection virtual pool that specifies
// high availability. This would indicate mixed protection, therefore we need
// to use the RP/VPLEX scheduler.
boolean rpVPlex = false;
if (vpool.getProtectionVarraySettings() != null && !vpool.getProtectionVarraySettings().isEmpty()) {
for (String protectionVarraURI : vpool.getProtectionVarraySettings().keySet()) {
String settingsURI = vpool.getProtectionVarraySettings().get(protectionVarraURI);
VpoolProtectionVarraySettings settings = dbClient.queryObject(VpoolProtectionVarraySettings.class, URI.create(settingsURI));
URI protectionVpoolId = vpool.getId();
if (settings.getVirtualPool() != null) {
protectionVpoolId = settings.getVirtualPool();
}
VirtualPool protectionVpool = dbClient.queryObject(VirtualPool.class, protectionVpoolId);
if (VirtualPool.vPoolSpecifiesHighAvailability(protectionVpool)) {
rpVPlex = true;
break;
}
}
}
return rpVPlex;
}
use of com.emc.storageos.db.client.model.VpoolProtectionVarraySettings in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method verifyTargetStoragePoolAvailability.
/**
* Based on the current volume request's virtual pool, determine the protection settings and use them to determine
* the protection virtual arrays and the associated protection virtual pool. Pass the protection virtual array
* along with the existing target/target-journal volume to determine if the storage pools align
*
* @param volume - existing volume
* @param vpool - virtual pool being used in the current volume request
* @return true or false depending whether the existing volume's storage pool is available to the current virtual pool of the
* request
*/
private boolean verifyTargetStoragePoolAvailability(Volume volume, VirtualPool vpool) {
if (volume.checkPersonality(Volume.PersonalityTypes.METADATA.name())) {
VirtualPool journalVpool = dbClient.queryObject(VirtualPool.class, volume.getVirtualPool());
if (verifyStoragePoolAvailability(journalVpool, volume)) {
return true;
}
} else {
if (vpool.getProtectionVarraySettings() != null && !vpool.getProtectionVarraySettings().isEmpty()) {
String settingsURI = vpool.getProtectionVarraySettings().get(volume.getVirtualArray().toString());
VpoolProtectionVarraySettings settings = dbClient.queryObject(VpoolProtectionVarraySettings.class, URI.create(settingsURI));
// If there was no vpool specified with the protection settings, use the base vpool for the new volume request
URI protectionVpoolId = vpool.getId();
if (settings.getVirtualPool() != null) {
protectionVpoolId = settings.getVirtualPool();
}
VirtualPool protectionVpool = dbClient.queryObject(VirtualPool.class, protectionVpoolId);
if (verifyStoragePoolAvailability(protectionVpool, volume)) {
return true;
}
}
}
return false;
}
use of com.emc.storageos.db.client.model.VpoolProtectionVarraySettings in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method findSolution.
/**
* Placement method that assembles recommendation objects based on the vpool and protection varrays.
* Recursive: peels off one protectionVarray to hopefully assemble one Protection object within the recommendation object, then calls
* itself
* with the remainder of the protectionVarrays. If it fails to find a Protection for that protectionVarray, it returns failure and puts
* the
* protectionVarray back on the list.
*
* @param rpProtectionRecommendation - Top level RP recommendation
* @param sourceRecommendation - Source Recommendation against which we need to find the solution for targets
* @param varray - Source Virtual Array
* @param vpool - Source Virtual Pool
* @param targetVarrays - List of protection Virtual Arrays
* @param capabilities - Virtual Pool capabilities
* @param requestedCount - Resource count desired
* @param isMetroPoint - Boolean indicating whether this is MetroPoint
* @param activeSourceRecommendation - Primary Recommendation in case of MetroPoint. This field is null except for when we are finding
* solution for MP standby
* @param project - Project
* @return - True if protection solution was found, false otherwise.
*/
private boolean findSolution(RPProtectionRecommendation rpProtectionRecommendation, RPRecommendation sourceRecommendation, VirtualArray varray, VirtualPool vpool, List<VirtualArray> targetVarrays, VirtualPoolCapabilityValuesWrapper capabilities, int requestedCount, boolean isMetroPoint, RPRecommendation activeSourceRecommendation, Project project) {
if (targetVarrays.isEmpty()) {
_log.info("RP Placement : Could not find target solution because there are no protection virtual arrays specified.");
return false;
}
// Find the virtual pool that applies to this protection virtual array
// We are recursively calling into "findSolution", so pop the next protectionVarray off the top of the
// passed in list of protectionVarrays. This protectionVarray will be removed from the list before
// recursively calling back into the method (in the case that we do not find a solution).
VirtualArray targetVarray = targetVarrays.get(0);
placementStatus.getProcessedProtectionVArrays().put(targetVarray.getId(), true);
// Find the correct target vpool. It is either implicitly the same as the source vpool or has been
// explicitly set by the user.
VpoolProtectionVarraySettings protectionSettings = RPHelper.getProtectionSettings(vpool, targetVarray, dbClient);
// If there was no vpool specified with the protection settings, use the base vpool for this varray.
VirtualPool targetVpool = vpool;
if (protectionSettings.getVirtualPool() != null) {
targetVpool = dbClient.queryObject(VirtualPool.class, protectionSettings.getVirtualPool());
}
_log.info("RP Placement : Determining placement on protection varray : " + targetVarray.getLabel());
// Find matching pools for the protection varray
VirtualPoolCapabilityValuesWrapper newCapabilities = new VirtualPoolCapabilityValuesWrapper(capabilities);
newCapabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, requestedCount);
List<Recommendation> targetPoolRecommendations = new ArrayList<Recommendation>();
// If MP remote target is specified, fetch the target recommendation from the active when looking at the standby side.
if (isMetroPoint && activeSourceRecommendation != null && isMetroPointProtectionSpecified(activeSourceRecommendation, ProtectionType.REMOTE)) {
StringBuffer unusedTargets = new StringBuffer();
Recommendation targetPoolRecommendation = new Recommendation();
for (RPRecommendation targetRec : activeSourceRecommendation.getTargetRecommendations()) {
if (targetVarray.getId().equals(targetRec.getVirtualArray())) {
targetPoolRecommendation.setSourceStoragePool(targetRec.getSourceStoragePool());
targetPoolRecommendation.setSourceStorageSystem(targetRec.getSourceStorageSystem());
targetPoolRecommendations.add(targetPoolRecommendation);
break;
} else {
unusedTargets.append(targetRec.getVirtualArray().toString());
unusedTargets.append(" ");
}
}
// we need to kick out and continue on.
if (targetPoolRecommendations.isEmpty()) {
_log.warn(String.format("RP Placement : Could not find a MetroPoint CRR Solution because the" + " Active and Standby Copies could not find a common Target varray. " + "Active Target varrays [ %s] - Standby Target varray [ %s ]. " + "Reason: This might not be a MetroPoint CRR config. Please check the vpool config and " + "the RecoverPoint Protection System for the connectivity of the varrays.", unusedTargets.toString(), targetVarray.getId()));
return false;
}
} else {
// Get target pool recommendations. Each recommendation also specifies the resource
// count that the pool can satisfy based on the size requested.
targetPoolRecommendations = getRecommendedPools(rpProtectionRecommendation, targetVarray, targetVpool, null, null, newCapabilities, RPHelper.TARGET, null);
if (targetPoolRecommendations.isEmpty()) {
_log.error(String.format("RP Placement : No matching storage pools found for the source varray: [%s]. " + "There are no storage pools that match the passed vpool parameters and protocols and/or there are no pools that have " + "enough capacity to hold at least one resource of the requested size.", varray.getLabel()));
throw APIException.badRequests.noMatchingStoragePoolsForVpoolAndVarray(vpool.getLabel(), varray.getLabel());
}
}
// Find the correct target journal varray. It is either implicitly the same as the target varray or has been
// explicitly set by the user.
VirtualArray targetJournalVarray = targetVarray;
if (!NullColumnValueGetter.isNullURI(protectionSettings.getJournalVarray())) {
targetJournalVarray = dbClient.queryObject(VirtualArray.class, protectionSettings.getJournalVarray());
}
// Find the correct target journal vpool. It is either implicitly the same as the target vpool or has been
// explicitly set by the user.
VirtualPool targetJournalVpool = targetVpool;
if (!NullColumnValueGetter.isNullURI(protectionSettings.getJournalVpool())) {
targetJournalVpool = dbClient.queryObject(VirtualPool.class, protectionSettings.getJournalVpool());
}
Iterator<Recommendation> targetPoolRecommendationsIter = targetPoolRecommendations.iterator();
while (targetPoolRecommendationsIter.hasNext()) {
Recommendation targetPoolRecommendation = targetPoolRecommendationsIter.next();
StoragePool candidateTargetPool = dbClient.queryObject(StoragePool.class, targetPoolRecommendation.getSourceStoragePool());
List<String> associatedStorageSystems = getCandidateTargetVisibleStorageSystems(rpProtectionRecommendation.getProtectionDevice(), targetVarray, sourceRecommendation.getInternalSiteName(), candidateTargetPool, VirtualPool.vPoolSpecifiesHighAvailability(targetVpool));
if (associatedStorageSystems.isEmpty()) {
_log.info(String.format("RP Placement : Solution cannot be found using target pool %s" + " there is no connectivity to rp cluster sites.", candidateTargetPool.getLabel()));
continue;
}
// We want to find an internal site name that isn't already in the solution
for (String associatedStorageSystem : associatedStorageSystems) {
String targetInternalSiteName = ProtectionSystem.getAssociatedStorageSystemSiteName(associatedStorageSystem);
URI targetStorageSystemURI = ConnectivityUtil.findStorageSystemBySerialNumber(ProtectionSystem.getAssociatedStorageSystemSerialNumber(associatedStorageSystem), dbClient, StorageSystemType.BLOCK);
ProtectionType protectionType = null;
if (!sourceRecommendation.containsTargetInternalSiteName(targetInternalSiteName)) {
// MetroPoint has been specified so process the MetroPoint targets accordingly.
if (isMetroPoint) {
if (targetInternalSiteName.equals(sourceRecommendation.getInternalSiteName())) {
// A local protection candidate.
if (isMetroPointProtectionSpecified(sourceRecommendation, ProtectionType.LOCAL)) {
// so continue onto the next candidate RP site.
continue;
}
// Add the local protection
protectionType = ProtectionType.LOCAL;
} else {
if (isMetroPointProtectionSpecified(sourceRecommendation, ProtectionType.REMOTE)) {
// candidate RP site.
continue;
} else {
if (activeSourceRecommendation != null) {
String primaryTargetInternalSiteName = getMetroPointRemoteTargetRPSite(rpProtectionRecommendation);
if (primaryTargetInternalSiteName != null && !targetInternalSiteName.equals(primaryTargetInternalSiteName)) {
// site but the same as the primary target site.
continue;
}
}
// Add the remote protection
protectionType = ProtectionType.REMOTE;
}
}
}
}
// Check to make sure the RP site is connected to the varray
URI protectionSystemURI = rpProtectionRecommendation.getProtectionDevice();
if (!isRpSiteConnectedToVarray(targetStorageSystemURI, protectionSystemURI, targetInternalSiteName, targetVarray)) {
_log.info(String.format("RP Placement: Disqualified RP site [%s] because its initiators are not in a network " + "configured for use by the virtual array [%s]", targetInternalSiteName, targetVarray.getLabel()));
continue;
}
// Maybe make a topology check in here? Or is the source topology check enough?
StorageSystem targetStorageSystem = dbClient.queryObject(StorageSystem.class, targetStorageSystemURI);
ProtectionSystem ps = dbClient.queryObject(ProtectionSystem.class, protectionSystemURI);
String rpSiteName = (ps.getRpSiteNames() != null) ? ps.getRpSiteNames().get(targetInternalSiteName) : "";
_log.info(String.format("RP Placement : Choosing RP Site %s (%s) for target on varray [%s](%s)", rpSiteName, targetInternalSiteName, targetVarray.getLabel(), targetVarray.getId()));
// Construct the target recommendation object
_log.info(String.format("RP Placement : Build RP Target Recommendation..."));
RPRecommendation targetRecommendation = buildRpRecommendation(associatedStorageSystem, targetVarray, targetVpool, candidateTargetPool, newCapabilities, requestedCount, targetInternalSiteName, targetStorageSystemURI, targetStorageSystem.getSystemType(), ps);
if (targetRecommendation == null) {
// No Target Recommendation found, so continue.
_log.warn(String.format("RP Placement : Could not create Target Recommendation using [%s], continuing...", associatedStorageSystem));
continue;
}
_log.info(String.format("RP Placement : RP Target Recommendation %s %n", targetRecommendation.toString(dbClient, ps, 1)));
if (protectionType != null) {
targetRecommendation.setProtectionType(protectionType);
}
// First Determine if journal recommendation need to be computed. It might have already been done.
boolean isJournalPlacedForVarray = false;
for (RPRecommendation targetJournalRec : rpProtectionRecommendation.getTargetJournalRecommendations()) {
if (targetJournalRec.getVirtualArray().equals(targetJournalVarray.getId())) {
isJournalPlacedForVarray = true;
}
}
// Build the target journal recommendation
if (!isJournalPlacedForVarray) {
_log.info(String.format("RP Placement : Build RP Target Journal Recommendation..."));
RPRecommendation targetJournalRecommendation = buildJournalRecommendation(rpProtectionRecommendation, targetInternalSiteName, protectionSettings.getJournalSize(), targetJournalVarray, targetJournalVpool, ps, newCapabilities, capabilities.getResourceCount(), null, false);
if (targetJournalRecommendation == null) {
// No Target Journal Recommendation found, so continue.
_log.warn(String.format("RP Placement : Could not create Target Journal Recommendation using [%s], continuing...", associatedStorageSystem));
continue;
}
_log.info(String.format("RP Placement : RP Target Journal Recommendation %s %n", targetJournalRecommendation.toString(dbClient, ps, 1)));
rpProtectionRecommendation.getTargetJournalRecommendations().add(targetJournalRecommendation);
} else {
_log.info(String.format("RP Placement : RP Target Journal already placed."));
}
// the Target Recommendation.
if (sourceRecommendation.getTargetRecommendations() == null) {
sourceRecommendation.setTargetRecommendations(new ArrayList<RPRecommendation>());
}
sourceRecommendation.getTargetRecommendations().add(targetRecommendation);
// Set the placement status to reference either the primary or secondary.
PlacementStatus tmpPlacementStatus = placementStatus;
if (activeSourceRecommendation != null) {
tmpPlacementStatus = secondaryPlacementStatus;
}
// At this point we have found a target storage pool accessible to the protection vPool and protection vArray
// that can be protected by an rp cluster site that is part of the same rp system that can protect the source storage pool
rpProtectionRecommendation.setPlacementStepsCompleted(PlacementProgress.IDENTIFIED_SOLUTION_FOR_SUBSET_OF_TARGETS);
if (tmpPlacementStatus.isBestSolutionToDate(rpProtectionRecommendation)) {
tmpPlacementStatus.setLatestInvalidRecommendation(rpProtectionRecommendation);
}
if (isMetroPoint) {
if (rpProtectionRecommendation.getSourceRecommendations() != null && getProtectionVarrays(rpProtectionRecommendation).size() == targetVarrays.size()) {
finalizeTargetPlacement(rpProtectionRecommendation, tmpPlacementStatus);
return true;
}
} else if (targetVarrays.size() == 1) {
finalizeTargetPlacement(rpProtectionRecommendation, tmpPlacementStatus);
return true;
}
// Find a solution based on this recommendation object and the remaining target arrays
// Make a new protection varray list
List<VirtualArray> remainingVarrays = new ArrayList<VirtualArray>();
remainingVarrays.addAll(targetVarrays);
remainingVarrays.remove(targetVarray);
if (!remainingVarrays.isEmpty()) {
_log.info("RP placement: Calling find solution on the next virtual array : " + remainingVarrays.get(0).getLabel() + " Current virtual array: " + targetVarray.getLabel());
} else {
_log.info("RP Placement : Solution cannot be found, will try again with different pool combination");
return false;
}
if (!this.findSolution(rpProtectionRecommendation, sourceRecommendation, varray, vpool, remainingVarrays, newCapabilities, requestedCount, isMetroPoint, activeSourceRecommendation, project)) {
// Remove the current recommendation and try the next site name, pool, etc.
_log.info("RP Placement: Solution for remaining virtual arrays couldn't be found. " + "Trying different solution (if available) for varray: " + targetVarray.getLabel());
} else {
// We found a good solution
_log.info("RP Placement: Solution for remaining virtual arrays was found. Returning to caller. Virtual Array : " + targetVarray.getLabel());
return true;
}
}
}
// If we get here, the recommendation object never got a new protection object, and we just return false,
// which will move onto the next possibility (in the case of a recursive call)
_log.info("RP Placement : Solution cannot be found, will try again with different pool combination");
return false;
}
use of com.emc.storageos.db.client.model.VpoolProtectionVarraySettings 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;
}
Aggregations