use of com.emc.storageos.volumecontroller.Recommendation 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.Recommendation in project coprhd-controller by CoprHD.
the class VolumeRecommendation method getDeviceMap.
/**
* Return a map of device URI to a list of recommendations in that device.
* This method can be used only for block volume recommendations since it assumes that there is only a single pool in the recommended
* storage pools.
*
* @param recommendations List<VolumeRecommendation>
* @param dbClient
* @return Map of device URI to List<VolumeRecommendation> in that device
*/
public static Map<URI, List<VolumeRecommendation>> getDeviceMap(List<Recommendation> recommendations, DbClient dbClient) {
HashMap<URI, List<VolumeRecommendation>> deviceMap = new HashMap<URI, List<VolumeRecommendation>>();
for (Recommendation baseRecommendation : recommendations) {
VolumeRecommendation recommendation = (VolumeRecommendation) baseRecommendation;
URI poolId = recommendation.getCandidatePools().get(0);
StoragePool storagePool = dbClient.queryObject(StoragePool.class, poolId);
URI deviceId = storagePool.getStorageDevice();
if (deviceMap.get(deviceId) == null) {
deviceMap.put(deviceId, new ArrayList<VolumeRecommendation>());
}
deviceMap.get(deviceId).add(recommendation);
}
return deviceMap;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class FileStorageScheduler method prepareFileSystems.
/**
* create fileshare from the Recommendation object
*
* @param param
* -file share create param
* @param task
* -task id
* @param taskList
* - task list
* @param project
* -project
* @param varray
* - Virtual Array
* @param vpool
* - Virtual Pool
* @param recommendations
* - recommendation structure
* @param cosCapabilities
* - Virtual pool wrapper
* @param createInactive
* - create device sync inactive
* @return
*/
public List<FileShare> prepareFileSystems(FileSystemParam param, String task, TaskList taskList, Project project, VirtualArray varray, VirtualPool vpool, List<Recommendation> recommendations, VirtualPoolCapabilityValuesWrapper cosCapabilities, Boolean createInactive) {
List<FileShare> preparedFileSystems = new ArrayList<>();
Iterator<Recommendation> recommendationsIter = recommendations.iterator();
while (recommendationsIter.hasNext()) {
FileRecommendation recommendation = (FileRecommendation) recommendationsIter.next();
// If id is already set in recommendation, do not prepare the fileSystem (fileSystem already exists)
if (recommendation.getId() != null) {
continue;
}
if (recommendation.getFileType().toString().equals(FileRecommendation.FileType.FILE_SYSTEM_DATA.toString())) {
// Grab the existing fileshare and task object from the incoming task list
FileShare fileShare = getPrecreatedFile(taskList, param.getLabel());
// Set the recommendation
_log.info(String.format("createFileSystem --- FileShare: %1$s, StoragePool: %2$s, StorageSystem: %3$s", fileShare.getId(), recommendation.getSourceStoragePool(), recommendation.getSourceStorageSystem()));
setFileRecommendation(recommendation, fileShare, vpool, createInactive);
preparedFileSystems.add(fileShare);
}
}
return preparedFileSystems;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class VPlexScheduler method getRecommendationsForVpool.
@Override
public List<Recommendation> getRecommendationsForVpool(VirtualArray vArray, Project project, VirtualPool vPool, VpoolUse vPoolUse, VirtualPoolCapabilityValuesWrapper capabilities, Map<VpoolUse, List<Recommendation>> currentRecommendations) {
_log.info("Getting recommendations for VPlex volume placement");
// availability volumes.
if (!VirtualPool.vPoolSpecifiesHighAvailability(vPool)) {
throw APIException.badRequests.invalidHighAvailability(vPool.getHighAvailability());
}
_log.info("VirtualPool has high availability {}", vPool.getHighAvailability());
Set<URI> vplexSystemsForPlacement = new HashSet<URI>();
if (vPoolUse == VpoolUse.ROOT) {
// For now only validate that we're using the same vplex systems on the ROOT request
vplexSystemsForPlacement = getVPlexSystemsForPlacement(vArray, vPool, capabilities);
}
// Determine if the volume creation request is for HA volumes.
boolean isHAVolumeRequest = VirtualPool.vPoolSpecifiesHighAvailabilityDistributed(vPool);
// Get and validate the high availability VirtualArray and VirtualPool.
// Note that the HA VirtualPool is optional. When not specified, the
// high availability VirtualPool is the passed (root) VirtualPool.
VirtualPool haVPool = vPool;
VirtualArray haVArray = null;
StringMap haVaVpMap = vPool.getHaVarrayVpoolMap();
if ((isHAVolumeRequest) && (haVaVpMap != null)) {
_log.info("Is HA request and with an HA VirtualArray VirtualPool map");
Iterator<String> vaIter = haVaVpMap.keySet().iterator();
while (vaIter.hasNext()) {
String haVaId = vaIter.next();
_log.info("HA VirtualArray is {}", haVaId);
if (!haVaId.equals(NullColumnValueGetter.getNullURI().toString())) {
_log.info("HA VirtualArray is not a null URI");
haVArray = getVirtualArrayForVolumeCreateRequest(project, URI.create(haVaId));
if (vArray.getId().toString().equals(haVArray.getId().toString())) {
throw APIException.badRequests.sameVirtualArrayAndHighAvailabilityArray();
}
}
// Now get the VirtualPool.
String haVpId = haVaVpMap.get(haVaId);
_log.info("HA VirtualPool is {}", haVpId);
if (!haVpId.equals(NullColumnValueGetter.getNullURI().toString())) {
_log.info("HA VirtualPool is not a null URI");
haVPool = BlockService.getVirtualPoolForRequest(project, URI.create(haVpId), _dbClient, _permissionsHelper);
}
}
}
// Get the volume placement based on passed parameters.
_log.info("VirtualPool: {}, HA VirtualPool: {}", vPool.getId().toString(), haVPool.getId().toString());
List<Recommendation> recommendations = scheduleStorage(vArray, vplexSystemsForPlacement, null, vPool, isHAVolumeRequest, haVArray, haVPool, capabilities, project, vPoolUse, currentRecommendations);
return recommendations;
}
use of com.emc.storageos.volumecontroller.Recommendation 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