use of com.emc.storageos.volumecontroller.RPRecommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method getHaRecommendation.
/**
* Determine high availability recommendation
*
* @param varray - High availability Virtual Array
* @param vpool - High availability Virtual Pool
* @param project - Project
* @param capabilities - Virtual Pool capabilities
* @return RPRecommendation representation for HA
*/
private RPRecommendation getHaRecommendation(VirtualArray varray, VirtualPool vpool, Project project, VirtualPoolCapabilityValuesWrapper capabilities) {
// this logic.
if (vpool.getHighAvailability() == null || VirtualPool.HighAvailabilityType.vplex_local.name().equals(vpool.getHighAvailability()) || VirtualPool.vPoolSpecifiesMetroPoint(vpool)) {
return null;
}
VirtualArray haVarray = vplexScheduler.getHaVirtualArray(varray, project, vpool);
VirtualPool haVpool = vplexScheduler.getHaVirtualPool(varray, project, vpool);
Map<String, Object> attributeMap = new HashMap<String, Object>();
Map<String, List<StoragePool>> vplexPoolMapForSrcVarray = getVplexMatchingPools(varray, vpool, haVarray, haVpool, capabilities, attributeMap);
Recommendation haRecommendation = findVPlexHARecommendations(varray, vpool, haVarray, haVpool, project, capabilities, vplexPoolMapForSrcVarray);
if (haRecommendation == null) {
_log.error("No HA Recommendations could be created.");
StringBuffer errorMessage = new StringBuffer();
if (attributeMap.get(AttributeMatcher.ERROR_MESSAGE) != null) {
errorMessage = (StringBuffer) attributeMap.get(AttributeMatcher.ERROR_MESSAGE);
}
throw APIException.badRequests.noStoragePools(varray.getLabel(), vpool.getLabel(), errorMessage.toString());
}
RPRecommendation rpHaRecommendation = new RPRecommendation();
VPlexRecommendation vplexRec = (VPlexRecommendation) haRecommendation;
// Always force count to 1 for a VPLEX rec for RP. VPLEX uses
// these recs and they are invoked one at a time even
// in a multi-volume request.
vplexRec.setResourceCount(1);
rpHaRecommendation.setVirtualVolumeRecommendation(vplexRec);
rpHaRecommendation.setSourceStoragePool(vplexRec.getSourceStoragePool());
rpHaRecommendation.setSourceStorageSystem(vplexRec.getSourceStorageSystem());
rpHaRecommendation.setVirtualArray(vplexRec.getVirtualArray());
rpHaRecommendation.setVirtualPool(vplexRec.getVirtualPool());
rpHaRecommendation.setResourceCount(capabilities.getResourceCount());
rpHaRecommendation.setSize(capabilities.getSize());
return rpHaRecommendation;
}
use of com.emc.storageos.volumecontroller.RPRecommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method getRecommendedPools.
/**
* Returns a list of recommendations for storage pools that satisfy the request.
* The return list is sorted in increasing order by the number of resources of size X
* that the pool can satisfy, where X is the size of each resource in this request.
*
* @param rpProtectionRecommendation - RP protection recommendation
* @param varray - Virtual Array
* @param vpool - Virtual Pool
* @param haVarray - HA Virtual Array
* @param haVpool - HA Virtual Pool
* @param capabilities - Virtual Pool capabilities
* @param personality - Volume personality
* @param internalSiteName - RP internal site name
* @return - List of recommendations
*/
private List<Recommendation> getRecommendedPools(RPProtectionRecommendation rpProtectionRecommendation, VirtualArray varray, VirtualPool vpool, VirtualArray haVarray, VirtualPool haVpool, VirtualPoolCapabilityValuesWrapper capabilities, String personality, String internalSiteName) {
// TODO (Brad/Bharath): ChangeVPool doesn't add any new targets. If new targets are requested as part of the changeVpool,
// then this code needs to be enhanced to be able to handle that.
_log.info("RP Placement : Fetching pool recommendations for : " + personality);
long sizeInBytes = capabilities.getSize();
long requestedCount = capabilities.getResourceCount();
long sizeInKB = getSizeInKB(sizeInBytes);
List<Recommendation> recommendations = new ArrayList<Recommendation>();
_log.info(String.format("RP Placement : Requested size : [%s] Bytes - [%s] KB - [%s] GB", sizeInBytes, sizeInKB, SizeUtil.translateSize(sizeInBytes, SizeUtil.SIZE_GB)));
// Fetch candidate storage pools
List<StoragePool> candidatePools = getCandidatePools(varray, vpool, haVarray, haVpool, capabilities, personality);
// Get all the pools already recommended
List<RPRecommendation> poolsInAllRecommendations = rpProtectionRecommendation.getPoolsInAllRecommendations();
// Get all the pools that can satisfy the size constraint of (size * resourceCount)
List<RPRecommendation> reconsiderPools = new ArrayList<RPRecommendation>();
StringBuffer buff = new StringBuffer();
for (StoragePool storagePool : candidatePools) {
int count = Math.abs((int) (storagePool.getFreeCapacity() / (sizeInKB)));
RPRecommendation recommendedPool = getRecommendationForStoragePool(poolsInAllRecommendations, storagePool);
// pool should be capable of satisfying at least one resource of the specified size.
if (count >= 1) {
if (recommendedPool == null) {
buff.append(String.format("%nRP Placement : # of resources of size %fGB that pool %s can accomodate: %s", SizeUtil.translateSize(sizeInBytes, SizeUtil.SIZE_GB), storagePool.getLabel(), count));
// Pool not in any recommendation thus far, create a new recommendation
Recommendation recommendation = new Recommendation();
recommendation.setSourceStoragePool(storagePool.getId());
recommendation.setSourceStorageSystem(storagePool.getStorageDevice());
recommendation.setResourceCount(count);
recommendations.add(recommendation);
} else {
// Pool already consumed in recommendation, save it and reconsider if there are no unused free pools in this
// recommendation
reconsiderPools.add(recommendedPool);
}
}
}
_log.info(buff.toString());
// Append the reconsider pool list, that way the non-reconsider pools are considered first and then the reconsider pools
if (!reconsiderPools.isEmpty()) {
// Reconsider all the consumed pools and see if there is any pool that can match the cumulative size.
// Say the pool was already recommended for X resources, and the current request needed Y resources.
// The pool recommendation should satisfy X+Y to be a valid recommendation.
recommendations.addAll(placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, reconsiderPools));
}
if (!recommendations.isEmpty()) {
// There is at least one pool that is capable of satisfying the request, return the list.
printPoolRecommendations(recommendations);
return recommendations;
}
if (personality.equals(RPHelper.SOURCE)) {
List<RPRecommendation> existingSourcePoolRecs = rpProtectionRecommendation.getSourcePoolsInRecommendation();
recommendations = placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, existingSourcePoolRecs);
if (recommendations.isEmpty()) {
existingSourcePoolRecs = rpProtectionRecommendation.getTargetPoolsInRecommendation();
recommendations = placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, existingSourcePoolRecs);
}
if (recommendations.isEmpty()) {
existingSourcePoolRecs = rpProtectionRecommendation.getJournalPoolsInRecommendation();
recommendations = placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, existingSourcePoolRecs);
}
} else if (personality.equals(RPHelper.TARGET)) {
List<RPRecommendation> existingTargetPoolRecs = rpProtectionRecommendation.getTargetPoolsInRecommendation();
recommendations = placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, existingTargetPoolRecs);
if (recommendations.isEmpty()) {
existingTargetPoolRecs = rpProtectionRecommendation.getSourcePoolsInRecommendation();
recommendations = placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, existingTargetPoolRecs);
}
if (recommendations.isEmpty()) {
existingTargetPoolRecs = rpProtectionRecommendation.getJournalPoolsInRecommendation();
recommendations = placeAlreadyRecommendedPool(sizeInBytes, requestedCount, sizeInKB, existingTargetPoolRecs);
}
} else {
// Looking for a recommendation for RP journal. If we got here it implies that there are no "free" pools and all the recommended
// pools are already used up. Check the list of pools in journal recommendation first and filter them by the internal site
// to consider only the pools that have visibility to the internal site.
List<RPRecommendation> journalRecs = rpProtectionRecommendation.getJournalPoolsInRecommendation();
for (RPRecommendation journalRec : journalRecs) {
if (journalRec.getInternalSiteName().equals(internalSiteName)) {
StoragePool existingTargetPool = dbClient.queryObject(StoragePool.class, journalRec.getSourceStoragePool());
int count = Math.abs((int) (existingTargetPool.getFreeCapacity() / (sizeInKB)));
_log.info(String.format("%nRP Placement : # of resources of size %fGB that pool %s can accomodate: %s%n", SizeUtil.translateSize(sizeInBytes, SizeUtil.SIZE_GB), existingTargetPool.getLabel(), count));
if (count >= requestedCount + journalRec.getResourceCount()) {
recommendations.add(journalRec);
}
}
}
if (recommendations.isEmpty()) {
// Couldn't find a free pool or used pool, return all the pools that sees the same RP site as the one we are trying for a
// recommendation for.
journalRecs = rpProtectionRecommendation.getPoolsInAllRecommendations();
for (RPRecommendation journalRec : journalRecs) {
if (journalRec.getInternalSiteName().equals(internalSiteName)) {
StoragePool existingTargetPool = dbClient.queryObject(StoragePool.class, journalRec.getSourceStoragePool());
int count = Math.abs((int) (existingTargetPool.getFreeCapacity() / (sizeInKB)));
_log.info(String.format("%nRP Placement : # of resources of size %sGB that pool %s can accomodate: %s%n", SizeUtil.translateSize(sizeInBytes, SizeUtil.SIZE_GB).toString(), existingTargetPool.getLabel(), count));
if (count >= requestedCount + journalRec.getResourceCount()) {
recommendations.add(journalRec);
}
}
}
}
}
Collections.sort(recommendations, new Comparator<Recommendation>() {
@Override
public int compare(Recommendation a1, Recommendation a2) {
return ComparisonChain.start().compare(a1.getResourceCount(), a2.getResourceCount()).compare(a1.getResourceCount(), a1.getResourceCount()).result();
}
});
printPoolRecommendations(recommendations);
return recommendations;
}
use of com.emc.storageos.volumecontroller.RPRecommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method placeAlreadyRecommendedPool.
/**
* Checks if existing recommendations for pools can satisfy requested resource count in addition to what it already satisfies.
*
* @param sizeInBytes - Size requested in bytes
* @param requestedCount - Resource count requested
* @param sizeInKB - Size in KB
* @param recs - Existing recommendations
* @return List of recommendations that can satisfy already satisfied count # of resources plus new count
*/
private List<Recommendation> placeAlreadyRecommendedPool(long sizeInBytes, long requestedCount, long sizeInKB, List<RPRecommendation> recs) {
List<Recommendation> recommendations = new ArrayList<Recommendation>();
StringBuffer buff = new StringBuffer();
for (Recommendation rec : recs) {
StoragePool existingTargetPool = dbClient.queryObject(StoragePool.class, rec.getSourceStoragePool());
int count = Math.abs((int) (existingTargetPool.getFreeCapacity() / (sizeInKB)));
buff.append(String.format("%nRP Placement (Already placed) : # of resources of size %sGB that pool %s can accomodate: %d", SizeUtil.translateSize(sizeInBytes, SizeUtil.SIZE_GB).toString(), existingTargetPool.getLabel(), count));
if (count >= requestedCount + rec.getResourceCount()) {
recommendations.add(rec);
}
}
_log.info(buff.toString());
return recommendations;
}
use of com.emc.storageos.volumecontroller.RPRecommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method buildCgRecommendations.
/**
* Builds a recommendation from existing CG.
*
* This method is called when adding more volumes into an existing CG or change vpool scenario.
*
* When adding to an existing CG we can accommodate the request with the recommendations from
* resources that have already been placed in the existing CG.
*
* @param capabilities - Virtual Pool capabilities
* @param vpool - Virtual Pool
* @param protectionVarrays - List of target copy virtual arrays
* @param vpoolChangeVolume - change virtual pool volume
* @return - List of recommendations
*/
protected List<Recommendation> buildCgRecommendations(VirtualPoolCapabilityValuesWrapper capabilities, VirtualPool vpool, List<VirtualArray> protectionVarrays, Volume vpoolChangeVolume) {
BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, capabilities.getBlockConsistencyGroup());
_log.info(String.format("Attempting to align placement (protection system, storage pools, internal site names) with " + "existing volumes in RecoverPoint consistency group %s.", cg.getLabel()));
List<Recommendation> recommendations = new ArrayList<Recommendation>();
// Find the first existing source volume
List<Volume> sourceVolumes = RPHelper.getCgSourceVolumes(cg.getId(), dbClient);
if (sourceVolumes.isEmpty()) {
_log.info(String.format("Unable to fully align placement with existing volumes in RecoverPoint consistency group %s. " + "The consistency group currently contains no volumes.", cg.getLabel()));
return recommendations;
}
// Verify that all the underlying protection storage pools used by the existing source volume are available to this request
if (!verifyExistingSourceProtectionPools(sourceVolumes.get(0), vpool, cg.getLabel())) {
return recommendations;
}
Volume sourceVolume = null;
boolean createRecommendations = false;
for (Volume currentSourceVolume : sourceVolumes) {
// enough capacity, use it to produce the recommendation.
if (cgPoolsHaveAvailableCapacity(currentSourceVolume, capabilities, vpool, protectionVarrays)) {
createRecommendations = true;
sourceVolume = currentSourceVolume;
break;
}
}
if (!createRecommendations) {
return recommendations;
}
RPProtectionRecommendation recommendation = new RPProtectionRecommendation();
if (sourceVolume.getProtectionController() != null) {
ProtectionSystem ps = dbClient.queryObject(ProtectionSystem.class, sourceVolume.getProtectionController());
if (ps.getInactive()) {
// be protected so we must fail.
throw APIException.badRequests.cgReferencesInvalidProtectionSystem(cg.getId(), sourceVolume.getProtectionController());
}
} else {
// be protected so we must fail.
throw APIException.badRequests.cgReferencesInvalidProtectionSystem(cg.getId(), sourceVolume.getProtectionController());
}
recommendation.setProtectionDevice(sourceVolume.getProtectionController());
recommendation.setVpoolChangeVolume(vpoolChangeVolume != null ? vpoolChangeVolume.getId() : null);
recommendation.setVpoolChangeNewVpool(vpoolChangeVolume != null ? vpool.getId() : null);
recommendation.setVpoolChangeProtectionAlreadyExists(vpoolChangeVolume != null ? vpoolChangeVolume.checkForRp() : false);
recommendation.setResourceCount(capabilities.getResourceCount());
// Check to see if we need an additional journal for Source
Map<Integer, Long> additionalJournalForSource = RPHelper.additionalJournalRequiredForRPCopy(vpool.getJournalSize(), cg.getId(), capabilities.getSize(), capabilities.getResourceCount(), sourceVolume.getRpCopyName(), dbClient);
if (!CollectionUtils.isEmpty(additionalJournalForSource)) {
// ACTIVE SOURCE JOURNAL Recommendation
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();
}
VirtualPool sourceJournalVpool = NullColumnValueGetter.isNotNullValue(vpool.getJournalVpool()) ? dbClient.queryObject(VirtualPool.class, URI.create(vpool.getJournalVpool())) : vpool;
Long sourceJournalSize = getJournalCapabilities(vpool.getJournalSize(), capabilities, 1).getSize();
RPRecommendation sourceJournalRecommendation = buildRpRecommendationFromExistingVolume(sourceJournal, sourceJournalVpool, capabilities, sourceJournalSize);
// Parse out the calculated values
Map.Entry<Integer, Long> entry = additionalJournalForSource.entrySet().iterator().next();
Integer journalCount = entry.getKey();
Long journalSize = entry.getValue();
// Override values in recommendation with calculated journal count and size
sourceJournalRecommendation.setResourceCount(journalCount);
sourceJournalRecommendation.setSize(journalSize);
recommendation.setSourceJournalRecommendation(sourceJournalRecommendation);
// STANDBY SOURCE JOURNAL Recommendation
String standbyCopyName = RPHelper.getStandbyProductionCopyName(dbClient, sourceVolume);
if (standbyCopyName != null) {
List<Volume> existingStandbyJournals = RPHelper.findExistingJournalsForCopy(dbClient, sourceVolume.getConsistencyGroup(), standbyCopyName);
Volume standbyJournal = existingStandbyJournals.get(0);
if (standbyJournal == null) {
_log.error(String.format("No existing standby journal found in CG [%s] for copy [%s], returning false", sourceVolume.getConsistencyGroup(), standbyCopyName));
throw APIException.badRequests.unableToFindSuitableJournalRecommendation();
}
VirtualPool haVpool = (null != VirtualPool.getHAVPool(vpool, dbClient)) ? VirtualPool.getHAVPool(vpool, dbClient) : vpool;
VirtualPool standbyJournalVpool = NullColumnValueGetter.isNotNullValue(vpool.getStandbyJournalVpool()) ? dbClient.queryObject(VirtualPool.class, URI.create(vpool.getStandbyJournalVpool())) : haVpool;
RPRecommendation standbyJournalRecommendation = buildRpRecommendationFromExistingVolume(standbyJournal, standbyJournalVpool, capabilities, sourceJournalSize);
// Override values in recommendation with calculated journal count and size
standbyJournalRecommendation.setResourceCount(journalCount);
standbyJournalRecommendation.setSize(journalSize);
recommendation.setStandbyJournalRecommendation(standbyJournalRecommendation);
}
}
// SOURCE Recommendation
RPRecommendation sourceRecommendation = buildRpRecommendationFromExistingVolume(sourceVolume, vpool, capabilities, null);
recommendation.getSourceRecommendations().add(sourceRecommendation);
// TARGET Recommendation(s)
Map<URI, VpoolProtectionVarraySettings> protectionSettings = VirtualPool.getProtectionSettings(vpool, dbClient);
for (VirtualArray protectionVarray : protectionVarrays) {
Volume targetVolume = getTargetVolumeForProtectionVirtualArray(sourceVolume, protectionVarray);
// if the target vpool is not set, it defaults to the source vpool
VirtualPool targetVpool = vpool;
if (protectionSettings.get(protectionVarray.getId()) != null && protectionSettings.get(protectionVarray.getId()).getVirtualPool() != null) {
targetVpool = dbClient.queryObject(VirtualPool.class, protectionSettings.get(protectionVarray.getId()).getVirtualPool());
}
RPRecommendation targetRecommendation = buildRpRecommendationFromExistingVolume(targetVolume, targetVpool, capabilities, null);
if (sourceRecommendation.getTargetRecommendations() == null) {
sourceRecommendation.setTargetRecommendations(new ArrayList<RPRecommendation>());
}
sourceRecommendation.getTargetRecommendations().add(targetRecommendation);
// Check to see if we need an additional journal for Target
Map<Integer, Long> additionalJournalForTarget = RPHelper.additionalJournalRequiredForRPCopy(vpool.getJournalSize(), cg.getId(), capabilities.getSize(), capabilities.getResourceCount(), targetVolume.getRpCopyName(), dbClient);
if (!CollectionUtils.isEmpty(additionalJournalForTarget)) {
// TARGET JOURNAL Recommendation
List<Volume> targetJournals = RPHelper.findExistingJournalsForCopy(dbClient, targetVolume.getConsistencyGroup(), targetVolume.getRpCopyName());
Volume targetJournal = targetJournals.get(0);
if (targetJournal == 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();
}
VirtualPool targetJournalVpool = protectionSettings.get(protectionVarray.getId()).getJournalVpool() != null ? dbClient.queryObject(VirtualPool.class, protectionSettings.get(protectionVarray.getId()).getJournalVpool()) : targetVpool;
Long targetJournalSize = getJournalCapabilities(protectionSettings.get(protectionVarray.getId()).getJournalSize(), capabilities, 1).getSize();
RPRecommendation targetJournalRecommendation = buildRpRecommendationFromExistingVolume(targetJournal, targetJournalVpool, capabilities, targetJournalSize);
// Parse out the calculated values
Integer journalCount = 0;
Long journalSize = 0L;
if (!CollectionUtils.isEmpty(additionalJournalForSource)) {
Map.Entry<Integer, Long> entry = additionalJournalForSource.entrySet().iterator().next();
journalCount = entry.getKey();
journalSize = entry.getValue();
} else {
_log.info("Journal for Source is Null, journal Size will be calculated from Target");
Map.Entry<Integer, Long> entry = additionalJournalForTarget.entrySet().iterator().next();
journalCount = entry.getKey();
journalSize = entry.getValue();
}
_log.info("journalCount : {} and journalSize: {}", journalCount, journalSize);
// Override values in recommendation with calculated journal count and size
targetJournalRecommendation.setResourceCount(journalCount);
targetJournalRecommendation.setSize(journalSize);
if (recommendation.getTargetJournalRecommendations() == null) {
recommendation.setTargetJournalRecommendations(new ArrayList<RPRecommendation>());
}
recommendation.getTargetJournalRecommendations().add(targetJournalRecommendation);
}
}
_log.info(String.format("Produced recommendations based on existing source volume [%s](%s) from " + "RecoverPoint consistency group [%s].", sourceVolume.getLabel(), sourceVolume.getId(), cg.getLabel()));
recommendations.add(recommendation);
return recommendations;
}
use of com.emc.storageos.volumecontroller.RPRecommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method buildRpRecommendation.
/**
* Construct RP Recommendation object
*
* @param associatedStorageSystem - Associated Storage System
* @param varray - Virtual Array
* @param vpool - Virtual Pool
* @param sourcePool - Storage Pool
* @param capabilities - VirtualPool capabilities
* @param satisfiedSourceVolCount - resource count
* @param sourceInternalSiteName - Internal site name
* @param sourceStorageSytemUri - Storage System URI
* @param type - StorageSystem Type
* @param ps - Protection System
* @return a fully formed RP Recommendation object
*/
private RPRecommendation buildRpRecommendation(String associatedStorageSystem, VirtualArray varray, VirtualPool vpool, StoragePool sourcePool, VirtualPoolCapabilityValuesWrapper capabilities, int satisfiedSourceVolCount, String sourceInternalSiteName, URI sourceStorageSytemUri, String type, ProtectionSystem ps) {
RPRecommendation rpRecommendation = new RPRecommendation();
rpRecommendation.setRpSiteAssociateStorageSystem(associatedStorageSystem);
rpRecommendation.setSourceStoragePool(sourcePool.getId());
rpRecommendation.setSourceStorageSystem(sourcePool.getStorageDevice());
rpRecommendation.setResourceCount(satisfiedSourceVolCount);
rpRecommendation.setVirtualArray(varray.getId());
rpRecommendation.setVirtualPool(vpool);
rpRecommendation.setInternalSiteName(sourceInternalSiteName);
rpRecommendation.setSize(capabilities.getSize());
// VPLEX will consume this to create the virtual volumes.
if (DiscoveredDataObject.Type.vplex.name().equals(type)) {
VPlexRecommendation virtualVolumeRecommendation = new VPlexRecommendation();
virtualVolumeRecommendation.setVirtualArray(rpRecommendation.getVirtualArray());
virtualVolumeRecommendation.setVirtualPool(rpRecommendation.getVirtualPool());
virtualVolumeRecommendation.setVPlexStorageSystem((sourceStorageSytemUri));
virtualVolumeRecommendation.setSourceStoragePool(sourcePool.getId());
virtualVolumeRecommendation.setSourceStorageSystem(sourcePool.getStorageDevice());
// Always force count to 1 for a VPLEX rec for RP. VPLEX uses
// these recs and they are invoked one at a time even
// in a multi-volume request.
virtualVolumeRecommendation.setResourceCount(1);
rpRecommendation.setVirtualVolumeRecommendation(virtualVolumeRecommendation);
}
return rpRecommendation;
}
Aggregations