use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class VPlexScheduler method scheduleStorageForLocalVPLEXVolume.
/**
* Get recommendations for resource placement for local VPLEX volumes.
*
* @param varray 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 storageSystem The URI of a specific backend storage system to
* which the source resource should be limited, or null when it
* doesn't matter.
* @param vpool The virtual pool requested for the source resources.
* @param capabilities The virtual pool capabilities.
*
* @return A list of VPlexRecommendation instances specifying the
* recommended resource placement.
*/
private List<Recommendation> scheduleStorageForLocalVPLEXVolume(VirtualArray varray, Set<URI> requestedVPlexSystems, URI storageSystem, VirtualPool vpool, VirtualPoolCapabilityValuesWrapper capabilities, Project project, VpoolUse vPoolUse, Map<VpoolUse, List<Recommendation>> currentRecommendations) {
_log.info("Executing VPlex high availability placement strategy for Local VPLEX volumes");
// of the StorageSystemsMatcher.
if (storageSystem != null) {
StorageSystem sourceStorageSystem = _dbClient.queryObject(StorageSystem.class, storageSystem);
capabilities.put(VirtualPoolCapabilityValuesWrapper.SOURCE_STORAGE_SYSTEM, sourceStorageSystem);
}
// Initialize the list of recommendations that will be returned
List<Recommendation> recommendations = new ArrayList<Recommendation>();
// Call the lower level scheduler to get its baseRecommendations.
Scheduler nextScheduler = _placementManager.getNextScheduler(SCHEDULER_NAME, vpool, vPoolUse);
_log.info(String.format("Calling next scheduler: %s", nextScheduler.getClass().getSimpleName()));
List<Recommendation> baseRecommendations = nextScheduler.getRecommendationsForVpool(varray, project, vpool, vPoolUse, capabilities, currentRecommendations);
_log.info(String.format("Received %d recommendations from %s", baseRecommendations.size(), nextScheduler.getClass().getSimpleName()));
List<StoragePool> allMatchingPools = _placementManager.getStoragePoolsFromRecommendations(baseRecommendations);
_log.info("Found {} matching pools for varray", allMatchingPools.size());
// Sort the matching pools by VPLEX system.
Map<String, List<StoragePool>> vplexPoolMapForSrcVarray = getVPlexConnectedMatchingPools(varray, requestedVPlexSystems, capabilities, allMatchingPools);
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;
}
// See if any one VPlex system can utilize all the specified pools.
for (Map.Entry<String, List<StoragePool>> entry : vplexPoolMapForSrcVarray.entrySet()) {
if (entry.getValue().containsAll(allMatchingPools)) {
_log.info(String.format("Generating local recommendations for VPLEX %s", entry.getKey()));
recommendations.addAll(createVPlexRecommendations(baseRecommendations, entry.getKey(), varray, vpool));
break;
}
}
if (recommendations.isEmpty()) {
_log.info("No single VPLEX could front the entire set of recommendations");
}
_placementManager.logRecommendations("VPLEX Local", recommendations);
return recommendations;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class VPlexScheduler method scheduleStorageForMirror.
/**
* Get recommendations for resource placement based on the passed
* parameters.
*
* @param srcVarray The VirtualArray in which the resources were requested.
* @param srcVpool Source volume virtual pool
* @param mirrorVpool The virtual pool to be used for mirror
* @param srcVpool The VirtualPool requested for the source resources.
* @param capabilities The VirtualPool capabilities.
* @param vplexStorageSystemURI The URI of the VPLEX system to which resources should be connected
* @param excludeStorageSystem The URI of the storage system that needs to be excluded
* @param cluster The VPLEX cluster to which resources should be connected
*
* @return A list of VPlexRecommendation instances specifying the
* recommended resource placement resources.
*/
public List<Recommendation> scheduleStorageForMirror(VirtualArray srcVarray, VirtualPool srcVpool, VirtualPool mirrorVpool, VirtualPoolCapabilityValuesWrapper capabilities, URI vplexStorageSystemURI, URI excludeStorageSystem, String cluster) {
_log.info("Executing VPlex Mirror placement strategy");
// Initialize the list of recommendations.
List<Recommendation> recommendations = new ArrayList<Recommendation>();
// Get all storage pools that match the passed VirtualPool params,
// and virtual array. In addition, the pool must
// have enough capacity to hold at least one resource of the
// requested size.
_log.info("Getting placement recommendations for srcVarray {}", srcVarray.getId());
Map<String, Object> attributeMap = new HashMap<String, Object>();
List<StoragePool> allMatchingPools = getMatchingPools(srcVarray, null, excludeStorageSystem, mirrorVpool, capabilities, attributeMap);
_log.info("Found {} Matching pools for VirtualArray for the Mirror", allMatchingPools.size());
// If the attribute matcher framework returns an error, then throw that error.
// Otherwise, even when there are no pools, let the code return the empty list
// of recommendations which is handled by the caller. This code was added for
// COP-17666, but resulted in a regression captured by COP-25216. Therefore,
// we now only throw an exception if there is an actual error set by a matcher.
// If there is no error, returning the empty list will result in the previous
// message being displayed.
StringBuffer errorMessage = (StringBuffer) attributeMap.get(AttributeMatcher.ERROR_MESSAGE);
if ((CollectionUtils.isEmpty(allMatchingPools)) && (errorMessage != null) && (errorMessage.length() != 0)) {
throw APIException.badRequests.noStoragePools(srcVarray.getLabel(), srcVpool.getLabel(), errorMessage.toString());
}
// Due to VirtualPool attribute matching, we should only get storage
// pools on storage systems that are connected to a VPlex
// storage system. We find these storage pools and associate
// them to the VPlex storage systems to which their storage
// systems are connected.
Map<String, List<StoragePool>> vplexPoolMapForSrcVarray = sortPoolsByVPlexStorageSystem(allMatchingPools, srcVarray.getId().toString(), cluster);
// If only specified VPlex from source volume is desired, filter the vplexPoolMapForSrcVarray
// to only use pools from the vplexStorageSystemURI.
Iterator<Entry<String, List<StoragePool>>> it = vplexPoolMapForSrcVarray.entrySet().iterator();
if (vplexStorageSystemURI != null) {
while (it.hasNext()) {
Entry<String, List<StoragePool>> entry = it.next();
String vplexKey = entry.getKey();
URI vplexURI = null;
try {
vplexURI = URI.create(vplexKey);
} catch (IllegalArgumentException ex) {
_log.error("Bad VPLEX URI: " + vplexURI);
continue;
}
if (false == vplexStorageSystemURI.equals(vplexURI)) {
it.remove();
}
}
}
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;
}
// The list of potential VPlex storage systems.
Set<String> vplexStorageSystemIds = vplexPoolMapForSrcVarray.keySet();
vplexStorageSystemIds = vplexPoolMapForSrcVarray.keySet();
_log.info("{} VPlex storage systems have matching pools", vplexStorageSystemIds.size());
Iterator<String> vplexSystemIdsIter = vplexStorageSystemIds.iterator();
while ((vplexSystemIdsIter.hasNext()) && (recommendations.isEmpty())) {
String vplexStorageSystemId = vplexSystemIdsIter.next();
_log.info("Check matching pools for VPlex {}", vplexStorageSystemId);
// pools for this VPlex storage system.
if (VirtualPool.ProvisioningType.Thin.toString().equalsIgnoreCase(mirrorVpool.getSupportedProvisioningType())) {
capabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, Boolean.TRUE);
}
List<Recommendation> recommendationsForMirrorVarray = _blockScheduler.getRecommendationsForPools(srcVarray.getId().toString(), vplexPoolMapForSrcVarray.get(vplexStorageSystemId), capabilities);
if (recommendationsForMirrorVarray.isEmpty()) {
_log.info("Matching pools insufficient for placement");
// not sufficient, so we need to try another VPlex.
continue;
}
_log.info("Matching pools sufficient for placement");
recommendations.addAll(createVPlexRecommendations(vplexStorageSystemId, srcVarray, srcVpool, recommendationsForMirrorVarray));
continue;
}
return recommendations;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class VPlexScheduler method scheduleStorageForImport.
/**
* Schedule Storage for a VPLEX import operation where we are creating the
* HA volume.
*
* @param srcNH Source Neighborhood
* @param vplexs Set<URI> Set of Vplex System URIs that can be used
* @param requestedHaNH Optional requested HA Neighborhood. Can be null.
* @param cos CoS to be used for new volumes
* @param capabilities CoS capabilities to be used for new volume
* @return List<Recommendation>
*/
public List<Recommendation> scheduleStorageForImport(VirtualArray srcNH, Set<URI> vplexs, VirtualArray requestedHaNH, VirtualPool cos, VirtualPoolCapabilityValuesWrapper capabilities) {
Set<String> vplexSystemIds = new HashSet<String>();
for (URI vplexURI : vplexs) {
vplexSystemIds.add(vplexURI.toString());
}
List<Recommendation> recommendations = new ArrayList<Recommendation>();
// For an HA request, get the possible high availability neighborhoods
// for each potential VPlex storage system.
Map<String, List<String>> vplexHaNHMap = ConnectivityUtil.getVPlexVarrays(_dbClient, vplexSystemIds, srcNH.getId());
for (URI vplexSystemURI : vplexs) {
StorageSystem vplexSystem = _dbClient.queryObject(StorageSystem.class, vplexSystemURI);
// See if there is an HA varray
// for the VPlex that also contains pools suitable to place
// the resources.
List<String> vplexHaNHIds = vplexHaNHMap.get(vplexSystem.getId().toString());
if (vplexHaNHIds == null) {
continue;
}
_log.info("Found {} HA varrays", vplexHaNHIds.size());
for (String vplexHaNHId : vplexHaNHIds) {
_log.info("Check HA varray {}", vplexHaNHId);
// varray is not it, then skip the varray.
if ((requestedHaNH != null) && (!vplexHaNHId.equals(requestedHaNH.getId().toString()))) {
_log.info("Not the requested HA varray, skip");
continue;
}
// Get all storage pools that match the passed CoS params,
// protocols, and this HA varray. In addition, the
// pool must have enough capacity to hold at least one
// resource of the requested size.
VirtualArray vplexHaNH = _dbClient.queryObject(VirtualArray.class, URI.create(vplexHaNHId));
Map<String, Object> attributeMap = new HashMap<String, Object>();
List<StoragePool> allMatchingPools = getMatchingPools(vplexHaNH, null, cos, capabilities, attributeMap);
_log.info("Found {} matching pools for HA varray", allMatchingPools.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>> vplexPoolMapForHaNH = sortPoolsByVPlexStorageSystem(allMatchingPools, vplexHaNHId);
// 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> recommendationsForHaNH = new ArrayList<Recommendation>();
if (vplexPoolMapForHaNH.containsKey(vplexSystem.getId().toString())) {
_log.info("Found matching pools in HA NH for VPlex {}", vplexSystem.getId());
recommendationsForHaNH = _blockScheduler.getRecommendationsForPools(vplexHaNH.getId().toString(), vplexPoolMapForHaNH.get(vplexSystem.getId().toString()), capabilities);
} else {
_log.info("No matching pools in HA NH for VPlex {}", vplexSystem.getId());
}
recommendations.addAll(createVPlexRecommendations(vplexSystem.getId().toString(), vplexHaNH, cos, recommendationsForHaNH));
}
}
return recommendations;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class AbstractBlockServiceApiImpl method createVolumesAndDescriptors.
@Override
public List<VolumeDescriptor> createVolumesAndDescriptors(List<VolumeDescriptor> descriptors, String name, Long size, Project project, VirtualArray varray, VirtualPool vpool, List<Recommendation> recommendations, TaskList taskList, String task, VirtualPoolCapabilityValuesWrapper vpoolCapabilities) {
BlockServiceApi api = null;
List<VolumeDescriptor> volumeDescriptors = new ArrayList<VolumeDescriptor>();
for (Recommendation recommendation : recommendations) {
if (recommendation instanceof SRDFRecommendation || recommendation instanceof SRDFCopyRecommendation) {
api = BlockService.getBlockServiceImpl(DiscoveredDataObject.Type.srdf.name());
} else if (recommendation instanceof VolumeRecommendation) {
api = BlockService.getBlockServiceImpl(BlockServiceApi.DEFAULT);
} else {
String message = String.format("No BlockServiceApiImpl to handle recommendation of class: ", recommendation.getClass().getName());
s_logger.error(message);
throw WorkflowException.exceptions.workflowConstructionError(message);
}
volumeDescriptors.addAll(api.createVolumesAndDescriptors(descriptors, name, size, project, varray, vpool, recommendations, taskList, task, vpoolCapabilities));
}
return volumeDescriptors;
}
use of com.emc.storageos.volumecontroller.Recommendation in project coprhd-controller by CoprHD.
the class BlockMirrorServiceApiImpl method startNativeContinuousCopies.
@Override
public TaskList startNativeContinuousCopies(StorageSystem storageSystem, Volume sourceVolume, VirtualPool sourceVirtualPool, VirtualPoolCapabilityValuesWrapper capabilities, NativeContinuousCopyCreate param, String taskId) throws ControllerException {
if (!((storageSystem.getUsingSmis80() && storageSystem.deviceIsType(Type.vmax)) || storageSystem.deviceIsType(Type.vnxblock))) {
validateNotAConsistencyGroupVolume(sourceVolume, sourceVirtualPool);
}
TaskList taskList = new TaskList();
// Currently, this will create a single mirror and add it to the source volume
// Two steps: first place the mirror and then prepare the mirror.
List<Recommendation> volumeRecommendations = new ArrayList<Recommendation>();
// Prepare mirror.
int volumeCounter = 1;
int volumeCount = capabilities.getResourceCount();
String volumeLabel = param.getName();
List<Volume> preparedVolumes = new ArrayList<Volume>();
// If the requested volume is part of CG
if (sourceVolume.isInCG()) {
if (volumeCount > 1) {
throw APIException.badRequests.invalidMirrorCountForVolumesInConsistencyGroup();
}
URIQueryResultList cgVolumeList = new URIQueryResultList();
_dbClient.queryByConstraint(ContainmentConstraint.Factory.getVolumesByConsistencyGroup(sourceVolume.getConsistencyGroup()), cgVolumeList);
// recommendation
while (cgVolumeList.iterator().hasNext()) {
Volume cgSourceVolume = _dbClient.queryObject(Volume.class, cgVolumeList.iterator().next());
_log.info("Processing volume {} in CG {}", cgSourceVolume.getId(), sourceVolume.getConsistencyGroup());
VirtualPool cgVolumeVPool = _dbClient.queryObject(VirtualPool.class, cgSourceVolume.getVirtualPool());
populateVolumeRecommendations(capabilities, cgVolumeVPool, cgSourceVolume, taskId, taskList, volumeCount, volumeCounter, volumeLabel, preparedVolumes, volumeRecommendations);
}
} else {
// Source Volume without CG
populateVolumeRecommendations(capabilities, sourceVirtualPool, sourceVolume, taskId, taskList, volumeCount, volumeCounter, volumeLabel, preparedVolumes, volumeRecommendations);
}
List<URI> mirrorList = new ArrayList<URI>(preparedVolumes.size());
for (Volume volume : preparedVolumes) {
Operation op = _dbClient.createTaskOpStatus(BlockMirror.class, volume.getId(), taskId, ResourceOperationTypeEnum.ATTACH_BLOCK_MIRROR);
volume.getOpStatus().put(taskId, op);
TaskResourceRep volumeTask = toTask(volume, taskId, op);
taskList.getTaskList().add(volumeTask);
mirrorList.add(volume.getId());
}
BlockController controller = getController(BlockController.class, storageSystem.getSystemType());
try {
controller.attachNativeContinuousCopies(storageSystem.getId(), sourceVolume.getId(), mirrorList, taskId);
} catch (ControllerException ce) {
String errorMsg = format("Failed to start continuous copies on volume %s: %s", sourceVolume.getId(), ce.getMessage());
_log.error(errorMsg, ce);
for (TaskResourceRep taskResourceRep : taskList.getTaskList()) {
taskResourceRep.setState(Operation.Status.error.name());
taskResourceRep.setMessage(errorMsg);
Operation statusUpdate = new Operation(Operation.Status.error.name(), errorMsg);
_dbClient.updateTaskOpStatus(Volume.class, taskResourceRep.getResource().getId(), taskId, statusUpdate);
}
throw ce;
}
return taskList;
}
Aggregations