use of com.emc.storageos.util.NetworkLite in project coprhd-controller by CoprHD.
the class BlockStorageScheduler method getAllocatedPortsMap.
/**
* Converts Map<NetworkLite, List<StoragePort> to Map<URI, List<StoragePort>
* @param allocatedPorts map from NetworkLite to allocated ports
* @return map from network URI to allocated ports
*/
private Map<URI, List<StoragePort>> getAllocatedPortsMap(Map<NetworkLite, List<StoragePort>> allocatedPorts) {
Map<URI, List<StoragePort>> returnedPortMap = new HashMap<URI, List<StoragePort>>();
for (Map.Entry<NetworkLite, List<StoragePort>> entry : allocatedPorts.entrySet()) {
URI netURI = entry.getKey().getId();
returnedPortMap.put(netURI, entry.getValue());
}
return returnedPortMap;
}
use of com.emc.storageos.util.NetworkLite in project coprhd-controller by CoprHD.
the class BlockStorageScheduler method assignPrezonedStoragePorts.
/**
* Find the existing zones for a list of initiators. The initiators can be for a mask
* that is being created or for a mask to which new initiators are added. In the latter
* case the list of initiators would include only what is being added to the mask.
* <p>
* This existing zoning map returned by this function will be used by the port allocation code to give already zoned port priority over
* other ports.
* <p>
* This function will only do its work if the config item controller_port_alloc_by_metrics_only is set to false. The default value of
* the config is true.
* <p>
* This function will find existing zones for the list of initiators on the network system for all the storage system assignable ports.
* If duplicate zones are found for an initiator-port pair, the existing zone selection algorithm is applied.
* <p>
* If zones were found on the network systems for the initiators and ports, there can be 3 possible scenarios
* <ol>
* <li>the number of existing paths is equal that what is requested in the vpool, in this case the port allocation/assignment code would
* still be invoked but it will return no additional assignments</li>
* <li>the number of existing paths is less that what is requested in the vpool, additional assignments will be made by the port
* allocation/assignment code</li>
* <li>Not all existing paths should be used, for example there are more paths than requested by the vpool or it could be that some
* initiators have more paths that requested. The port allocation code is invoked to select the most favorable paths of the existing
* ones.</li>
* </ol>
* Note that by using existing zones, the path-per-initiator may be violated.
*
* @param storage the storage system where the mask will be or was created
* @param exportGroup the export group of the mask
* @param initiators the initiators being added to the mask.
* @param existingZoningMap this is the zoning map for an existing mask to which
* initiators are being added. It is null for new masks.
* @param pathParams the export group aggregated path parameter
* @param volumeURIs the volumes in the export mask
* @param virtualArrayUri the URI of the export virtual array
* @param token the workflow step Id
* @return a map of existing zones paths between the storage system ports and the
* mask initiators.
*/
public StringSetMap assignPrezonedStoragePorts(StorageSystem storage, ExportGroup exportGroup, List<Initiator> initiators, StringSetMap existingZoningMap, ExportPathParams pathParams, Collection<URI> volumeURIs, NetworkDeviceController networkDeviceController, URI virtualArrayUri, String token) {
// Prime the new zoning map with existing ones
StringSetMap newZoningMap = new StringSetMap();
if (existingZoningMap != null) {
newZoningMap.putAll(existingZoningMap);
}
// check if this is a backend export
boolean backend = ExportMaskUtils.areBackendInitiators(initiators);
// Adjust the paths param based on whether at the end of this call the ports selected should meet the paths requirement
ExportPathParams prezoningPathParams = getPrezoningPathParam(virtualArrayUri, pathParams, storage, backend);
try {
if (networkDeviceController == null) {
return newZoningMap;
}
if (!NetworkUtil.areNetworkSystemDiscovered(_dbClient)) {
_log.info("Cannot discover existing zones. There are no network systems discovered.");
return newZoningMap;
}
if (!_networkScheduler.portAllocationUseExistingZones(storage.getSystemType(), backend)) {
_log.info("The system configuration requests port selection to be based on metrics only " + "i.e. ignore existing zones when selecting ports.");
return newZoningMap;
}
_log.info("Checking for existing zoned ports for export {} before invoking port allocation.", exportGroup.getGeneratedName());
List<Initiator> newInitiators = new ArrayList<Initiator>();
for (Initiator initiator : initiators) {
if (!newZoningMap.containsKey(initiator.getId().toString())) {
newInitiators.add(initiator);
}
}
Map<Initiator, List<StoragePort>> assignments = new HashMap<Initiator, List<StoragePort>>();
Map<Initiator, List<StoragePort>> existingAssignments = generateInitiatorsToStoragePortsMap(existingZoningMap, virtualArrayUri);
if (!newInitiators.isEmpty()) {
// discover existing zones that are for the storage system and varray
// At this time we are not discovering routed zones but we will take care of this
Collection<StoragePort> ports = ExportUtils.getStorageSystemAssignablePorts(_dbClient, storage.getId(), virtualArrayUri, pathParams);
Map<NetworkLite, List<Initiator>> initiatorsByNetwork = NetworkUtil.getInitiatorsByNetwork(newInitiators, _dbClient);
Map<Initiator, NetworkLite> initiatorToNetworkLiteMap = getInitiatorToNetworkLiteMap(initiatorsByNetwork);
Map<NetworkLite, List<StoragePort>> portByNetwork = ExportUtils.mapStoragePortsToNetworks(ports, initiatorsByNetwork.keySet(), _dbClient);
Map<NetworkLite, StringSetMap> zonesByNetwork = new HashMap<NetworkLite, StringSetMap>();
// get all the prezoned ports for the initiators
Map<NetworkLite, List<StoragePort>> preZonedPortsByNetwork = getPrezonedPortsForInitiators(networkDeviceController, portByNetwork, initiatorsByNetwork, zonesByNetwork, token);
if (!preZonedPortsByNetwork.isEmpty()) {
// trim the initiators to the pre-zoned ports
StringMapUtil.retainAll(initiatorsByNetwork, preZonedPortsByNetwork);
Map<NetworkLite, List<StoragePort>> allocatedPortsByNetwork = allocatePorts(storage, virtualArrayUri, initiatorsByNetwork, preZonedPortsByNetwork, volumeURIs, prezoningPathParams, existingZoningMap);
Map<URI, List<StoragePort>> allocatedPortsMap = getAllocatedPortsMap(allocatedPortsByNetwork);
// Get a map of Host to Network to Initiators
Map<URI, Map<URI, List<Initiator>>> hostsToNetToInitiators = getHostInitiatorsMapFromNetworkLite(initiatorsByNetwork);
// Compute the number of Ports needed for each Network
StoragePortsAssigner assigner = StoragePortsAssignerFactory.getAssignerForZones(storage.getSystemType(), zonesByNetwork);
// Assign the storage ports on a per host basis.
for (Map.Entry<URI, Map<URI, List<Initiator>>> entry : hostsToNetToInitiators.entrySet()) {
URI hostURI = entry.getKey();
// The map of switch name to Initiators per network
Map<URI, Map<String, List<Initiator>>> switchInitiatorsByNet = new HashMap<URI, Map<String, List<Initiator>>>();
// The map of swtich name to storage ports per network
Map<URI, Map<String, List<StoragePort>>> switchStoragePortsByNet = new HashMap<URI, Map<String, List<StoragePort>>>();
Map<URI, List<Initiator>> initiatorByNetMap = entry.getValue();
PlacementUtils.getSwitchfoForInititaorsStoragePorts(initiatorByNetMap, allocatedPortsMap, _dbClient, storage, switchInitiatorsByNet, switchStoragePortsByNet);
assigner.assignPortsToHost(assignments, entry.getValue(), allocatedPortsMap, prezoningPathParams, existingAssignments, hostURI, initiatorToNetworkLiteMap, switchInitiatorsByNet, switchStoragePortsByNet);
}
addAssignmentsToZoningMap(assignments, newZoningMap);
}
// if manual zoning is on, then make sure the paths discovered meet the path requirement
if (allocateFromPrezonedPortsOnly(virtualArrayUri, storage.getSystemType(), backend)) {
try {
validateMinPaths(storage, prezoningPathParams, existingAssignments, assignments, newInitiators);
} catch (PlacementException pex) {
_log.error("There are fewer pre-zoned paths than required by the virtual pool." + " Please either add the needed paths or enable automatic SAN zoning in the virtual array" + " so that the additional paths can be added by the application.", pex);
throw pex;
}
}
}
_log.info("Zoning map after the assignment of pre-zoned ports: {}", newZoningMap);
} catch (Exception ex) {
_log.error("Failed to assign from pre-zoned storage ports because: ", ex);
if (allocateFromPrezonedPortsOnly(virtualArrayUri, storage.getSystemType(), backend)) {
_log.error("The virtual array is configured for manual zoning and the application " + "cannot assign from other storage ports. Failing the workflow.");
throw ex;
} else {
_log.info("The virtual array is configured for auto zoning and the application " + "will attempt to assign from other storage ports. Resuming the workflow.");
}
}
return newZoningMap;
}
use of com.emc.storageos.util.NetworkLite in project coprhd-controller by CoprHD.
the class BlockStorageScheduler method getPrezonedPortsForInitiators.
/**
* Reads the existing zones for the initiators from the network system and finds all ports that are
* already prezoned to one or more of the initiators.
*
* @param networkDeviceController an instance of networkDeviceController
* @param portByNetwork the ports in the export mask grouped by network
* @param initiatorsByNetwork the initiators of interest grouped by network
* @param zonesByNetwork an OUT param to collect the zones found grouped by network
* @param token the workflow step id
* @return a map of ports in networks that are already zoned to one or more of the initiators
*/
public Map<NetworkLite, List<StoragePort>> getPrezonedPortsForInitiators(NetworkDeviceController networkDeviceController, Map<NetworkLite, List<StoragePort>> portByNetwork, Map<NetworkLite, List<Initiator>> initiatorsByNetwork, Map<NetworkLite, StringSetMap> zonesByNetwork, String token) {
// so now we have a a collection of initiators and ports, let's get the zones
Map<NetworkLite, List<StoragePort>> preZonedPortsByNetwork = new HashMap<NetworkLite, List<StoragePort>>();
StringSetMap zonesInNetwork = null;
Map<String, List<Zone>> initiatorWwnToZonesMap = new HashMap<String, List<Zone>>();
for (NetworkLite network : portByNetwork.keySet()) {
if (!Transport.FC.toString().equals(network.getTransportType())) {
continue;
}
List<Initiator> networkInitiators = initiatorsByNetwork.get(network);
if (networkInitiators == null || networkInitiators.isEmpty()) {
continue;
}
Map<String, StoragePort> portByWwn = DataObjectUtils.mapByProperty(portByNetwork.get(network), "portNetworkId");
URI[] networkSystemURIUsed = new URI[1];
zonesInNetwork = networkDeviceController.getZoningMap(network, networkInitiators, portByWwn, initiatorWwnToZonesMap, networkSystemURIUsed);
_log.info("Existing zones in network {} are {}", network.getNativeGuid(), zonesInNetwork);
// if the OUT parameter is not null, fill in the discovered zones
if (zonesByNetwork != null && !zonesInNetwork.isEmpty()) {
zonesByNetwork.put(network, zonesInNetwork);
}
for (String iniId : zonesInNetwork.keySet()) {
for (String portId : zonesInNetwork.get(iniId)) {
StringMapUtil.addToListMap(preZonedPortsByNetwork, network, DataObjectUtils.findInCollection(portByNetwork.get(network), URI.create(portId)));
}
}
}
// now store the retrieved zones in ZK
if (!initiatorWwnToZonesMap.isEmpty()) {
Map<String, List<Zone>> zonesMap = (Map<String, List<Zone>>) WorkflowService.getInstance().loadWorkflowData(token, "zonemap");
// some workflows call port allocation more than one time, rather than overriding, add to these zones to already stored zones.
if (zonesMap == null) {
zonesMap = initiatorWwnToZonesMap;
} else {
zonesMap.putAll(initiatorWwnToZonesMap);
}
WorkflowService.getInstance().storeWorkflowData(token, "zonemap", zonesMap);
}
return preZonedPortsByNetwork;
}
use of com.emc.storageos.util.NetworkLite in project coprhd-controller by CoprHD.
the class VPlexBackendManager method generateExportMasks.
private Map<ExportMask, ExportGroup> generateExportMasks(URI varrayURI, StorageSystem vplex, StorageSystem array, String stepId, StringBuilder errorMessages) {
// Build the data structures used for analysis and validation.
buildDataStructures(vplex, array, varrayURI);
// Assign initiators to hosts
String clusterName = getClusterName(vplex);
Set<Map<String, Map<URI, Set<Initiator>>>> initiatorGroups = getInitiatorGroups(clusterName, _directorToInitiatorIds, _initiatorIdToNetwork, _idToInitiatorMap, array.getSystemType().equals(SystemType.vnxblock.name()), false);
// First we must determine the Initiator Groups and PortGroups to be used.
VplexBackEndMaskingOrchestrator orca = getOrch(array);
// set VPLEX director count to set number of paths per director
if (orca instanceof VplexXtremIOMaskingOrchestrator) {
// get VPLEX director count
int directorCount = getVplexDirectorCount(initiatorGroups);
((VplexXtremIOMaskingOrchestrator) orca).setVplexDirectorCount(directorCount);
}
// get the allocatable ports - if the custom config requests pre-zoned ports to be used
// get the existing zones in zonesByNetwork
Map<NetworkLite, StringSetMap> zonesByNetwork = new HashMap<NetworkLite, StringSetMap>();
Map<URI, List<StoragePort>> allocatablePorts = getAllocatablePorts(array, _networkMap.keySet(), varrayURI, zonesByNetwork, stepId);
Map<ExportMask, ExportGroup> exportMasksMap = new HashMap<ExportMask, ExportGroup>();
if (allocatablePorts.isEmpty()) {
String message = "No allocatable ports found for export to VPLEX backend. ";
_log.warn(message);
if (errorMessages != null) {
errorMessages.append(message);
}
_log.warn("Returning empty export mask map because no allocatable ports could be found.");
return exportMasksMap;
}
Map<URI, Map<String, Integer>> switchToPortNumber = getSwitchToMaxPortNumberMap(array);
Set<Map<URI, List<List<StoragePort>>>> portGroups = orca.getPortGroups(allocatablePorts, _networkMap, varrayURI, initiatorGroups.size(), switchToPortNumber, null, errorMessages);
// Now generate the Masking Views that will be needed.
Map<URI, String> initiatorSwitchMap = new HashMap<URI, String>();
Map<URI, Map<String, List<StoragePort>>> switchStoragePortsMap = new HashMap<URI, Map<String, List<StoragePort>>>();
Map<URI, List<StoragePort>> storageports = getStoragePorts(portGroups);
Map<URI, String> portSwitchMap = new HashMap<URI, String>();
PlacementUtils.getSwitchNameForInititaorsStoragePorts(_initiators, storageports, _dbClient, array, initiatorSwitchMap, switchStoragePortsMap, portSwitchMap);
Iterator<Map<String, Map<URI, Set<Initiator>>>> igIterator = initiatorGroups.iterator();
// get the assigner needed - it is with a pre-zoned ports assigner or the default
StoragePortsAssigner assigner = StoragePortsAssignerFactory.getAssignerForZones(array.getSystemType(), zonesByNetwork);
for (Map<URI, List<List<StoragePort>>> portGroup : portGroups) {
String maskName = clusterName.replaceAll("[^A-Za-z0-9_]", "_");
_log.info("Generating ExportMask: " + maskName);
if (!igIterator.hasNext()) {
igIterator = initiatorGroups.iterator();
}
Map<String, Map<URI, Set<Initiator>>> initiatorGroup = igIterator.next();
StringSetMap zoningMap = orca.configureZoning(portGroup, initiatorGroup, _networkMap, assigner, initiatorSwitchMap, switchStoragePortsMap, portSwitchMap);
ExportMask exportMask = generateExportMask(array.getId(), maskName, portGroup, initiatorGroup, zoningMap);
// Set a flag indicating that we do not want to remove zoningMap entries
StringSetMap map = new StringSetMap();
StringSet values = new StringSet();
values.add(Boolean.TRUE.toString());
map.put(ExportMask.DeviceDataMapKeys.ImmutableZoningMap.name(), values);
if (array.getSystemType().equals(SystemType.vmax.name())) {
// If VMAX, set consisteLUNs = false
values = new StringSet();
values.add(Boolean.FALSE.toString());
map.put(ExportMask.DeviceDataMapKeys.VMAXConsistentLUNs.name(), values);
}
exportMask.addDeviceDataMap(map);
// Create an ExportGroup for the ExportMask.
List<Initiator> initiators = new ArrayList<Initiator>();
for (String director : initiatorGroup.keySet()) {
for (URI networkURI : initiatorGroup.get(director).keySet()) {
for (Initiator initiator : initiatorGroup.get(director).get(networkURI)) {
initiators.add(initiator);
}
}
}
_dbClient.createObject(exportMask);
ExportGroup exportGroup = ExportUtils.createVplexExportGroup(_dbClient, vplex, array, initiators, varrayURI, _projectURI, _tenantURI, 0, exportMask);
exportMasksMap.put(exportMask, exportGroup);
}
return exportMasksMap;
}
use of com.emc.storageos.util.NetworkLite in project coprhd-controller by CoprHD.
the class VPlexBackendManager method getAllocatablePorts.
/**
* Returns a list of all possible allocatable ports on an array for a given set of Networks.
*
* @param array
* the storage array
* @param varray
* -- URI of varray
* @param networkURI
* -- Set<URI> of networks
* @param zonesByNetwork
* an OUT param to collect the zones found grouped by network
* @param token
* the workflow step id
*
* @return
*/
public Map<URI, List<StoragePort>> getAllocatablePorts(StorageSystem array, Set<URI> networkURIs, URI varray, Map<NetworkLite, StringSetMap> zonesByNetwork, String stepId) {
Collection<NetworkLite> networks = NetworkUtil.queryNetworkLites(networkURIs, _dbClient);
Map<URI, List<StoragePort>> map = new HashMap<URI, List<StoragePort>>();
// find all the available storage ports
Map<NetworkLite, List<StoragePort>> tempMap = _blockStorageScheduler.selectStoragePortsInNetworks(array.getId(), networks, varray, null);
// if the user requests to use only pre-zoned ports, then filter to pre-zoned ports only
if (_networkDeviceController.getNetworkScheduler().portAllocationUseExistingZones(array.getSystemType(), true)) {
Map<NetworkLite, List<Initiator>> initiatorsByNetwork = NetworkUtil.getInitiatorsByNetwork(_initiators, _dbClient);
tempMap = _blockStorageScheduler.getPrezonedPortsForInitiators(_networkDeviceController, tempMap, initiatorsByNetwork, zonesByNetwork, stepId);
}
for (NetworkLite network : tempMap.keySet()) {
map.put(network.getId(), tempMap.get(network));
}
return map;
}
Aggregations