Search in sources :

Example 36 with ExportPathParams

use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.

the class BlockStorageScheduler method calculateExportPathParamForExportMask.

/**
 * Calculates the path parameters for an existing ExportMask.
 * This has to be calculated per host, since maxPaths is per host.
 *
 * @param dbClient
 * @param mask
 * @return ExportPathParams with calculated values
 */
public static ExportPathParams calculateExportPathParamForExportMask(DbClient dbClient, ExportMask mask) {
    Map<String, Integer> hostInitiatorCounts = new HashMap<String, Integer>();
    // Calculate the path parameters.
    ExportPathParams param = new ExportPathParams(0, 0, 0);
    // If there is a zoningMap, use that.
    if (mask.getZoningMap() != null) {
        for (String initiatorId : mask.getZoningMap().keySet()) {
            Initiator initiator = dbClient.queryObject(Initiator.class, URI.create(initiatorId));
            if (initiator == null || initiator.getInactive()) {
                continue;
            }
            String host = (initiator.getHost() != null) ? initiator.getHost().toString() : "<unknown>";
            if (hostInitiatorCounts.get(host) == null) {
                hostInitiatorCounts.put(host, 0);
            }
            Set<String> portIds = mask.getZoningMap().get(initiatorId);
            if (portIds == null) {
                continue;
            }
            int ppi = 0;
            for (String portId : portIds) {
                Integer newValue = hostInitiatorCounts.get(host) + 1;
                hostInitiatorCounts.put(host, newValue);
                ppi++;
            }
            if (ppi > param.getPathsPerInitiator()) {
                param.setPathsPerInitiator(ppi);
            }
        }
        // Return the maximum of any host.
        for (Integer value : hostInitiatorCounts.values()) {
            if (value > param.getMaxPaths()) {
                param.setMaxPaths(value);
            }
        }
    } else {
        // If there is not a zoning map, we won't change things.
        _log.info(String.format("No zoning map for mask %s (%s), will not change zoning", mask.getMaskName(), mask.getId()));
        param.setMaxPaths(Integer.MAX_VALUE);
    }
    return param;
}
Also used : HashMap(java.util.HashMap) Initiator(com.emc.storageos.db.client.model.Initiator) ContainmentConstraint(com.emc.storageos.db.client.constraint.ContainmentConstraint) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams)

Example 37 with ExportPathParams

use of com.emc.storageos.db.client.model.ExportPathParams 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;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) Initiator(com.emc.storageos.db.client.model.Initiator) List(java.util.List) ArrayList(java.util.ArrayList) URIQueryResultList(com.emc.storageos.db.client.constraint.URIQueryResultList) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) NetworkLite(com.emc.storageos.util.NetworkLite) StoragePort(com.emc.storageos.db.client.model.StoragePort) DatabaseException(com.emc.storageos.db.exceptions.DatabaseException) DeviceControllerException(com.emc.storageos.exceptions.DeviceControllerException) Map(java.util.Map) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) StringSetMap(com.emc.storageos.db.client.model.StringSetMap) TreeMap(java.util.TreeMap) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams)

Example 38 with ExportPathParams

use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.

the class StoragePortsAssignerTest method testAllocationAssignmentWithSwitchAffinity.

public static Map<Initiator, List<StoragePort>> testAllocationAssignmentWithSwitchAffinity(PortAllocationContext[] contexts, Map<URI, Map<URI, List<Initiator>>> hostToNetToInitiators, int maxPaths, int minPaths, int pathsPerInitiator, int initiatorsPerPort, String arrayType, Map<Initiator, List<StoragePort>> existingAssignments) throws Exception {
    Map<URI, List<Initiator>> net2InitiatorsMap = makeNet2InitiatorsMap(hostToNetToInitiators);
    Map<Initiator, List<StoragePort>> assignments = new HashMap<Initiator, List<StoragePort>>();
    if (pathsPerInitiator > maxPaths) {
        return assignments;
    }
    ExportPathParams pathParams = new ExportPathParams(maxPaths, minPaths, pathsPerInitiator);
    pathParams.setMaxInitiatorsPerPort(initiatorsPerPort);
    try {
        for (int i = 0; i < contexts.length; i++) {
            contexts[i].reinitialize();
        }
        Map<URI, PortAllocationContext> net2ContextMap = new HashMap<URI, PortAllocationContext>();
        for (int i = 0; i < contexts.length; i++) {
            PortAllocationContext context = contexts[i];
            net2ContextMap.put(context._initiatorNetwork.getId(), context);
        }
        // Map the existing (already allocated) StoragePorts to their Networks.
        Map<URI, Set<StoragePort>> existingPortsMap = generateNetworkToStoragePortsMap(existingAssignments);
        // Make a Map of Network to existing Initiators
        Map<URI, Set<Initiator>> existingInitiatorsMap = generateNetworkToInitiatorsMap(existingAssignments);
        // Compute the number of Ports needed for each Network
        StoragePortsAssigner assigner = StoragePortsAssignerFactory.getAssigner(arrayType);
        List<URI> networkOrder = new ArrayList<URI>();
        Map<URI, Integer> net2PortsNeeded = assigner.getPortsNeededPerNetwork(net2InitiatorsMap, pathParams, existingPortsMap, existingInitiatorsMap, true, networkOrder);
        // For each Network, allocate the ports required, and then assign the ports.
        StoragePortsAllocator allocator = new StoragePortsAllocator();
        Map<URI, List<StoragePort>> netToPortsAllocated = new HashMap<URI, List<StoragePort>>();
        PortAllocationContext previousContext = null;
        for (URI netURI : networkOrder) {
            Integer portsNeeded = net2PortsNeeded.get(netURI);
            if (portsNeeded == 0) {
                System.out.println("No ports to be assigned for net: " + netURI);
                continue;
            }
            // Get the context for this network.
            PortAllocationContext context = net2ContextMap.get(netURI);
            // Copy context from the previous allocation.
            if (previousContext != null) {
                context.copyPreviousNetworkContext(previousContext);
            }
            previousContext = context;
            Map<String, Integer> switchMap = new HashMap<String, Integer>();
            List<Initiator> inits = net2InitiatorsMap.get(netURI);
            int number = inits.size() * pathsPerInitiator / 2;
            System.out.println("Number ports in the switch: " + number);
            switchMap.put("mds-a", number);
            switchMap.put("mds-b", number);
            List<StoragePort> portsAllocated = allocator.allocatePortsForNetwork(portsNeeded, context, false, existingPortsMap.get(netURI), true, switchMap);
            netToPortsAllocated.put(netURI, portsAllocated);
        }
        // Now for each host, do the port assignment.
        Map<URI, Map<String, List<StoragePort>>> switchStoragePortsByNet = getSwitchPortsByNetMap(netToPortsAllocated, net2ContextMap);
        for (Map.Entry<URI, Map<URI, List<Initiator>>> entry : hostToNetToInitiators.entrySet()) {
            Map<URI, Map<String, List<Initiator>>> switchInitiatorsByNet = getSwitchInitiatorByNetMap(entry.getValue());
            System.out.println("Assign ports for host " + entry.getKey());
            assigner.assignPortsToHost(assignments, entry.getValue(), netToPortsAllocated, pathParams, existingAssignments, entry.getKey(), null, switchInitiatorsByNet, switchStoragePortsByNet);
        }
        List<String> assignmentStrings = new ArrayList<String>();
        for (Initiator initiator : assignments.keySet()) {
            StringBuilder buf = new StringBuilder();
            buf.append(String.format("%s - %s/%s -> ", initiator.getHostName(), initiator.getInitiatorPort(), getInitiatorSwitch(initiator)));
            List<StoragePort> ports = assignments.get(initiator);
            if (ports == null) {
                buf.append("<ignored>");
            } else {
                for (StoragePort port : assignments.get(initiator)) {
                    buf.append(port.getPortName() + "/" + getPortSwitch(port, switchStoragePortsByNet) + " ");
                }
            }
            buf.append(" ");
            assignmentStrings.add(buf.toString());
        }
        Collections.sort(assignmentStrings);
        for (String line : assignmentStrings) {
            System.out.println(line);
        }
        verifyAssignments(assignments, arrayType, maxPaths, pathsPerInitiator, initiatorsPerPort, net2InitiatorsMap, existingAssignments);
    } catch (PlacementException ex) {
        System.out.println("PlacementException: " + ex.getMessage());
    } catch (Exception ex) {
        System.out.println("ERROR: " + ex.getMessage());
        throw ex;
    }
    return assignments;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) URI(java.net.URI) Initiator(com.emc.storageos.db.client.model.Initiator) ArrayList(java.util.ArrayList) List(java.util.List) StoragePort(com.emc.storageos.db.client.model.StoragePort) HashMap(java.util.HashMap) Map(java.util.Map) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams) PortAllocationContext(com.emc.storageos.volumecontroller.placement.StoragePortsAllocator.PortAllocationContext)

Example 39 with ExportPathParams

use of com.emc.storageos.db.client.model.ExportPathParams in project coprhd-controller by CoprHD.

the class HostMapper method map.

public static ExportGroupRestRep map(ExportGroup from, List<Initiator> initiators, Map<String, Integer> volumes, List<Host> hosts, List<Cluster> clusters, List<ExportPathParams> exportPathParams) {
    if (from == null) {
        return null;
    }
    ExportGroupRestRep to = new ExportGroupRestRep();
    mapDataObjectFields(from, to);
    if (initiators != null) {
        for (Initiator initiator : initiators) {
            to.getInitiators().add(map(initiator));
        }
    }
    if (volumes != null) {
        for (Map.Entry<String, Integer> entry : volumes.entrySet()) {
            ExportBlockParam volume = new ExportBlockParam();
            volume.setId(URI.create(entry.getKey()));
            Integer lun = entry.getValue();
            if (lun != null && lun != ExportGroup.LUN_UNASSIGNED) {
                volume.setLun(lun);
            }
            to.getVolumes().add(volume);
        }
    }
    if (hosts != null) {
        for (Host host : hosts) {
            to.getHosts().add(map(host));
        }
    }
    if (clusters != null) {
        for (Cluster cluster : clusters) {
            to.getClusters().add(map(cluster));
        }
    }
    if (exportPathParams != null && !exportPathParams.isEmpty()) {
        for (ExportPathParams pathParam : exportPathParams) {
            ExportPathParametersRep pathParamRep = map(pathParam);
            for (Map.Entry<String, String> entry : from.getPathParameters().entrySet()) {
                if (entry.getValue().equals(pathParam.getId().toString())) {
                    pathParamRep.getBlockObjects().add(entry.getKey());
                }
            }
            to.getPathParams().add(pathParamRep);
        }
    }
    if (from.getProject() != null) {
        to.setProject(toRelatedResource(ResourceTypeEnum.PROJECT, from.getProject().getURI()));
    }
    if (from.getTenant() != null) {
        to.setTenant(toRelatedResource(ResourceTypeEnum.TENANT, from.getTenant().getURI()));
    }
    to.setVirtualArray(toRelatedResource(ResourceTypeEnum.VARRAY, from.getVirtualArray()));
    if (from.getType() != null) {
        to.setType(from.getType());
    }
    to.setGeneratedName(from.getGeneratedName());
    if (from.getAltVirtualArrays() != null && !from.getAltVirtualArrays().isEmpty()) {
        // The alternate virtual array is a map from Storage System URI to Virtual Array URI
        List<StringHashMapEntry> toVirtualArrays = new ArrayList<StringHashMapEntry>();
        for (Map.Entry<String, String> entry : from.getAltVirtualArrays().entrySet()) {
            StringHashMapEntry toEntry = new StringHashMapEntry();
            toEntry.setName(entry.getKey());
            toEntry.setValue(entry.getValue());
            toVirtualArrays.add(toEntry);
        }
        to.setAltVirtualArrays(toVirtualArrays);
    }
    return to;
}
Also used : ArrayList(java.util.ArrayList) Cluster(com.emc.storageos.db.client.model.Cluster) Host(com.emc.storageos.db.client.model.Host) StringHashMapEntry(com.emc.storageos.model.StringHashMapEntry) ExportBlockParam(com.emc.storageos.model.block.export.ExportBlockParam) ExportGroupRestRep(com.emc.storageos.model.block.export.ExportGroupRestRep) Initiator(com.emc.storageos.db.client.model.Initiator) ExportPathParametersRep(com.emc.storageos.model.block.export.ExportPathParametersRep) Map(java.util.Map) StringMap(com.emc.storageos.db.client.model.StringMap) ExportPathParams(com.emc.storageos.db.client.model.ExportPathParams)

Aggregations

ExportPathParams (com.emc.storageos.db.client.model.ExportPathParams)39 URI (java.net.URI)33 ArrayList (java.util.ArrayList)26 List (java.util.List)21 URIQueryResultList (com.emc.storageos.db.client.constraint.URIQueryResultList)17 Initiator (com.emc.storageos.db.client.model.Initiator)17 HashMap (java.util.HashMap)17 ExportMask (com.emc.storageos.db.client.model.ExportMask)13 HashSet (java.util.HashSet)13 ExportGroup (com.emc.storageos.db.client.model.ExportGroup)12 NamedURI (com.emc.storageos.db.client.model.NamedURI)12 Map (java.util.Map)11 StringMap (com.emc.storageos.db.client.model.StringMap)8 StoragePortGroup (com.emc.storageos.db.client.model.StoragePortGroup)6 StringSet (com.emc.storageos.db.client.model.StringSet)6 DeviceControllerException (com.emc.storageos.exceptions.DeviceControllerException)6 ApplicationAddVolumeList (com.emc.storageos.volumecontroller.ApplicationAddVolumeList)6 Workflow (com.emc.storageos.workflow.Workflow)6 BlockObject (com.emc.storageos.db.client.model.BlockObject)5 StoragePort (com.emc.storageos.db.client.model.StoragePort)5