X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=pce%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Ftransportpce%2Fpce%2Fnetworkanalyzer%2FPceCalculation.java;h=81cc58b52f5bb57ca14544be5798304e1dd43e61;hb=67763b4d82e44c68fdbc765cdeec5496ff65b01e;hp=113135541659e803c9345e7c1fe5a3c00a66dc9a;hpb=66ccddbe00692f230350a19e1a222f09d6abd9a7;p=transportpce.git diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java index 113135541..81cc58b52 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/PceCalculation.java @@ -8,26 +8,33 @@ package org.opendaylight.transportpce.pce.networkanalyzer; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; - import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; import org.opendaylight.transportpce.common.ResponseCodes; +import org.opendaylight.transportpce.common.StringConstants; +import org.opendaylight.transportpce.common.fixedflex.GridConstant; +import org.opendaylight.transportpce.common.mapping.MappingUtils; +import org.opendaylight.transportpce.common.mapping.MappingUtilsImpl; +import org.opendaylight.transportpce.common.mapping.PortMapping; import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.pce.constraints.PceConstraints; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.PathComputationRequestInput; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Node1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType; -import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmNodeType; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.PathComputationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.mc.capabilities.McCapabilities; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmLinkType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmNodeType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId; @@ -50,13 +57,17 @@ public class PceCalculation { private PathComputationRequestInput input; private String anodeId = ""; private String znodeId = ""; + private String serviceFormatA = ""; + private String serviceFormatZ = ""; + private String serviceType = ""; + private Long serviceRate = 0L; private PceConstraints pceHardConstraints; ///////////// Intermediate data///////////////// - private List addLinks = new ArrayList(); - private List dropLinks = new ArrayList(); - private HashSet azSrgs = new HashSet(); + private List addLinks = new ArrayList<>(); + private List dropLinks = new ArrayList<>(); + private HashSet azSrgs = new HashSet<>(); private PceNode aendPceNode = null; private PceNode zendPceNode = null; @@ -65,36 +76,41 @@ public class PceCalculation { private List allNodes = null; // this List serves graph calculation - private Map allPceNodes = new HashMap(); + private Map allPceNodes = new HashMap<>(); // this List serves calculation of ZtoA path description // TODO maybe better solution is possible - private Map allPceLinks = new HashMap(); - private Set linksToExclude = new HashSet(); + private Map allPceLinks = new HashMap<>(); + private Set linksToExclude = new HashSet<>(); private PceResult returnStructure; + private PortMapping portMapping; private enum ConstraintTypes { NONE, HARD_EXCLUDE, HARD_INCLUDE, HARD_DIVERSITY, SOFT_EXCLUDE, SOFT_INCLUDE, SOFT_DIVERSITY; } + private MappingUtils mappingUtils; + public PceCalculation(PathComputationRequestInput input, NetworkTransactionService networkTransactionService, - PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc) { + PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc, + PortMapping portMapping) { this.input = input; this.networkTransactionService = networkTransactionService; this.returnStructure = rc; this.pceHardConstraints = pceHardConstraints; + this.mappingUtils = new MappingUtilsImpl(networkTransactionService.getDataBroker()); + this.portMapping = portMapping; parseInput(); } - public void calcPath() { + public void retrievePceNetwork() { - LOG.info("In PceCalculation calcPath: "); + LOG.info("In PceCalculation retrieveNetwork: "); if (!readMdSal()) { returnStructure.setRC(ResponseCodes.RESPONSE_FAILED); return; } - MapUtils.mapDiversityConstraints(allNodes, allLinks, pceHardConstraints); if (!analyzeNw()) { @@ -108,31 +124,100 @@ public class PceCalculation { } private boolean parseInput() { - anodeId = input.getServiceAEnd().getNodeId(); - znodeId = input.getServiceZEnd().getNodeId(); + if (input.getServiceAEnd().getServiceFormat() == null || input.getServiceZEnd().getServiceFormat() == null + || input.getServiceAEnd().getServiceRate() == null) { + LOG.error("Service Format and Service Rate are required for a path calculation"); + return false; + } + serviceFormatA = input.getServiceAEnd().getServiceFormat().getName(); + serviceFormatZ = input.getServiceZEnd().getServiceFormat().getName(); + serviceRate = input.getServiceAEnd().getServiceRate().toJava(); + LOG.info("parseInput: A and Z :[{}] and [{}]", anodeId, znodeId); - returnStructure.setRate(input.getServiceAEnd().getServiceRate()); + if (!(serviceFormatA.equals(serviceFormatZ))) { + LOG.info("parseInput: different service format for A and Z not handled, will use service format from Aend"); + } else if (serviceRate == 100L) { + switch (serviceFormatA) { + case "Ethernet": + case "OC": + serviceType = StringConstants.SERVICE_TYPE_100GE; + break; + case "OTU": + serviceType = StringConstants.SERVICE_TYPE_OTU4; + break; + case "ODU": + serviceType = StringConstants.SERVICE_TYPE_ODU4; + break; + default: + LOG.debug("parseInput: unsupported service type: Format {} Rate 100L", serviceFormatA); + break; + } + //switch(serviceRate) may seem a better option at first glance. + //But switching on Long or long is not directly possible in Java. + //And casting to int bumps the limit here. + //Passing by ENUM or String are possible alternatives. + //Maybe HashMap and similar options should also be considered here. + } else if ("Ethernet".equals(serviceFormatA)) { + //only rate 100L is currently supported except in Ethernet + if (serviceRate == 400L) { + serviceType = StringConstants.SERVICE_TYPE_400GE; + } else if (serviceRate == 10L) { + serviceType = StringConstants.SERVICE_TYPE_10GE; + } else if (serviceRate == 1L) { + serviceType = StringConstants.SERVICE_TYPE_1GE; + } else { + LOG.debug("parseInput: unsupported service type: Format Ethernet Rate {}", serviceRate); + } + } else { + LOG.debug("parseInput: unsupported service type: Format {} Rate {}", + serviceFormatA, serviceRate); + } + if (StringConstants.SERVICE_TYPE_ODU4.equals(serviceType) + || StringConstants.SERVICE_TYPE_10GE.equals(serviceType) + || StringConstants.SERVICE_TYPE_1GE.equals(serviceType)) { + anodeId = input.getServiceAEnd().getTxDirection().getPort().getPortDeviceName(); + znodeId = input.getServiceZEnd().getTxDirection().getPort().getPortDeviceName(); + } else { + anodeId = input.getServiceAEnd().getNodeId(); + znodeId = input.getServiceZEnd().getNodeId(); + } + + returnStructure.setRate(input.getServiceAEnd().getServiceRate().toJava()); + returnStructure.setServiceFormat(input.getServiceAEnd().getServiceFormat()); return true; } private boolean readMdSal() { - LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID); - InstanceIdentifier nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class) - .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build(); + InstanceIdentifier nwInstanceIdentifier = null; Network nw = null; + if (("OC".equals(serviceFormatA)) || ("OTU".equals(serviceFormatA)) + || ("Ethernet".equals(serviceFormatA) && ((serviceRate == 100L) || (serviceRate == 400L)))) { + LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID); + nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build(); + } else if ("ODU".equals(serviceFormatA) + || ("Ethernet".equals(serviceFormatA) && ((serviceRate == 10L) || (serviceRate == 1L)))) { + LOG.info("readMdSal: network {}", NetworkUtils.OTN_NETWORK_ID); + nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class) + .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID))).build(); + } else { + LOG.info("readMdSal: service-rate {} / service-format not handled {}", serviceRate, serviceFormatA); + return false; + } + try { Optional nwOptional = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier).get(); if (nwOptional.isPresent()) { nw = nwOptional.get(); - LOG.debug("readMdSal: network nodes: nwOptional.isPresent = true {}", nw.toString()); + LOG.debug("readMdSal: network nodes: nwOptional.isPresent = true {}", nw); } } catch (InterruptedException | ExecutionException e) { LOG.error("readMdSal: Error reading topology {}", nwInstanceIdentifier); networkTransactionService.close(); returnStructure.setRC(ResponseCodes.RESPONSE_FAILED); throw new RuntimeException( - "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e); + "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e); } networkTransactionService.close(); @@ -140,25 +225,29 @@ public class PceCalculation { LOG.error("readMdSal: network is null: {}", nwInstanceIdentifier); return false; } - allNodes = nw.getNode().stream().sorted((n1, n2) -> n1.getNodeId().getValue().compareTo(n2.getNodeId() - .getValue())).collect(Collectors.toList()); + allNodes = nw.nonnullNode().values().stream().sorted((n1, n2) + -> n1.getNodeId().getValue().compareTo(n2.getNodeId().getValue())).collect(Collectors.toList()); Network1 nw1 = nw.augmentation(Network1.class); - - allLinks = nw1.getLink().stream().sorted((l1, l2) -> l1.getSource().getSourceTp().toString().compareTo(l2 - .getSource().getSourceTp().toString())).collect(Collectors.toList()); + if (nw1 != null) { + allLinks = nw1.nonnullLink().values().stream().sorted((l1, l2) + -> l1.getSource().getSourceTp().toString().compareTo(l2.getSource().getSourceTp().toString())) + .collect(Collectors.toList()); + } else { + LOG.warn("no otn links in otn-topology"); + } if (allNodes == null || allNodes.isEmpty()) { LOG.error("readMdSal: no nodes "); return false; } LOG.info("readMdSal: network nodes: {} nodes added", allNodes.size()); - LOG.debug("readMdSal: network nodes: {} nodes added", allNodes.toString()); + LOG.debug("readMdSal: network nodes: {} nodes added", allNodes); if (allLinks == null || allLinks.isEmpty()) { LOG.error("readMdSal: no links "); return false; } LOG.info("readMdSal: network links: {} links added", allLinks.size()); - LOG.debug("readMdSal: network links: {} links added", allLinks.toString()); + LOG.debug("readMdSal: network links: {} links added", allLinks); return true; } @@ -167,34 +256,54 @@ public class PceCalculation { LOG.debug("analyzeNw: allNodes size {}, allLinks size {}", allNodes.size(), allLinks.size()); - for (Node node : allNodes) { - validateNode(node); - } - LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size()); + if (StringConstants.SERVICE_TYPE_100GE.equals(serviceType) + || StringConstants.SERVICE_TYPE_OTU4.equals(serviceType) + || StringConstants.SERVICE_TYPE_400GE.equals(serviceType)) { + // 100GE service and OTU4 service are handled at the openroadm-topology layer + for (Node node : allNodes) { + validateNode(node); + } - if (aendPceNode == null || zendPceNode == null) { - LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network"); - return false; - } + LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size()); - for (Link link : allLinks) { - validateLink(link); - } + if (aendPceNode == null || zendPceNode == null) { + LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network"); + return false; + } + for (Link link : allLinks) { + validateLink(link); + } + // debug prints + LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size()); + // debug prints + LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size()); + for (NodeId srg : azSrgs) { + LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue()); + } + // debug prints + for (PceLink link : addLinks) { + filteraddLinks(link); + } + for (PceLink link : dropLinks) { + filterdropLinks(link); + } - LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size()); + } else { + // ODU4, 10GE/ODU2e or 1GE/ODU0 services are handled at openroadm-otn layer - // debug prints - LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size()); - for (NodeId srg : azSrgs) { - LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue()); - } - // debug prints + for (Node node : allNodes) { + validateOtnNode(node); + } - for (PceLink link : addLinks) { - filteraddLinks(link); - } - for (PceLink link : dropLinks) { - filterdropLinks(link); + LOG.info("analyzeNw: allPceNodes {}", allPceNodes); + + if (aendPceNode == null || zendPceNode == null) { + LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network"); + return false; + } + for (Link link : allLinks) { + validateLink(link); + } } LOG.info("analyzeNw: allPceNodes size {}, allPceLinks size {}", allPceNodes.size(), allPceLinks.size()); @@ -203,8 +312,8 @@ public class PceCalculation { return false; } - LOG.debug("analyzeNw: allPceNodes {}", allPceNodes.toString()); - LOG.debug("analyzeNw: allPceLinks {}", allPceLinks.toString()); + LOG.debug("analyzeNw: allPceNodes {}", allPceNodes); + LOG.debug("analyzeNw: allPceLinks {}", allPceLinks); return true; } @@ -216,7 +325,7 @@ public class PceCalculation { if (azSrgs.contains(nodeId)) { allPceLinks.put(pcelink.getLinkId(), pcelink); allPceNodes.get(nodeId).addOutgoingLink(pcelink); - LOG.debug("analyzeNw: Add_LINK added to source and to allPceLinks {}", pcelink.getLinkId().toString()); + LOG.debug("analyzeNw: Add_LINK added to source and to allPceLinks {}", pcelink.getLinkId()); return true; } @@ -234,7 +343,7 @@ public class PceCalculation { if (azSrgs.contains(nodeId)) { allPceLinks.put(pcelink.getLinkId(), pcelink); allPceNodes.get(nodeId).addOutgoingLink(pcelink); - LOG.debug("analyzeNw: Drop_LINK added to dest and to allPceLinks {}", pcelink.getLinkId().toString()); + LOG.debug("analyzeNw: Drop_LINK added to dest and to allPceLinks {}", pcelink.getLinkId()); return true; } @@ -246,168 +355,259 @@ public class PceCalculation { } private boolean validateLink(Link link) { - - LOG.debug("validateLink: link {} ", link.toString()); - - if (linksToExclude.contains(link.getLinkId())) { - LOG.info("validateLink: Link is ignored due opposite link problem - {}", link.getLinkId().getValue()); - return false; - } + LOG.info("validateLink: link {} ", link); NodeId sourceId = link.getSource().getSourceNode(); NodeId destId = link.getDestination().getDestNode(); PceNode source = allPceNodes.get(sourceId); PceNode dest = allPceNodes.get(destId); + State state = link.augmentation(Link1.class).getOperationalState(); if (source == null) { LOG.debug("validateLink: Link is ignored due source node is rejected by node validation - {}", - link.getSource().getSourceNode().getValue()); + link.getSource().getSourceNode().getValue()); return false; } if (dest == null) { LOG.debug("validateLink: Link is ignored due dest node is rejected by node validation - {}", - link.getDestination().getDestNode().getValue()); + link.getDestination().getDestNode().getValue()); return false; } - PceLink pcelink = new PceLink(link, source, dest); - if (!pcelink.isValid()) { - dropOppositeLink(link); - LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link"); + if (State.OutOfService.equals(state)) { + LOG.debug("validateLink: Link is ignored due operational state - {}", + state.getName()); return false; } - LinkId linkId = pcelink.getLinkId(); + if (StringConstants.SERVICE_TYPE_100GE.equals(serviceType) + || StringConstants.SERVICE_TYPE_OTU4.equals(serviceType) + || StringConstants.SERVICE_TYPE_400GE.equals(serviceType)) { + // 100GE or 400GE or OTU4 services are handled at WDM Layer + PceLink pcelink = new PceLink(link, source, dest); + if (!pcelink.isValid()) { + dropOppositeLink(link); + LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link"); + return false; + } + LinkId linkId = pcelink.getLinkId(); + if (validateLinkConstraints(pcelink).equals(ConstraintTypes.HARD_EXCLUDE)) { + dropOppositeLink(link); + LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue()); + return false; + } + switch (pcelink.getlinkType()) { + case ROADMTOROADM: + case EXPRESSLINK: + allPceLinks.put(linkId, pcelink); + source.addOutgoingLink(pcelink); + LOG.debug("validateLink: {}-LINK added to allPceLinks {}", + pcelink.getlinkType(), pcelink); + break; + case ADDLINK: + pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString())); + addLinks.add(pcelink); + LOG.debug("validateLink: ADD-LINK saved {}", pcelink); + break; + case DROPLINK: + pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString())); + dropLinks.add(pcelink); + LOG.debug("validateLink: DROP-LINK saved {}", pcelink); + break; + case XPONDERINPUT: + // store separately all SRG links directly + azSrgs.add(sourceId); + // connected to A/Z + if (!dest.checkTP(pcelink.getDestTP().toString())) { + LOG.debug( + "validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink); + return false; + } + if (dest.getXpdrClient(pcelink.getDestTP().toString()) != null) { + pcelink.setClient(dest.getXpdrClient(pcelink.getDestTP().toString())); + } + allPceLinks.put(linkId, pcelink); + source.addOutgoingLink(pcelink); + LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink); + break; + // does it mean XPONDER==>>SRG ? + case XPONDEROUTPUT: + // store separately all SRG links directly + azSrgs.add(destId); + // connected to A/Z + if (!source.checkTP(pcelink.getSourceTP().toString())) { + LOG.debug( + "validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink); + return false; + } + if (source.getXpdrClient(pcelink.getSourceTP().toString()) != null) { + pcelink.setClient(source.getXpdrClient(pcelink.getSourceTP().toString())); + } + allPceLinks.put(linkId, pcelink); + source.addOutgoingLink(pcelink); + LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink); + break; + default: + LOG.warn("validateLink: link type is not supported {}", pcelink); + } + return true; + + } else if ((StringConstants.SERVICE_TYPE_ODU4.equals(serviceType)) + || (StringConstants.SERVICE_TYPE_10GE.equals(serviceType)) + || (StringConstants.SERVICE_TYPE_1GE.equals(serviceType))) { + // ODU4, 1GE and 10GE services relying on ODU2, ODU2e or ODU0 services are handled at OTN layer + PceLink pceOtnLink = new PceLink(link, source, dest); - switch (validateLinkConstraints(pcelink)) { - case HARD_EXCLUDE : + if (!pceOtnLink.isOtnValid(link, serviceType)) { + dropOppositeLink(link); + LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link"); + return false; + } + + LinkId linkId = pceOtnLink.getLinkId(); + if (validateLinkConstraints(pceOtnLink).equals(ConstraintTypes.HARD_EXCLUDE)) { dropOppositeLink(link); LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue()); return false; - default: - break; - } + } - switch (pcelink.getlinkType()) { - case ROADMTOROADM : - allPceLinks.put(linkId, pcelink); - source.addOutgoingLink(pcelink); - LOG.debug("validateLink: ROADMTOROADM-LINK added to allPceLinks {}", pcelink.toString()); - break; - case EXPRESSLINK : - allPceLinks.put(linkId, pcelink); - source.addOutgoingLink(pcelink); - LOG.debug("validateLink: EXPRESS-LINK added to allPceLinks {}", pcelink.toString()); - break; - case ADDLINK : - pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString(), true)); - addLinks.add(pcelink); - LOG.debug("validateLink: ADD-LINK saved {}", pcelink.toString()); - break; - case DROPLINK : - pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString(), false)); - dropLinks.add(pcelink); - LOG.debug("validateLink: DROP-LINK saved {}", pcelink.toString()); - break; - case XPONDERINPUT : - // store separately all SRG links directly - azSrgs.add(sourceId); - // connected to A/Z - if (!dest.checkTP(pcelink.getDestTP().toString())) { - LOG.debug("validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink.toString()); - return false; - } - pcelink.setClient(dest.getClient(pcelink.getDestTP().toString())); - allPceLinks.put(linkId, pcelink); - source.addOutgoingLink(pcelink); - LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink.toString()); - break; - // does it mean XPONDER==>>SRG ? - case XPONDEROUTPUT : - // store separately all SRG links directly - azSrgs.add(destId); - // connected to A/Z - if (!source.checkTP(pcelink.getSourceTP().toString())) { - LOG.debug("validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink.toString()); - return false; - } - pcelink.setClient(source.getClient(pcelink.getSourceTP().toString())); - allPceLinks.put(linkId, pcelink); - source.addOutgoingLink(pcelink); - LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink.toString()); - break; - default: - LOG.warn("validateLink: link type is not supported {}", pcelink.toString()); + switch (pceOtnLink.getlinkType()) { + case OTNLINK: + if (dest.getXpdrClient(pceOtnLink.getDestTP().toString()) != null) { + pceOtnLink.setClient(dest.getXpdrClient(pceOtnLink.getDestTP().toString())); + } + + allPceLinks.put(linkId, pceOtnLink); + source.addOutgoingLink(pceOtnLink); + LOG.info("validateLink: OTN-LINK added to allPceLinks {}", pceOtnLink); + break; + default: + LOG.warn("validateLink: link type is not supported {}", pceOtnLink); + } + return true; + } else { + LOG.error(" validateLink: Unmanaged service type {}", serviceType); + return false; } - return true; } - private boolean validateNode(Node node) { - LOG.debug("validateNode: node {} ", node.toString()); - + private void validateNode(Node node) { + LOG.debug("validateNode: node {} ", node); // PceNode will be used in Graph algorithm Node1 node1 = node.augmentation(Node1.class); if (node1 == null) { LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId()); + return; + } + if (State.OutOfService.equals(node1.getOperationalState())) { + LOG.error("getNodeType: node is ignored due to operational state - {}", node1.getOperationalState() + .getName()); + return; } OpenroadmNodeType nodeType = node1.getNodeType(); + String deviceNodeId = MapUtils.getSupNetworkNode(node); + // Should never happen but because of existing topology test files + // we have to manage this case + if (deviceNodeId == null || deviceNodeId.isBlank()) { + deviceNodeId = node.getNodeId().getValue(); + } - PceNode pceNode = new PceNode(node,nodeType,node.getNodeId()); - pceNode.validateAZxponder(anodeId, znodeId); - pceNode.initWLlist(); + LOG.info("Device node id {} for {}", deviceNodeId, node); + PceOpticalNode pceNode = new PceOpticalNode(deviceNodeId, this.serviceType, portMapping, node, nodeType, + mappingUtils.getOpenRoadmVersion(deviceNodeId), getSlotWidthGranularity(deviceNodeId, node.getNodeId())); + pceNode.validateAZxponder(anodeId, znodeId, input.getServiceAEnd().getServiceFormat()); + pceNode.initFrequenciesBitSet(); if (!pceNode.isValid()) { LOG.warn(" validateNode: Node is ignored"); - return false; + return; + } + if (validateNodeConstraints(pceNode).equals(ConstraintTypes.HARD_EXCLUDE)) { + return; + } + if (endPceNode(nodeType, pceNode.getNodeId(), pceNode) && this.aendPceNode == null + && isAZendPceNode(this.serviceFormatA, pceNode, anodeId, "A")) { + this.aendPceNode = pceNode; + } + if (endPceNode(nodeType, pceNode.getNodeId(), pceNode) && this.zendPceNode == null + && isAZendPceNode(this.serviceFormatZ, pceNode, znodeId, "Z")) { + this.zendPceNode = pceNode; } - switch (validateNodeConstraints(pceNode)) { - case HARD_EXCLUDE : - return false; + allPceNodes.put(pceNode.getNodeId(), pceNode); + LOG.debug("validateNode: node is saved {}", pceNode.getNodeId().getValue()); + return; + } - default : - break; + private boolean isAZendPceNode(String serviceFormat, PceOpticalNode pceNode, String azNodeId, String azEndPoint) { + switch (serviceFormat) { + case "Ethernet": + case "OC": + if (pceNode.getSupNetworkNodeId().equals(azNodeId)) { + return true; + } + return false; + case "OTU": + if ("A".equals(azEndPoint) && pceNode.getNodeId().getValue() + .equals(this.input.getServiceAEnd().getRxDirection().getPort().getPortDeviceName())) { + return true; + } + if ("Z".equals(azEndPoint) && pceNode.getNodeId().getValue() + .equals(this.input.getServiceZEnd().getRxDirection().getPort().getPortDeviceName())) { + return true; + } + return false; + default: + LOG.debug("Unsupported service Format {} for node {}", serviceFormat, pceNode.getNodeId().getValue()); + return false; } + } + + private void validateOtnNode(Node node) { + LOG.info("validateOtnNode: {} ", node.getNodeId().getValue()); + // PceOtnNode will be used in Graph algorithm + if (node.augmentation(Node1.class) != null) { + OpenroadmNodeType nodeType = node.augmentation(Node1.class).getNodeType(); - if (pceNode.getSupNodeIdPceNode().equals(this.anodeId)) { - if (this.aendPceNode != null) { - LOG.debug("aendPceNode already gets: {}", this.aendPceNode); - } else if (endPceNode(nodeType,pceNode.getNodeId(), pceNode)) { - this.aendPceNode = pceNode; + PceOtnNode pceOtnNode = new PceOtnNode(node, nodeType, node.getNodeId(), "otn", serviceType); + pceOtnNode.validateXponder(anodeId, znodeId); + + if (!pceOtnNode.isValid()) { + LOG.warn(" validateOtnNode: Node {} is ignored", node.getNodeId().getValue()); + return; } - // returning false otherwise would break E2E test - } - if (pceNode.getSupNodeIdPceNode().equals(this.znodeId)) { - if (this.zendPceNode != null) { - LOG.debug("zendPceNode already gets: {}", this.zendPceNode); - } else if (endPceNode(nodeType,pceNode.getNodeId(), pceNode)) { - this.zendPceNode = pceNode; + if (validateNodeConstraints(pceOtnNode).equals(ConstraintTypes.HARD_EXCLUDE)) { + return; } - // returning false otherwise would break E2E test + if (pceOtnNode.getNodeId().getValue().equals(anodeId) && this.aendPceNode == null) { + this.aendPceNode = pceOtnNode; + } + if (pceOtnNode.getNodeId().getValue().equals(znodeId) && this.zendPceNode == null) { + this.zendPceNode = pceOtnNode; + } + allPceNodes.put(pceOtnNode.getNodeId(), pceOtnNode); + LOG.info("validateOtnNode: node {} is saved", node.getNodeId().getValue()); + return; + } else { + LOG.error("ValidateOtnNode: no node-type augmentation. Node {} is ignored", node.getNodeId().getValue()); + return; } - - allPceNodes.put(pceNode.getNodeId(), pceNode); - LOG.debug("validateNode: node is saved {}", pceNode.getNodeId().getValue()); - return true; } private ConstraintTypes validateNodeConstraints(PceNode pcenode) { - if (pceHardConstraints.getExcludeSupNodes().isEmpty() && pceHardConstraints.getExcludeCLLI().isEmpty()) { return ConstraintTypes.NONE; } - - if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNodeIdPceNode())) { + if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNetworkNodeId())) { LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue()); return ConstraintTypes.HARD_EXCLUDE; } - if (pceHardConstraints.getExcludeCLLI().contains(pcenode.getCLLI())) { + if (pceHardConstraints.getExcludeCLLI().contains(pcenode.getSupClliNodeId())) { LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue()); return ConstraintTypes.HARD_EXCLUDE; } - return ConstraintTypes.NONE; } @@ -421,7 +621,7 @@ public class PceCalculation { return ConstraintTypes.NONE; } - List constraints = new ArrayList(pceHardConstraints.getExcludeSRLG()); + List constraints = new ArrayList<>(pceHardConstraints.getExcludeSRLG()); constraints.retainAll(link.getsrlgList()); if (!constraints.isEmpty()) { LOG.info("validateLinkConstraints: {}", link.getLinkId().getValue()); @@ -434,22 +634,21 @@ public class PceCalculation { private void dropOppositeLink(Link link) { LinkId opplink = MapUtils.extractOppositeLink(link); - PceLink oppPceLink = allPceLinks.get(opplink); - if (oppPceLink != null) { - allPceLinks.remove(oppPceLink); + if (allPceLinks.containsKey(opplink)) { + allPceLinks.remove(opplink); } else { linksToExclude.add(opplink); } } - private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceNode pceNode) { + private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceOpticalNode pceNode) { switch (openroadmNodeType) { - case SRG : + case SRG: pceNode.initSrgTps(); this.azSrgs.add(nodeId); break; - case XPONDER : - pceNode.initXndrTps(); + case XPONDER: + pceNode.initXndrTps(input.getServiceAEnd().getServiceFormat()); break; default: LOG.warn("endPceNode: Node {} is not SRG or XPONDER !", nodeId); @@ -457,7 +656,7 @@ public class PceCalculation { } if (!pceNode.isValid()) { - LOG.error("validateNode : there are no availaible wavelengths in node {}", pceNode.getNodeId().getValue()); + LOG.error("validateNode : there are no available frequencies in node {}", pceNode.getNodeId().getValue()); return false; } return true; @@ -479,24 +678,40 @@ public class PceCalculation { return this.allPceLinks; } + public String getServiceType() { + return serviceType; + } + public PceResult getReturnStructure() { return returnStructure; } - private static void printNodesInfo(Map allpcenodes) { - Iterator> nodes = allpcenodes.entrySet().iterator(); - while (nodes.hasNext()) { - PceNode pcenode = nodes.next().getValue(); - List links = pcenode.getOutgoingLinks(); - LOG.info("In printNodes in node {} : outgoing links {} ", pcenode.getNodeId().getValue(), links.toString()); - } + private static void printNodesInfo(Map allPceNodes) { + allPceNodes.forEach(((nodeId, pceNode) -> { + LOG.info("In printNodes in node {} : outgoing links {} ", pceNode.getNodeId().getValue(), + pceNode.getOutgoingLinks()); + })); } - /*private static void printLinksInfo(Map allpcelinks) { - Iterator> links = allpcelinks.entrySet().iterator(); - while (links.hasNext()) { - LOG.info("In printLinksInfo link {} : ", links.next().getValue().toString()); + /** + * Get mc capability slot width granularity for device. + * @param deviceNodeId String + * @param nodeId NodeId + * @return slot width granularity + */ + private BigDecimal getSlotWidthGranularity(String deviceNodeId, NodeId nodeId) { + // nodeId: openroadm-topology level node + // deviceNodeId: openroadm-network level node + List mcCapabilities = mappingUtils.getMcCapabilitiesForNode(deviceNodeId); + String[] params = nodeId.getValue().split("-"); + // DEGX or SRGX + String rdmModuleName = params[params.length - 1]; + for (McCapabilities mcCapabitility : mcCapabilities) { + if (mcCapabitility.getMcNodeName().contains(rdmModuleName) + && mcCapabitility.getSlotWidthGranularity() != null) { + return mcCapabitility.getSlotWidthGranularity().getValue(); + } } - }*/ - + return GridConstant.SLOT_WIDTH_50; + } }