use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class BlockMirrorServiceApiImpl method populateVolumeRecommendations.
/**
* Populate the Recommendations for the given sourceVolume
*
* @param capabilities
* @param sourceVolumeVPool
* @param sourceVolume
* @param taskId
* @param taskList
* @param volumeCount
* @param volumeCounter
* @param volumeLabel
* @param preparedVolumes
* @param volumeRecommendations
*/
private void populateVolumeRecommendations(VirtualPoolCapabilityValuesWrapper capabilities, VirtualPool sourceVolumeVPool, Volume sourceVolume, String taskId, TaskList taskList, Integer volumeCount, int volumeCounter, String volumeLabel, List<Volume> preparedVolumes, List<Recommendation> volumeRecommendations) {
List<Recommendation> currentRecommendation = new ArrayList<Recommendation>();
VirtualPool mirrorVPool = sourceVolumeVPool;
if (!isNullOrEmpty(sourceVolumeVPool.getMirrorVirtualPool())) {
URI mirrorPoolUri = URI.create(sourceVolumeVPool.getMirrorVirtualPool());
if (!URIUtil.isNull(mirrorPoolUri)) {
mirrorVPool = _dbClient.queryObject(VirtualPool.class, mirrorPoolUri);
}
}
for (int i = 0; i < capabilities.getResourceCount(); i++) {
VolumeRecommendation volumeRecommendation = new VolumeRecommendation(VolumeRecommendation.VolumeType.BLOCK_VOLUME, sourceVolume.getCapacity(), sourceVolumeVPool, sourceVolume.getVirtualArray());
volumeRecommendation.setId(sourceVolume.getId());
volumeRecommendation.addStoragePool(sourceVolume.getPool());
currentRecommendation.add(volumeRecommendation);
}
VirtualArray vArray = _dbClient.queryObject(VirtualArray.class, sourceVolume.getVirtualArray());
_scheduler.getRecommendationsForMirrors(vArray, mirrorVPool, capabilities, currentRecommendation);
// only mirror will be prepared (the source already exist)
_scheduler.prepareRecommendedVolumes(null, taskId, taskList, null, null, sourceVolumeVPool, volumeCount, currentRecommendation, null, volumeCounter, volumeLabel, preparedVolumes, capabilities, false);
volumeRecommendations.addAll(currentRecommendation);
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class FileStorageScheduler method getFileRecommendationsForVNAS.
/**
* Returns the File recommendations for vNAS
*
* @param vNAS
* @param vArrayURI
* @param vPool
* @param poolRecommendations
* @return
*/
private List<FileRecommendation> getFileRecommendationsForVNAS(VirtualNAS vNAS, URI vArrayURI, VirtualPool vPool, List<Recommendation> poolRecommendations) {
List<FileRecommendation> fileRecommendations = new ArrayList<FileRecommendation>();
List<StoragePort> ports = getAssociatedStoragePorts(vNAS, vArrayURI);
List<URI> storagePortURIList = new ArrayList<URI>();
for (Iterator<StoragePort> iterator = ports.iterator(); iterator.hasNext(); ) {
StoragePort storagePort = iterator.next();
// storageport must be part of network
if (!NullColumnValueGetter.isNullURI(storagePort.getNetwork())) {
storagePortURIList.add(storagePort.getId());
}
}
for (Iterator<Recommendation> iterator = poolRecommendations.iterator(); iterator.hasNext(); ) {
Recommendation recommendation = iterator.next();
FileRecommendation fRec = new FileRecommendation(recommendation);
URI storageDevice = fRec.getSourceStorageSystem();
if (vNAS.getStorageDeviceURI().equals(storageDevice)) {
fRec.setStoragePorts(storagePortURIList);
fRec.setvNAS(vNAS.getId());
fileRecommendations.add(fRec);
}
}
return fileRecommendations;
}
use of com.emc.storageos.volumecontroller.Recommendation 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.Recommendation 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.Recommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method getRecommendationsForResources.
/**
* Select and return one or more storage pools where the volume(s)
* should be created. The placement logic is based on:
* - VirtualArray, only storage devices in the given varray are candidates
* - protection varrays
* - VirtualPool, specifies must-meet & best-meet service specifications
* - access-protocols: storage pools must support all protocols specified in CoS
* - snapshots: if yes, only select storage pools with this capability
* - snapshot-consistency: if yes, only select storage pools with this capability
* - performance: best-match, select storage pools which meets desired performance
* - provision-mode: thick/thin
* - numPaths: select storage pools with required number of paths to the volume
* - Size: Place the resources in the minimum number of storage pools that can
* accommodate the size and number of resource requested.
*
* @param varray varray requested for source
* @param project for the storage
* @param vpool vpool requested
* @param capabilities CoS capabilities parameters
* @return list of Recommendation objects to satisfy the request
*/
@Override
public List<Recommendation> getRecommendationsForResources(VirtualArray varray, Project project, VirtualPool vpool, VirtualPoolCapabilityValuesWrapper capabilities) {
// Check to see if we need to throttle concurrent requests for the same RP CG
throttleConncurrentRequests(vpool, capabilities.getBlockConsistencyGroup());
Volume changeVpoolVolume = null;
if (capabilities.getChangeVpoolVolume() != null) {
changeVpoolVolume = dbClient.queryObject(Volume.class, URI.create(capabilities.getChangeVpoolVolume()));
_log.info(String.format("Existing volume [%s](%s) will be used as RP Source volume in recommendations.", changeVpoolVolume.getLabel(), changeVpoolVolume.getId()));
} else {
_log.info(String.format("Schedule new storage for [%s] resource(s) of size [%s].", capabilities.getResourceCount(), capabilities.getSize()));
}
List<VirtualArray> protectionVarrays = getProtectionVirtualArraysForVirtualPool(project, vpool, dbClient, _permissionsHelper);
VirtualArray haVarray = null;
VirtualPool haVpool = null;
SwapContainer container = null;
if (VirtualPool.vPoolSpecifiesHighAvailabilityDistributed(vpool)) {
container = swapSrcAndHAIfNeeded(varray, vpool);
varray = container.getSrcVarray();
vpool = container.getSrcVpool();
haVarray = container.getHaVarray();
haVpool = container.getHaVpool();
}
// Get all storage pools that match the passed Virtual Pool params and protocols.
// In addition, the pool must have enough capacity to hold at least one resource of the requested size.
List<StoragePool> candidatePools = getCandidatePools(varray, vpool, haVarray, haVpool, capabilities, RPHelper.SOURCE);
if (candidatePools == null || candidatePools.isEmpty()) {
_log.error(String.format("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());
}
this.initResources();
List<Recommendation> recommendations = buildCgRecommendations(capabilities, vpool, protectionVarrays, changeVpoolVolume);
if (recommendations.isEmpty()) {
if (VirtualPool.vPoolSpecifiesMetroPoint(vpool)) {
_log.info("Finding recommendations for Metropoint volume placement...");
// MetroPoint has been enabled. get the HA virtual array and virtual pool. This will allow us to obtain
// candidate storage pool and secondary cluster protection recommendations.
haVarray = vplexScheduler.getHaVirtualArray(container.getSrcVarray(), project, container.getSrcVpool());
haVpool = vplexScheduler.getHaVirtualPool(container.getSrcVarray(), project, container.getSrcVpool());
// Get the candidate source pools for the distributed cluster. The 2 null params are ignored in the pool matching
// because they are used to build the HA recommendations, which will not be done if MetroPoint is enabled.
List<StoragePool> haCandidateStoragePools = getCandidatePools(haVarray, haVpool, null, null, capabilities, RPHelper.SOURCE);
// MetroPoint has been enabled so we need to obtain recommendations for the primary (active) and secondary (HA/Stand-by)
// VPlex clusters.
recommendations = createMetroPointRecommendations(container.getSrcVarray(), protectionVarrays, container.getSrcVpool(), haVarray, haVpool, project, capabilities, candidatePools, haCandidateStoragePools, changeVpoolVolume);
} else {
_log.info("Finding recommendations for RecoverPoint volume placement...");
// Schedule storage based on the source pool constraint.
recommendations = scheduleStorageSourcePoolConstraint(varray, protectionVarrays, vpool, capabilities, candidatePools, project, changeVpoolVolume, null);
}
}
// There is only one entry of type RPProtectionRecommendation ever in the returned recommendation list.
_log.info(String.format("%s %n", ((RPProtectionRecommendation) recommendations.get(0)).toString(dbClient)));
return recommendations;
}
Aggregations