use of com.emc.storageos.volumecontroller.placement.StoragePortsAllocator in project coprhd-controller by CoprHD.
the class VplexCinderMaskingOrchestrator method getPortGroups.
@Override
public Set<Map<URI, List<List<StoragePort>>>> getPortGroups(Map<URI, List<StoragePort>> allocatablePorts, Map<URI, NetworkLite> networkMap, URI varrayURI, int nInitiatorGroups, Map<URI, Map<String, Integer>> switchToPortNumber, Map<URI, PortAllocationContext> contextMap, StringBuilder errorMessages) {
_log.debug("START - getPortGroups");
Set<Map<URI, List<List<StoragePort>>>> portGroups = new HashSet<Map<URI, List<List<StoragePort>>>>();
Map<URI, Integer> portsAllocatedPerNetwork = new HashMap<URI, Integer>();
// Port Group is always 1 for Cinder as of now.
for (URI netURI : allocatablePorts.keySet()) {
Integer nports = allocatablePorts.get(netURI).size() / CINDER_NUM_PORT_GROUP;
portsAllocatedPerNetwork.put(netURI, nports);
}
StoragePortsAllocator allocator = new StoragePortsAllocator();
for (int i = 0; i < CINDER_NUM_PORT_GROUP; i++) {
Map<URI, List<List<StoragePort>>> portGroup = new HashMap<URI, List<List<StoragePort>>>();
StringSet portNames = new StringSet();
for (URI netURI : allocatablePorts.keySet()) {
NetworkLite net = networkMap.get(netURI);
Map<String, Integer> switchCountMap = null;
if (switchToPortNumber != null) {
switchCountMap = switchToPortNumber.get(netURI);
}
PortAllocationContext context = null;
if (contextMap != null) {
context = contextMap.get(netURI);
}
List<StoragePort> allocatedPorts = allocatePorts(allocator, allocatablePorts.get(netURI), portsAllocatedPerNetwork.get(netURI), net, varrayURI, switchCountMap, context);
if (portGroup.get(netURI) == null) {
portGroup.put(netURI, new ArrayList<List<StoragePort>>());
}
portGroup.get(netURI).add(allocatedPorts);
allocatablePorts.get(netURI).removeAll(allocatedPorts);
for (StoragePort port : allocatedPorts) {
portNames.add(port.getPortName());
}
}
portGroups.add(portGroup);
_log.info(String.format("Port Group %d: port names in the port group {%s}", i, portNames.toString()));
}
_log.debug("END - getPortGroups");
return portGroups;
}
use of com.emc.storageos.volumecontroller.placement.StoragePortsAllocator in project coprhd-controller by CoprHD.
the class VplexXtremIOMaskingOrchestrator method getPortGroups.
@Override
public Set<Map<URI, List<List<StoragePort>>>> getPortGroups(Map<URI, List<StoragePort>> allocatablePorts, Map<URI, NetworkLite> networkMap, URI varrayURI, int nInitiatorGroups, Map<URI, Map<String, Integer>> switchToPortNumber, Map<URI, PortAllocationContext> contextMap, StringBuilder errorMessages) {
/**
* Number of Port Group for XtremIO is always one.
* - If multiple port groups, each VPLEX Director's initiators will be mapped to multiple ports
*
* Single Port Group contains different set of storage ports for each network,
* so that each VPLEX director's initiators will map to different port set.
*
* why allocatePorts() not required:
* allocatePorts() would return required number of storage ports from a network from unique X-bricks.
* But we need to select storage ports uniquely across X-bricks & StorageControllers and we need
* to make use of all storage ports.
*/
Set<Map<URI, List<List<StoragePort>>>> portGroups = new HashSet<Map<URI, List<List<StoragePort>>>>();
StringSet netNames = new StringSet();
// Order the networks from those with fewest ports to those with the most ports.
List<URI> orderedNetworks = orderNetworksByNumberOfPorts(allocatablePorts);
for (URI networkURI : orderedNetworks) {
netNames.add(networkMap.get(networkURI).getLabel());
}
_log.info("Calculating PortGroups for Networks: {}", netNames.toString());
StoragePortsAllocator allocator = new StoragePortsAllocator();
// Determine if we should check connectivity from the varray.auto_san_zoning
boolean sanZoningEnabled = false;
if (!simulation) {
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, varrayURI);
if (varray != null && NetworkScheduler.isZoningRequired(_dbClient, varray)) {
sanZoningEnabled = true;
}
}
/**
* Till all storage ports been processed:
* -- get a set of 4 storage ports selected equally across networks
* -- add this set into network to port List map (each port set within a network will be mapped for different
* directors)
*/
Map<URI, List<List<StoragePort>>> useablePorts = new HashMap<URI, List<List<StoragePort>>>();
Set<String> usedPorts = new HashSet<String>();
// map of selected X-brick to Storage Controllers across all networks
Map<String, List<String>> xBricksToSelectedSCs = new HashMap<String, List<String>>();
// map of network to selected X-bricks
Map<URI, List<String>> networkToSelectedXbricks = new HashMap<URI, List<String>>();
do {
Map<URI, List<StoragePort>> useablePortsSet = getUsablePortsSet(allocatablePorts, orderedNetworks, usedPorts, xBricksToSelectedSCs, networkToSelectedXbricks, networkMap, allocator, sanZoningEnabled, switchToPortNumber, contextMap);
if (useablePortsSet == null) {
// if requirement not satisfied
break;
}
for (URI networkURI : useablePortsSet.keySet()) {
if (!useablePorts.containsKey(networkURI)) {
useablePorts.put(networkURI, new ArrayList<List<StoragePort>>());
}
useablePorts.get(networkURI).add(useablePortsSet.get(networkURI));
}
} while (!isAllPortsLooped(orderedNetworks, allocatablePorts, usedPorts));
int numPG = XTREMIO_NUM_PORT_GROUP;
_log.info(String.format("Number of Port Groups: %d", numPG));
portGroups.add(useablePorts);
_log.info("Selected network to ports set: {}", useablePorts.entrySet());
// get number of X-bricks from selected ports
xtremIOXbricksCount = getXbricksCount(useablePorts);
return portGroups;
}
use of com.emc.storageos.volumecontroller.placement.StoragePortsAllocator in project coprhd-controller by CoprHD.
the class VPlexHDSMaskingOrchestrator method getPortGroups.
@Override
public Set<Map<URI, List<List<StoragePort>>>> getPortGroups(Map<URI, List<StoragePort>> allocatablePorts, Map<URI, NetworkLite> networkMap, URI varrayURI, int nInitiatorGroups, Map<URI, Map<String, Integer>> switchToPortNumber, Map<URI, PortAllocationContext> contextMap, StringBuilder errorMessages) {
Set<Map<URI, List<List<StoragePort>>>> portGroups = new HashSet<Map<URI, List<List<StoragePort>>>>();
// Group the networks into sets based on the number of ports they have.
StringSet netNames = new StringSet();
Map<Integer, Set<URI>> numPortsToNetworkSet = new HashMap<Integer, Set<URI>>();
for (URI networkURI : allocatablePorts.keySet()) {
int numPorts = allocatablePorts.get(networkURI).size();
if (numPorts > MAX_PORTS_PER_NETWORK) {
numPorts = MAX_PORTS_PER_NETWORK;
}
if (numPortsToNetworkSet.get(numPorts) == null) {
numPortsToNetworkSet.put(Integer.valueOf(numPorts), new HashSet<URI>());
}
numPortsToNetworkSet.get(Integer.valueOf(numPorts)).add(networkURI);
netNames.add(networkMap.get(networkURI).getLabel());
}
_log.info("Calculating PortGroups for Networks %s: " + netNames.toString());
// Eliminate ports from the same cpus, which are in the same portGroup.
// This is to avoid the 4096 LUN limit per cpu.
// Start with networks with fewest ports and work up. THis is because
// in the case of duplicate us of a cpu by two ports, we want to eliminate
// the port in the Network containing the most ports. So by starting with
// the Network with the fewest ports to populate the cpusUsed set, we will
// end up eliminating the port that is in the Network with a higher number of
// ports.
Set<String> cpusUsed = new HashSet<String>();
for (Integer numPorts = 1; numPorts < MAX_PORTS_PER_NETWORK; numPorts++) {
Set<URI> networkURIs = numPortsToNetworkSet.get(numPorts);
if (networkURIs == null) {
continue;
}
for (URI networkURI : networkURIs) {
List<StoragePort> nonConflictedPorts = new ArrayList<StoragePort>();
for (StoragePort port : allocatablePorts.get(networkURI)) {
if (!cpusUsed.contains(port.getPortGroup())) {
cpusUsed.add(port.getPortGroup());
nonConflictedPorts.add(port);
} else {
_log.info(String.format("Eliminating port %s because cpu already used", port.getPortName()));
}
}
allocatablePorts.put(networkURI, nonConflictedPorts);
}
}
// Determine the network with the lowest number of allocatable ports.
int minPorts = Integer.MAX_VALUE;
for (URI networkURI : allocatablePorts.keySet()) {
int numPorts = allocatablePorts.get(networkURI).size();
if (numPorts > MAX_PORTS_PER_NETWORK) {
numPorts = MAX_PORTS_PER_NETWORK;
}
if (numPorts < minPorts) {
minPorts = numPorts;
}
}
// Figure out the number of ports in each network per port group (PG).
// Then figure out the number of port groups to be generated.
// HEURISTIC:
// 1-3 ports, use 1 port per MV, unless there's only one Network, then use 2.
// If it has 8 or more ports, use 2 ports per network, 4 for MV.
// If it has 18 or more ports, use 3 ports per network, 6 per MV.
// oneNetwork indicates if there is only one Network available.
// portsPerPG is the number of ports to be allocated per PortGroup from the
// network with the fewest ports.
// numPG is the number of Port Groups that will be configured.
boolean oneNetwork = allocatablePorts.keySet().size() == 1;
int portsPerPG = oneNetwork ? 2 : 1;
if (minPorts >= 8) {
portsPerPG = 2;
}
if (minPorts >= 18) {
portsPerPG = 3;
}
int numPG = minPorts / portsPerPG;
if (numPG == 0) {
return portGroups;
}
_log.info(String.format("Number Port Groups %d Per Network Ports Per Group %d", numPG, portsPerPG));
// Make a map per Network of number of ports to allocate.
Map<URI, Integer> portsAllocatedPerNetwork = new HashMap<URI, Integer>();
for (URI netURI : allocatablePorts.keySet()) {
Integer nports = allocatablePorts.get(netURI).size() / numPG;
// ports from the network with the fewest ports, i.e. do not exceed 2x portsPerPG.
if (nports > (2 * portsPerPG)) {
nports = 2 * portsPerPG;
}
portsAllocatedPerNetwork.put(netURI, nports);
}
// Now call the StoragePortsAllocator for each Network, assigning required number of ports.
StoragePortsAllocator allocator = new StoragePortsAllocator();
for (int i = 0; i < numPG; i++) {
Map<URI, List<List<StoragePort>>> portGroup = new HashMap<URI, List<List<StoragePort>>>();
StringSet portNames = new StringSet();
for (URI netURI : allocatablePorts.keySet()) {
NetworkLite net = networkMap.get(netURI);
Map<String, Integer> switchCountMap = null;
if (switchToPortNumber != null) {
switchCountMap = switchToPortNumber.get(netURI);
}
PortAllocationContext context = null;
if (contextMap != null) {
context = contextMap.get(netURI);
}
List<StoragePort> allocatedPorts = allocatePorts(allocator, allocatablePorts.get(netURI), portsAllocatedPerNetwork.get(netURI), net, varrayURI, switchCountMap, context);
if (portGroup.get(netURI) == null) {
portGroup.put(netURI, new ArrayList<List<StoragePort>>());
}
portGroup.get(netURI).add(allocatedPorts);
allocatablePorts.get(netURI).removeAll(allocatedPorts);
for (StoragePort port : allocatedPorts) {
portNames.add(port.getPortName());
}
}
portGroups.add(portGroup);
_log.info(String.format("Port Group %d: %s", i, portNames.toString()));
// Reinitialize the context in the allocator; we want redundancy within PG
if (allocator.getContext() != null) {
allocator.getContext().reinitialize();
}
}
return portGroups;
}
use of com.emc.storageos.volumecontroller.placement.StoragePortsAllocator in project coprhd-controller by CoprHD.
the class VPlexVnxMaskingOrchestrator method getPortGroups.
/**
* Returns the set of port groups that should be used.
* Each port group is a map of Network to a list of Storage Ports in that Network.
* Since at most we can construct two InitiatorGroups, we try to construct
* two PortGroups.
*
* @return Sets of PortGroups, where each Port Group is a map of Network URI
* to a List of Storage Ports.
*/
@Override
public Set<Map<URI, List<List<StoragePort>>>> getPortGroups(Map<URI, List<StoragePort>> allocatablePorts, Map<URI, NetworkLite> networkMap, URI varrayURI, int nInitiatorGroups, Map<URI, Map<String, Integer>> switchToPortNumber, Map<URI, PortAllocationContext> contextMap, StringBuilder errorMessages) {
Set<Map<URI, List<List<StoragePort>>>> portGroups = new HashSet<Map<URI, List<List<StoragePort>>>>();
// Determine the network with the fewest ports. It will determine how many
// port groups can be made.
int minPorts = Integer.MAX_VALUE;
for (URI networkURI : allocatablePorts.keySet()) {
int numPorts = allocatablePorts.get(networkURI).size();
if (numPorts < minPorts) {
minPorts = numPorts;
}
}
// Figure out the number of ports in each network per port group (PG).
// Then figure out the number of port groups to be generated,
// which will always be one or two.
boolean oneNetwork = allocatablePorts.keySet().size() == 1;
int numPG = 1;
if (nInitiatorGroups == 2 && minPorts >= 2 && !oneNetwork) {
numPG = 2;
}
if (numPG == 0) {
return portGroups;
}
_log.info(String.format("Number Port Groups %d", numPG));
// Make a map per Network of number of ports to allocate.
Map<URI, Integer> portsAllocatedPerNetwork = new HashMap<URI, Integer>();
for (URI netURI : allocatablePorts.keySet()) {
// Calculate the number of ports to be allocated for this net. It is:
// the number of allocatable ports / numPG.
Integer nports = allocatablePorts.get(netURI).size() / numPG;
portsAllocatedPerNetwork.put(netURI, nports);
}
StoragePortsAllocator allocator = new StoragePortsAllocator();
for (int i = 0; i < numPG; i++) {
Map<URI, List<List<StoragePort>>> portGroup = new HashMap<URI, List<List<StoragePort>>>();
StringSet portNames = new StringSet();
for (URI netURI : allocatablePorts.keySet()) {
NetworkLite net = networkMap.get(netURI);
Map<String, Integer> switchCountMap = null;
if (switchToPortNumber != null) {
switchCountMap = switchToPortNumber.get(netURI);
}
PortAllocationContext context = null;
if (contextMap != null) {
context = contextMap.get(netURI);
}
List<StoragePort> allocatedPorts = allocatePorts(allocator, allocatablePorts.get(netURI), portsAllocatedPerNetwork.get(netURI), net, varrayURI, switchCountMap, context);
if (portGroup.get(netURI) == null) {
portGroup.put(netURI, new ArrayList<List<StoragePort>>());
}
portGroup.get(netURI).add(allocatedPorts);
allocatablePorts.get(netURI).removeAll(allocatedPorts);
for (StoragePort port : allocatedPorts) {
portNames.add(port.getPortName());
}
}
portGroups.add(portGroup);
_log.info(String.format("Port Group %d: %s", i, portNames.toString()));
// Reinitialize the context in the allocator; we want redundancy within PG
if (allocator.getContext() != null) {
allocator.getContext().reinitialize();
}
}
return portGroups;
}
use of com.emc.storageos.volumecontroller.placement.StoragePortsAllocator in project coprhd-controller by CoprHD.
the class VPlexVmaxMaskingOrchestrator method getPortGroups.
@Override
public Set<Map<URI, List<List<StoragePort>>>> getPortGroups(Map<URI, List<StoragePort>> allocatablePorts, Map<URI, NetworkLite> networkMap, URI varrayURI, int nInitiatorGroups, Map<URI, Map<String, Integer>> switchToPortNumber, Map<URI, PortAllocationContext> contextMap, StringBuilder errorMessages) {
Set<Map<URI, List<List<StoragePort>>>> portGroups = new HashSet<Map<URI, List<List<StoragePort>>>>();
StringSet netNames = new StringSet();
// Order the networks from those with fewest ports to those with the most ports.
List<URI> orderedNetworks = orderNetworksByNumberOfPorts(allocatablePorts);
for (URI networkURI : orderedNetworks) {
netNames.add(networkMap.get(networkURI).getLabel());
}
_log.info("Calculating PortGroups for Networks: " + netNames.toString());
Set<String> cpusUsed = new HashSet<String>();
Map<URI, List<StoragePort>> useablePorts = new HashMap<URI, List<StoragePort>>();
Set<String> eliminatedPorts = new HashSet<String>();
Set<String> usedPorts = new HashSet<String>();
// Eliminate ports from the same cpus, which are in the same portGroup.
// This is to avoid the 4096 LUN limit per cpu.
// Cycle through the networks, picking ports that can be used while considering cpus.
// Pick one port from each network, then cycle through them again.
boolean portWasPicked;
do {
portWasPicked = false;
for (URI networkURI : orderedNetworks) {
if (!useablePorts.containsKey(networkURI)) {
useablePorts.put(networkURI, new ArrayList<StoragePort>());
}
// Pick a port if possible
for (StoragePort port : allocatablePorts.get(networkURI)) {
// Do not choose a port that has already been chosen
if (usedPorts.contains(port.getPortName())) {
continue;
}
if (!cpusUsed.contains(port.getPortGroup())) {
// Choose this port, it has a new cpu.
cpusUsed.add(port.getPortGroup());
usedPorts.add(port.getPortName());
useablePorts.get(networkURI).add(port);
portWasPicked = true;
break;
} else {
// This port shares a cpu, don't choose it.
eliminatedPorts.add(port.getPortName());
}
}
}
} while (portWasPicked);
// If all networks have some ports remaining, use the filtered ports.
// If not, emit a warning and do not use the filtered port configuration.
boolean useFilteredPorts = true;
for (URI networkURI : orderedNetworks) {
if (useablePorts.get(networkURI).isEmpty()) {
useFilteredPorts = false;
break;
}
}
if (useFilteredPorts) {
String message = String.format("Ports successfully selected are %s. Ports eliminated because of sharing a cpu with an already-selected port are %s.", usedPorts.toString(), eliminatedPorts.toString());
_log.info(message);
if (errorMessages != null) {
errorMessages.append(message);
}
allocatablePorts = useablePorts;
} else {
_log.info("Some networks have zero remaining ports after cpu filtering, will use duplicate ports on some cpus. " + "This is not a recommended configuration.");
}
// Determine the network with the lowest number of allocatable ports.
int minPorts = Integer.MAX_VALUE;
for (URI networkURI : allocatablePorts.keySet()) {
int numPorts = allocatablePorts.get(networkURI).size();
if (numPorts > MAX_PORTS_PER_NETWORK) {
numPorts = MAX_PORTS_PER_NETWORK;
}
if (numPorts < minPorts) {
minPorts = numPorts;
}
}
// Figure out the number of ports in each network per port group (PG).
// Then figure out the number of port groups to be generated.
// HEURISTIC:
// If the smallest network has 1 port, then allow 1 port per Network unless there's only 1 Network.
// If there is only one network, require two ports per network in the Port Group.
// If it has 2 or more ports per network, use 2 ports per network per MV.
// If there are one or two networks, if it has 9 or more ports, use 3 ports per network per MV.
// If there are one or two networks, if it has 16 or more ports, use 4 ports per network per MV.
// oneNetwork indicates if there is only one Network available.
// portsPerPG is the number of ports to be allocated per PortGroup from the
// network with the fewest ports.
// numPG is the number of Port Groups that will be configured.
boolean oneNetwork = allocatablePorts.keySet().size() == 1;
boolean moreThanTwoNetworks = allocatablePorts.keySet().size() > 2;
int portsPerNetPerPG = oneNetwork ? 2 : 1;
// But if "morePortGroups" is set, will make additional portGroups if there are fewer ports.
if (morePortGroups) {
// This can be set true for testing environments
if (minPorts >= 4) {
// Makes at least two Port Groups if there are two ports
portsPerNetPerPG = 2;
}
} else {
if (minPorts >= 2) {
// Default is to require at least two ports per Port Group
portsPerNetPerPG = 2;
}
}
if (!moreThanTwoNetworks) {
if (minPorts >= 9) {
portsPerNetPerPG = 3;
}
if (minPorts >= 16) {
portsPerNetPerPG = 4;
}
}
int numPG = minPorts / portsPerNetPerPG;
String message = String.format("Min Ports: %d. Number Port Groups: %d. Ports Per Network Per Port Group: %d.", minPorts, numPG, portsPerNetPerPG);
_log.info(message);
if (errorMessages != null) {
errorMessages.append(message);
}
if (numPG == 0) {
return portGroups;
}
// Make a map per Network of number of ports to allocate.
Map<URI, Integer> portsAllocatedPerNetwork = new HashMap<URI, Integer>();
for (URI netURI : allocatablePorts.keySet()) {
Integer nports = allocatablePorts.get(netURI).size() / numPG;
// ports from the network with the fewest ports, i.e. do not exceed 2x portsPerPG.
if (nports > (2 * portsPerNetPerPG)) {
nports = 2 * portsPerNetPerPG;
}
portsAllocatedPerNetwork.put(netURI, nports);
}
// Now call the StoragePortsAllocator for each Network, assigning required number of ports.
StoragePortsAllocator allocator = new StoragePortsAllocator();
for (int i = 0; i < numPG; i++) {
Map<URI, List<List<StoragePort>>> portGroup = new HashMap<URI, List<List<StoragePort>>>();
StringSet portNames = new StringSet();
for (URI netURI : allocatablePorts.keySet()) {
NetworkLite net = networkMap.get(netURI);
Map<String, Integer> switchCountMap = null;
if (switchToPortNumber != null) {
switchCountMap = switchToPortNumber.get(netURI);
}
PortAllocationContext context = null;
if (contextMap != null) {
context = contextMap.get(netURI);
}
List<StoragePort> allocatedPorts = allocatePorts(allocator, allocatablePorts.get(netURI), portsAllocatedPerNetwork.get(netURI), net, varrayURI, switchCountMap, context);
if (portGroup.get(netURI) == null) {
portGroup.put(netURI, new ArrayList<List<StoragePort>>());
}
portGroup.get(netURI).add(allocatedPorts);
allocatablePorts.get(netURI).removeAll(allocatedPorts);
for (StoragePort port : allocatedPorts) {
portNames.add(port.getPortName());
}
}
portGroups.add(portGroup);
_log.info(String.format("Port Group %d: %s", i, portNames.toString()));
// Reinitialize the context in the allocator; we want redundancy within PG
if (allocator.getContext() != null) {
allocator.getContext().reinitialize();
}
}
return portGroups;
}
Aggregations