use of com.emc.storageos.volumecontroller.VPlexRecommendation 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;
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class RecoverPointScheduler method getAllHARecommendations.
/**
* Gets all the HA placement recommendations.
*
* @param srcVarray The source virtual array
* @param srcVpool The source virtual pool
* @param requestedHaVarray The requested highly available virtual array
* @param haVpool The highly available virtual pool
* @param capabilities The virtual pool capabilities
* @param vplexPoolMapForSrcVarray The source virtual array, VPlex connected storage pools
* @param srcStorageSystem The selected VPlex source leg storage system
* @param isRpTarget true if the request is specific to a RecoverPoint target, false otherwise
*
* @return A list of VPlexRecommendation instances specifying the
* HA recommended resource placement resources
*/
protected List<Recommendation> getAllHARecommendations(VirtualArray srcVarray, VirtualPool srcVpool, VirtualArray requestedHaVarray, VirtualPool haVpool, VirtualPoolCapabilityValuesWrapper capabilities, Map<String, List<StoragePool>> vplexPoolMapForSrcVarray) {
_log.info("Executing VPlex high availability placement strategy");
// Initialize the list of recommendations.
List<Recommendation> recommendations = new ArrayList<Recommendation>();
// The list of potential VPlex storage systems.
Set<String> vplexStorageSystemIds = vplexPoolMapForSrcVarray.keySet();
_log.info(String.format("%s VPlex storage systems have matching pools", vplexStorageSystemIds.size()));
// For an HA request, get the possible high availability varrays
// for each potential VPlex storage system.
Map<String, List<String>> vplexHaVarrayMap = ConnectivityUtil.getVPlexVarrays(dbClient, vplexStorageSystemIds, srcVarray.getId());
// passed VirtualPool is use.
if (haVpool == null) {
haVpool = srcVpool;
}
_log.info(String.format("Requested HA varray is %s", (requestedHaVarray != null ? requestedHaVarray.getId() : "not specified")));
// Loop over the potential VPlex storage systems, and attempt
// to place the resources.
Iterator<String> vplexSystemIdsIter = vplexStorageSystemIds.iterator();
while (vplexSystemIdsIter.hasNext()) {
String vplexStorageSystemId = vplexSystemIdsIter.next();
_log.info(String.format("Check matching pools for VPlex %s", vplexStorageSystemId));
// pools for this VPlex storage system.
if (VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(srcVpool.getSupportedProvisioningType())) {
capabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.TRUE);
}
// Otherwise we now have to see if there is an HA varray
// for the VPlex that also contains pools suitable to place
// the resources.
List<String> vplexHaVarrayIds = vplexHaVarrayMap.get(vplexStorageSystemId);
_log.info(String.format("Found %s HA varrays", vplexHaVarrayIds.size()));
for (String vplexHaVarrayId : vplexHaVarrayIds) {
_log.info(String.format("Check HA varray %s", vplexHaVarrayId));
// varray is not it, then skip the varray.
if ((requestedHaVarray != null) && (!vplexHaVarrayId.equals(requestedHaVarray.getId().toString()))) {
_log.info("Not the requested HA varray, skip");
continue;
}
// Get all storage pools that match the passed VirtualPool params,
// and this HA VirtualArray. In addition, the
// pool must have enough capacity to hold at least one
// resource of the requested size.
VirtualArray vplexHaVarray = dbClient.queryObject(VirtualArray.class, URI.create(vplexHaVarrayId));
Map<String, Object> attributeMap = new HashMap<String, Object>();
List<StoragePool> allMatchingPoolsForHaVarray = vplexScheduler.getMatchingPools(vplexHaVarray, null, haVpool, capabilities, attributeMap);
_log.info(String.format("Found %s matching pools for HA varray", allMatchingPoolsForHaVarray.size()));
// Now from the list of candidate pools, we only want pools
// on storage systems that are connected to the VPlex
// storage system. We find these storage pools and associate
// them to the VPlex storage systems to which their storage
// system is connected.
Map<String, List<StoragePool>> vplexPoolMapForHaVarray = vplexScheduler.sortPoolsByVPlexStorageSystem(allMatchingPoolsForHaVarray, vplexHaVarrayId);
// If the HA varray has candidate pools for this
// VPlex, see if the candidate pools in this HA
// varray are sufficient to place the resources.
List<Recommendation> recommendationsForHaVarray = new ArrayList<Recommendation>();
if (vplexPoolMapForHaVarray.containsKey(vplexStorageSystemId)) {
_log.info(String.format("Found matching pools in HA varray for VPlex %s", vplexStorageSystemId));
if (VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(haVpool.getSupportedProvisioningType())) {
capabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.TRUE);
}
recommendationsForHaVarray = blockScheduler.getRecommendationsForPools(vplexHaVarray.getId().toString(), vplexPoolMapForHaVarray.get(vplexStorageSystemId), capabilities);
} else {
_log.info(String.format("No matching pools in HA varray for VPlex %s", vplexStorageSystemId));
}
// the source and HA varrays.
if (!recommendationsForHaVarray.isEmpty()) {
_log.info("Matching pools in HA varray sufficient for placement.");
recommendations.addAll(vplexScheduler.createVPlexRecommendations(vplexStorageSystemId, vplexHaVarray, haVpool, recommendationsForHaVarray));
}
// varrays for this VPlex.
if (!recommendations.isEmpty() || (requestedHaVarray != null)) {
_log.info("Done trying to place resource for VPlex.");
break;
}
}
}
return recommendations;
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class VPlexScheduler method createVPlexRecommendations.
/**
* Sets the Id of the VPlex storage system into the passed recommendations.
*
* @param vplexStorageSystemId The id of the VPlex storage system.
* @param varray The varray for the recommendation.
* @param vpool The vpool for the recommendation.
* @param recommendations The list of recommendations.
*/
protected List<VPlexRecommendation> createVPlexRecommendations(String vplexStorageSystemId, VirtualArray varray, VirtualPool vpool, List<Recommendation> recommendations) {
List<VPlexRecommendation> vplexRecommendations = new ArrayList<VPlexRecommendation>();
for (Recommendation recommendation : recommendations) {
VPlexRecommendation vplexRecommendation = new VPlexRecommendation();
vplexRecommendation.setSourceStorageSystem(recommendation.getSourceStorageSystem());
vplexRecommendation.setSourceStoragePool(recommendation.getSourceStoragePool());
vplexRecommendation.setResourceCount(recommendation.getResourceCount());
// vplexRecommendation.setSourceDevice(URI.create(vplexStorageSystemId));
vplexRecommendation.setVPlexStorageSystem(URI.create(vplexStorageSystemId));
vplexRecommendation.setVirtualArray(varray.getId());
vplexRecommendation.setVirtualPool(vpool);
vplexRecommendations.add(vplexRecommendation);
}
return vplexRecommendations;
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class VPlexScheduler method scheduleStorageForDistributedVPLEXVolume.
/**
* Get recommendations for resource placement for distributed VLPEX volumes.
*
* @param srcVarray The virtual array in which the resources were requested.
* @param requestedVPlexSystems The URIs of the VPlex systems to which
* placement should be limited, or null when it doesn't matter.
* @param srcStorageSystem The URI of a specific backend storage system to
* which the source resource should be limited, or null when it
* doesn't matter.
* @param srcVpool The virtual pool requested for the source resources.
* @param haVarray The desired HA varray.
* @param haVpool The virtual pool for the HA resources.
* @param capabilities The virtual pool capabilities.
*
* @return A list of VPlexRecommendation instances specifying the
* recommended resource placement.
*/
private List<Recommendation> scheduleStorageForDistributedVPLEXVolume(VirtualArray srcVarray, Set<URI> requestedVPlexSystems, URI srcStorageSystem, VirtualPool srcVpool, VirtualArray haVarray, VirtualPool haVpool, VirtualPoolCapabilityValuesWrapper capabilities, Project project, VpoolUse srcVpoolUse, Map<VpoolUse, List<Recommendation>> currentRecommendations) {
_log.info("Executing VPLEX high availability placement strategy for Distributed VPLEX Volumes.");
// Initialize the list of recommendations.
List<Recommendation> recommendations = new ArrayList<Recommendation>();
// of the StorageSystemsMatcher.
if (srcStorageSystem != null) {
StorageSystem sourceStorageSystem = _dbClient.queryObject(StorageSystem.class, srcStorageSystem);
capabilities.put(VirtualPoolCapabilityValuesWrapper.SOURCE_STORAGE_SYSTEM, sourceStorageSystem);
}
// Call the lower level scheduler to get its recommendations.
Scheduler nextScheduler = _placementManager.getNextScheduler(SCHEDULER_NAME, srcVpool, srcVpoolUse);
_log.info(String.format("Calling next scheduler: %s", nextScheduler.getClass().getSimpleName()));
List<Recommendation> baseRecommendations = nextScheduler.getRecommendationsForVpool(srcVarray, project, srcVpool, srcVpoolUse, capabilities, currentRecommendations);
_log.info(String.format("Received %d recommendations from %s", baseRecommendations.size(), nextScheduler.getClass().getSimpleName()));
if (baseRecommendations.isEmpty()) {
throw BadRequestException.badRequests.noVplexLocalRecommendationFromSubScheduler(nextScheduler.getClass().getSimpleName(), srcVpool.getLabel(), srcVarray.getLabel());
}
_log.info(String.format("Received %d recommendations from %s", baseRecommendations.size(), nextScheduler.getClass().getSimpleName()));
List<StoragePool> allMatchingPoolsForSrcVarray = _placementManager.getStoragePoolsFromRecommendations(baseRecommendations);
_log.info("Found {} matching pools for source varray", allMatchingPoolsForSrcVarray.size());
URI cgURI = capabilities.getBlockConsistencyGroup();
BlockConsistencyGroup cg = (cgURI == null ? null : _dbClient.queryObject(BlockConsistencyGroup.class, cgURI));
// Sort the matching pools for the source varray by VPLEX system.
Map<String, List<StoragePool>> vplexPoolMapForSrcVarray = getVPlexConnectedMatchingPools(srcVarray, requestedVPlexSystems, capabilities, allMatchingPoolsForSrcVarray);
if (vplexPoolMapForSrcVarray.isEmpty()) {
_log.info("No matching pools on storage systems connected to a VPLEX");
// and there are none for that VPlex system.
return recommendations;
}
// Get all storage pools that match the passed HA VirtualPool params,
// and HA virtual array. In addition, the pool must have enough
// capacity to hold at least one resource of the requested size.
_log.info("Getting all matching pools for HA varray {}", haVarray.getId());
URI haStorageSystem = null;
VirtualPoolCapabilityValuesWrapper haCapabilities = new VirtualPoolCapabilityValuesWrapper(capabilities);
// Don't look for SRDF in the HA side.
haCapabilities.put(VirtualPoolCapabilityValuesWrapper.PERSONALITY, null);
// We don't require that the HA side have the same storage controller.
haCapabilities.put(VirtualPoolCapabilityValuesWrapper.BLOCK_CONSISTENCY_GROUP, null);
Map<String, Object> attributeMap = new HashMap<String, Object>();
List<StoragePool> allMatchingPoolsForHaVarray = getMatchingPools(haVarray, haStorageSystem, haVpool, haCapabilities, attributeMap);
if (allMatchingPoolsForHaVarray.isEmpty()) {
StringBuffer errorMessage = new StringBuffer();
if (attributeMap.get(AttributeMatcher.ERROR_MESSAGE) != null) {
errorMessage = (StringBuffer) attributeMap.get(AttributeMatcher.ERROR_MESSAGE);
}
throw BadRequestException.badRequests.noMatchingHighAvailabilityStoragePools(haVpool.getLabel(), haVarray.getLabel(), errorMessage.toString());
}
_log.info("Found {} matching pools for HA varray", allMatchingPoolsForHaVarray.size());
// Sort the matching pools for the HA varray by VPLEX system.
Map<String, List<StoragePool>> vplexPoolMapForHaVarray = sortPoolsByVPlexStorageSystem(allMatchingPoolsForHaVarray, haVarray.getId().toString());
if (vplexPoolMapForHaVarray.isEmpty()) {
_log.info("No matching pools on storage systems connected to a VPlex");
// on storage systems connected to a VPlex storage system.
return recommendations;
}
// Get the list of potential VPlex storage systems for the source
// virtual array.
Set<String> vplexStorageSystemIds = vplexPoolMapForSrcVarray.keySet();
_log.info("{} VPlex storage systems have matching pools", vplexStorageSystemIds.size());
// Get the possible high availability varrays for each of these
// potential VPlex storage system.
Map<String, List<String>> vplexHaVarrayMap = ConnectivityUtil.getVPlexVarrays(_dbClient, vplexStorageSystemIds, srcVarray.getId());
// Loop over the potential VPlex storage systems, and attempt
// to place the resources.
Iterator<String> vplexSystemIdsIter = vplexStorageSystemIds.iterator();
while ((vplexSystemIdsIter.hasNext()) && (recommendations.isEmpty())) {
String vplexStorageSystemId = vplexSystemIdsIter.next();
_log.info("Attempting placement on VPlex {}", vplexStorageSystemId);
// Check if this VPLEX can satisfy the requested HA varray.
List<String> vplexHaVarrays = vplexHaVarrayMap.get(vplexStorageSystemId);
if (!vplexHaVarrays.contains(haVarray.getId().toString())) {
// It cannot, try the next VPLEX.
continue;
}
// Check if there are HA storage pools for this VPLEX.
if (!vplexPoolMapForHaVarray.containsKey(vplexStorageSystemId)) {
// There are no HA pools for this VPLEX, try the next.
continue;
}
// Check if the resource can be placed on the matching
// pools for this VPlex storage system in the source varray.
List<Recommendation> recommendationsForSrcVarray = new ArrayList<Recommendation>();
recommendationsForSrcVarray.addAll(createVPlexRecommendations(baseRecommendations, vplexStorageSystemId, srcVarray, srcVpool));
if (recommendationsForSrcVarray.isEmpty()) {
_log.info("Matching pools for source varray insufficient for placement");
// not sufficient, so we need to try another VPlex.
continue;
}
// Get the storage systems specified by these recommendations.
// We don't want to use these same storage systems on the HA
// side when the same system is available to both, else you
// could create a distributed volume with both backend volumes
// on the same physical array.
Set<URI> recommendedSrcSystems = new HashSet<URI>();
for (Recommendation recommendation : recommendationsForSrcVarray) {
recommendedSrcSystems.add(recommendation.getSourceStorageSystem());
}
// Remove any storage pools on these systems from the list of
// matching pools for the HA varray for this VPLEX system.
boolean haPoolsLimitedBySrcSelections = false;
List<StoragePool> vplexPoolsForHaVarray = new ArrayList<StoragePool>(vplexPoolMapForHaVarray.get(vplexStorageSystemId));
Iterator<StoragePool> vplexPoolsForHaVarrayIter = vplexPoolsForHaVarray.iterator();
while (vplexPoolsForHaVarrayIter.hasNext()) {
StoragePool haPool = vplexPoolsForHaVarrayIter.next();
URI poolSystem = haPool.getStorageDevice();
if (recommendedSrcSystems.contains(poolSystem)) {
_log.info("Removing pool {} on system {} from consideration for HA placement", haPool.getId(), poolSystem);
vplexPoolsForHaVarrayIter.remove();
haPoolsLimitedBySrcSelections = true;
}
}
// Now check if the resource can be placed on the matching
// pools for this VPlex storage system in the HA varray.
List<Recommendation> recommendationsForHaVarray = getRecommendationsForPools(haVarray.getId().toString(), haVpool, vplexPoolsForHaVarray, capabilities);
if (recommendationsForHaVarray.isEmpty()) {
_log.info("Matching pools for HA varray insufficient for placement");
if (haPoolsLimitedBySrcSelections) {
// If we limited the pools on the HA side and failed to place,
// then let's reverse and use all pools on the HA side and limit
// the source side. This is certainly not perfect, but at least
// will try and use the pools on both sides before giving up.
recommendationsForHaVarray = getRecommendationsForPools(haVarray.getId().toString(), haVpool, vplexPoolMapForHaVarray.get(vplexStorageSystemId), capabilities);
if (recommendationsForHaVarray.isEmpty()) {
// Still can't place them on the HA side.
_log.info("Matching pools for HA varray still insufficient for placement");
continue;
} else {
// Remove the systems from the source side and see
// if the source side can still be placed when limited.
_log.info("Matching pools for HA varray now sufficient for placement");
}
} else {
// not sufficient, so we need to try another VPlex.
continue;
}
}
// We have recommendations for pools in both the source and HA varrays.
recommendations.addAll(recommendationsForSrcVarray);
recommendations.addAll(createVPlexRecommendations(vplexStorageSystemId, haVarray, haVpool, recommendationsForHaVarray));
_log.info("Done trying to place resources for VPlex.");
break;
}
_placementManager.logRecommendations("VPLEX Distributed", recommendations);
return recommendations;
}
Aggregations