Merge "review sims/tpce start-up sequence in 2.2.1 tests"
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / networkanalyzer / PceCalculation.java
1 /*
2  * Copyright © 2017 AT&T, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.transportpce.pce.networkanalyzer;
10
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Optional;
17 import java.util.Set;
18 import java.util.concurrent.ExecutionException;
19 import java.util.stream.Collectors;
20 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
21 import org.opendaylight.transportpce.common.NetworkUtils;
22 import org.opendaylight.transportpce.common.ResponseCodes;
23 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
24 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev200128.PathComputationRequestInput;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Node1;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmNodeType;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 //import org.opendaylight.yangtools.yang.common.Decimal64;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public class PceCalculation {
44     /* Logging. */
45     private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
46     private NetworkTransactionService networkTransactionService = null;
47
48     ///////////// data parsed from Input/////////////////
49     private PathComputationRequestInput input;
50     private String anodeId = "";
51     private String znodeId = "";
52     private String serviceFormatA = "";
53     private String serviceFormatZ = "";
54     private String serviceType = "";
55     private Long serviceRate = 0L;
56
57     private PceConstraints pceHardConstraints;
58
59     ///////////// Intermediate data/////////////////
60     private List<PceLink> addLinks = new ArrayList<>();
61     private List<PceLink> dropLinks = new ArrayList<>();
62     private HashSet<NodeId> azSrgs = new HashSet<>();
63
64     private PceNode aendPceNode = null;
65     private PceNode zendPceNode = null;
66
67     private List<Link> allLinks = null;
68     private List<Node> allNodes = null;
69
70     // this List serves graph calculation
71     private Map<NodeId, PceNode> allPceNodes = new HashMap<>();
72     // this List serves calculation of ZtoA path description
73     // TODO maybe better solution is possible
74     private Map<LinkId, PceLink> allPceLinks = new HashMap<>();
75     private Set<LinkId> linksToExclude = new HashSet<>();
76     private PceResult returnStructure;
77
78     private enum ConstraintTypes {
79         NONE, HARD_EXCLUDE, HARD_INCLUDE, HARD_DIVERSITY, SOFT_EXCLUDE, SOFT_INCLUDE, SOFT_DIVERSITY;
80     }
81
82     public PceCalculation(PathComputationRequestInput input, NetworkTransactionService networkTransactionService,
83             PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc) {
84         this.input = input;
85         this.networkTransactionService = networkTransactionService;
86         this.returnStructure = rc;
87
88         this.pceHardConstraints = pceHardConstraints;
89         parseInput();
90     }
91
92     public void retrievePceNetwork() {
93
94         LOG.info("In PceCalculation retrieveNetwork: ");
95
96         if (!readMdSal()) {
97             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
98             return;
99         }
100         MapUtils.mapDiversityConstraints(allNodes, allLinks, pceHardConstraints);
101
102         if (!analyzeNw()) {
103             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
104             return;
105         }
106         printNodesInfo(allPceNodes);
107
108         returnStructure.setRC(ResponseCodes.RESPONSE_OK);
109         return;
110     }
111
112     private boolean parseInput() {
113         anodeId = input.getServiceAEnd().getNodeId();
114         znodeId = input.getServiceZEnd().getNodeId();
115         if (input.getServiceAEnd().getServiceFormat() == null || input.getServiceZEnd().getServiceFormat() == null
116             || input.getServiceAEnd().getServiceRate() == null) {
117             LOG.error("Service Format and Service Rate are required for a path calculation");
118             return false;
119         }
120         serviceFormatA = input.getServiceAEnd().getServiceFormat().getName();
121         serviceFormatZ = input.getServiceZEnd().getServiceFormat().getName();
122         serviceRate = input.getServiceAEnd().getServiceRate().toJava();
123
124         LOG.info("parseInput: A and Z :[{}] and [{}]", anodeId, znodeId);
125         if (!(serviceFormatA.equals(serviceFormatZ))) {
126             LOG.info("parseInput: different service format for A and Z not handled, will use service format from Aend");
127         } else if (serviceRate == 100L) {
128             switch (serviceFormatA) {
129                 case "Ethernet":
130                 case "OC":
131                     serviceType = "100GE";
132                     break;
133                 case "OTU":
134                     serviceType = "OTU4";
135                     break;
136                 case "ODU":
137                     serviceType = "ODU4";
138                     break;
139                 default:
140                     LOG.debug("parseInput: unsupported service type: Format {} Rate 100L", serviceFormatA);
141                     break;
142             }
143             //switch(serviceRate) may seem a better option at first glance.
144             //But switching on Long or long is not directly possible in Java.
145             //And casting to int bumps the limit here.
146             //Passing by ENUM or String are possible alternatives.
147             //Maybe HashMap and similar options should also be considered here.
148         } else if ("Ethernet".equals(serviceFormatA)) {
149         //only rate 100L is currently supported except in Ethernet
150             if (serviceRate == 10L) {
151                 serviceType = "10GE";
152             } else if (serviceRate == 1L) {
153                 serviceType = "1GE";
154             } else {
155                 LOG.debug("parseInput: unsupported service type: Format Ethernet Rate {}", serviceRate);
156             }
157         } else {
158             LOG.debug("parseInput: unsupported service type: Format {} Rate {}",
159                 serviceFormatA, serviceRate);
160         }
161
162         returnStructure.setRate(input.getServiceAEnd().getServiceRate().toJava());
163         returnStructure.setServiceFormat(input.getServiceAEnd().getServiceFormat());
164         return true;
165     }
166
167     private boolean readMdSal() {
168         InstanceIdentifier<Network> nwInstanceIdentifier = null;
169         Network nw = null;
170         if (("OC".equals(serviceFormatA)) || ("OTU".equals(serviceFormatA)) || (("Ethernet".equals(serviceFormatA))
171             && (serviceRate == 100L))) {
172
173             LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID);
174             nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
175                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
176         } else if ("ODU".equals(serviceFormatA) || ("Ethernet".equals(serviceFormatA) && serviceRate == 10L)
177             || ("Ethernet".equals(serviceFormatA) && serviceRate == 1L)) {
178             LOG.info("readMdSal: network {}", NetworkUtils.OTN_NETWORK_ID);
179             nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
180                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID))).build();
181         } else {
182             LOG.info("readMdSal: service-rate {} / service-format not handled {}", serviceRate, serviceFormatA);
183             return false;
184         }
185
186         try {
187             Optional<Network> nwOptional =
188                 networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier).get();
189             if (nwOptional.isPresent()) {
190                 nw = nwOptional.get();
191                 LOG.debug("readMdSal: network nodes: nwOptional.isPresent = true {}", nw);
192             }
193         } catch (InterruptedException | ExecutionException e) {
194             LOG.error("readMdSal: Error reading topology {}", nwInstanceIdentifier);
195             networkTransactionService.close();
196             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
197             throw new RuntimeException(
198                 "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e);
199         }
200         networkTransactionService.close();
201
202         if (nw == null) {
203             LOG.error("readMdSal: network is null: {}", nwInstanceIdentifier);
204             return false;
205         }
206         allNodes = nw.getNode().stream().sorted((n1, n2) -> n1.getNodeId().getValue().compareTo(n2.getNodeId()
207             .getValue())).collect(Collectors.toList());
208         Network1 nw1 = nw.augmentation(Network1.class);
209         if (nw1 != null) {
210             allLinks = nw1.getLink().stream().sorted((l1, l2) -> l1.getSource().getSourceTp().toString().compareTo(l2
211                 .getSource().getSourceTp().toString())).collect(Collectors.toList());
212         } else {
213             LOG.warn("no otn links in otn-topology");
214         }
215         if (allNodes == null || allNodes.isEmpty()) {
216             LOG.error("readMdSal: no nodes ");
217             return false;
218         }
219         LOG.info("readMdSal: network nodes: {} nodes added", allNodes.size());
220         LOG.debug("readMdSal: network nodes: {} nodes added", allNodes);
221
222         if (allLinks == null || allLinks.isEmpty()) {
223             LOG.error("readMdSal: no links ");
224             return false;
225         }
226         LOG.info("readMdSal: network links: {} links added", allLinks.size());
227         LOG.debug("readMdSal: network links: {} links added", allLinks);
228
229         return true;
230     }
231
232     private boolean analyzeNw() {
233
234         LOG.debug("analyzeNw: allNodes size {}, allLinks size {}", allNodes.size(), allLinks.size());
235
236         if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
237             // 100GE service and OTU4 service are handled at the openroadm-topology layer
238             for (Node node : allNodes) {
239                 validateNode(node);
240             }
241
242             LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size());
243
244             if (aendPceNode == null || zendPceNode == null) {
245                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
246                 return false;
247             }
248             for (Link link : allLinks) {
249                 validateLink(link);
250             }
251             // debug prints
252             LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size());
253             // debug prints
254             LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size());
255             for (NodeId srg : azSrgs) {
256                 LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue());
257             }
258             // debug prints
259             for (PceLink link : addLinks) {
260                 filteraddLinks(link);
261             }
262             for (PceLink link : dropLinks) {
263                 filterdropLinks(link);
264             }
265
266         } else {
267             // ODU4, 10GE/ODU2e or 1GE/ODU0 services are handled at openroadm-otn layer
268
269             for (Node node : allNodes) {
270                 validateOtnNode(node);
271             }
272
273             LOG.info("analyzeNw: allPceNodes {}", allPceNodes);
274
275             if (aendPceNode == null || zendPceNode == null) {
276                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
277                 return false;
278             }
279             for (Link link : allLinks) {
280                 validateLink(link);
281             }
282         }
283
284         LOG.info("analyzeNw: allPceNodes size {}, allPceLinks size {}", allPceNodes.size(), allPceLinks.size());
285
286         if ((allPceNodes.size() == 0) || (allPceLinks.size() == 0)) {
287             return false;
288         }
289
290         LOG.debug("analyzeNw: allPceNodes {}", allPceNodes);
291         LOG.debug("analyzeNw: allPceLinks {}", allPceLinks);
292
293         return true;
294     }
295
296     private boolean filteraddLinks(PceLink pcelink) {
297
298         NodeId nodeId = pcelink.getSourceId();
299
300         if (azSrgs.contains(nodeId)) {
301             allPceLinks.put(pcelink.getLinkId(), pcelink);
302             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
303             LOG.debug("analyzeNw: Add_LINK added to source and to allPceLinks {}", pcelink.getLinkId());
304             return true;
305         }
306
307         // remove the SRG from PceNodes, as it is not directly connected to A/Z
308         allPceNodes.remove(nodeId);
309         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
310
311         return false;
312     }
313
314     private boolean filterdropLinks(PceLink pcelink) {
315
316         NodeId nodeId = pcelink.getDestId();
317
318         if (azSrgs.contains(nodeId)) {
319             allPceLinks.put(pcelink.getLinkId(), pcelink);
320             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
321             LOG.debug("analyzeNw: Drop_LINK added to dest and to allPceLinks {}", pcelink.getLinkId());
322             return true;
323         }
324
325         // remove the SRG from PceNodes, as it is not directly connected to A/Z
326         allPceNodes.remove(pcelink.getDestId());
327         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
328
329         return false;
330     }
331
332     private boolean validateLink(Link link) {
333         LOG.info("validateLink: link {} ", link);
334
335         NodeId sourceId = link.getSource().getSourceNode();
336         NodeId destId = link.getDestination().getDestNode();
337         PceNode source = allPceNodes.get(sourceId);
338         PceNode dest = allPceNodes.get(destId);
339
340         if (source == null) {
341             LOG.debug("validateLink: Link is ignored due source node is rejected by node validation - {}",
342                 link.getSource().getSourceNode().getValue());
343             return false;
344         }
345         if (dest == null) {
346             LOG.debug("validateLink: Link is ignored due dest node is rejected by node validation - {}",
347                 link.getDestination().getDestNode().getValue());
348             return false;
349         }
350
351         if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
352             // 100GE or OTU4 services are handled at WDM Layer
353             PceLink pcelink = new PceLink(link, source, dest);
354             if (!pcelink.isValid()) {
355                 dropOppositeLink(link);
356                 LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
357                 return false;
358             }
359             LinkId linkId = pcelink.getLinkId();
360             if (validateLinkConstraints(pcelink).equals(ConstraintTypes.HARD_EXCLUDE)) {
361                 dropOppositeLink(link);
362                 LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
363                 return false;
364             }
365             switch (pcelink.getlinkType()) {
366                 case ROADMTOROADM:
367                 case EXPRESSLINK:
368                     allPceLinks.put(linkId, pcelink);
369                     source.addOutgoingLink(pcelink);
370                     LOG.debug("validateLink: {}-LINK added to allPceLinks {}",
371                         pcelink.getlinkType(), pcelink);
372                     break;
373                 case ADDLINK:
374                     pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString()));
375                     addLinks.add(pcelink);
376                     LOG.debug("validateLink: ADD-LINK saved  {}", pcelink);
377                     break;
378                 case DROPLINK:
379                     pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString()));
380                     dropLinks.add(pcelink);
381                     LOG.debug("validateLink: DROP-LINK saved  {}", pcelink);
382                     break;
383                 case XPONDERINPUT:
384                     // store separately all SRG links directly
385                     azSrgs.add(sourceId);
386                     // connected to A/Z
387                     if (!dest.checkTP(pcelink.getDestTP().toString())) {
388                         LOG.debug(
389                             "validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink);
390                         return false;
391                     }
392                     if (dest.getXpdrClient(pcelink.getDestTP().toString()) != null) {
393                         pcelink.setClient(dest.getXpdrClient(pcelink.getDestTP().toString()));
394                     }
395                     allPceLinks.put(linkId, pcelink);
396                     source.addOutgoingLink(pcelink);
397                     LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink);
398                     break;
399                 // does it mean XPONDER==>>SRG ?
400                 case XPONDEROUTPUT:
401                     // store separately all SRG links directly
402                     azSrgs.add(destId);
403                     // connected to A/Z
404                     if (!source.checkTP(pcelink.getSourceTP().toString())) {
405                         LOG.debug(
406                             "validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink);
407                         return false;
408                     }
409                     if (source.getXpdrClient(pcelink.getSourceTP().toString()) != null) {
410                         pcelink.setClient(source.getXpdrClient(pcelink.getSourceTP().toString()));
411                     }
412                     allPceLinks.put(linkId, pcelink);
413                     source.addOutgoingLink(pcelink);
414                     LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink);
415                     break;
416                 default:
417                     LOG.warn("validateLink: link type is not supported {}", pcelink);
418             }
419             return true;
420
421         } else if (("ODU4".equals(serviceType)) || ("10GE".equals(serviceType)) || ("1GE".equals(serviceType))) {
422             // ODU4, 1GE and 10GE services relying on ODU2, ODU2e or ODU0 services are handled at OTN layer
423             PceLink pceOtnLink = new PceLink(link, source, dest);
424
425             if (!pceOtnLink.isOtnValid(link, serviceType)) {
426                 dropOppositeLink(link);
427                 LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
428                 return false;
429             }
430
431             LinkId linkId = pceOtnLink.getLinkId();
432             if (validateLinkConstraints(pceOtnLink).equals(ConstraintTypes.HARD_EXCLUDE)) {
433                 dropOppositeLink(link);
434                 LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
435                 return false;
436             }
437
438             switch (pceOtnLink.getlinkType()) {
439                 case OTNLINK:
440                     if (dest.getXpdrClient(pceOtnLink.getDestTP().toString()) != null) {
441                         pceOtnLink.setClient(dest.getXpdrClient(pceOtnLink.getDestTP().toString()));
442                     }
443
444                     allPceLinks.put(linkId, pceOtnLink);
445                     source.addOutgoingLink(pceOtnLink);
446                     LOG.info("validateLink: OTN-LINK added to allPceLinks {}", pceOtnLink);
447                     break;
448                 default:
449                     LOG.warn("validateLink: link type is not supported {}", pceOtnLink);
450             }
451             return true;
452
453         } else {
454             LOG.error(" validateLink: Unmanaged service type {}", serviceType);
455             return false;
456         }
457
458     }
459
460     private boolean validateNode(Node node) {
461         LOG.debug("validateNode: node {} ", node);
462
463         // PceNode will be used in Graph algorithm
464         Node1 node1 = node.augmentation(Node1.class);
465         if (node1 == null) {
466             LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId());
467             return false;
468         }
469         OpenroadmNodeType nodeType = node1.getNodeType();
470
471         PceOpticalNode pceNode = new PceOpticalNode(node, nodeType, node.getNodeId(),
472             input.getServiceAEnd().getServiceFormat(), "optical");
473         pceNode.validateAZxponder(anodeId, znodeId);
474         pceNode.initWLlist();
475
476         if (!pceNode.isValid()) {
477             LOG.warn(" validateNode: Node is ignored");
478             return false;
479         }
480
481         if (validateNodeConstraints(pceNode).equals(ConstraintTypes.HARD_EXCLUDE)) {
482             return false;
483         }
484         if ((pceNode.getSupNetworkNodeId().equals(anodeId) && (this.aendPceNode == null))
485             && (Boolean.TRUE.equals(endPceNode(nodeType, pceNode.getNodeId(), pceNode)))) {
486             this.aendPceNode = pceNode;
487         }
488         if ((pceNode.getSupNetworkNodeId().equals(znodeId) && (this.zendPceNode == null))
489             && (Boolean.TRUE.equals(endPceNode(nodeType, pceNode.getNodeId(), pceNode)))) {
490             this.zendPceNode = pceNode;
491         }
492
493         allPceNodes.put(pceNode.getNodeId(), pceNode);
494         LOG.debug("validateNode: node is saved {}", pceNode.getNodeId().getValue());
495         return true;
496     }
497
498     private boolean validateOtnNode(Node node) {
499
500         LOG.info("validateOtnNode: {} ", node.getNodeId().getValue());
501         // PceOtnNode will be used in Graph algorithm
502         if (node.augmentation(Node1.class) != null) {
503             OpenroadmNodeType nodeType = node.augmentation(Node1.class).getNodeType();
504
505             PceOtnNode pceOtnNode = new PceOtnNode(node, nodeType, node.getNodeId(), "otn", serviceType);
506             pceOtnNode.validateXponder(anodeId, znodeId);
507
508             if (!pceOtnNode.isValid()) {
509                 LOG.warn(" validateOtnNode: Node {} is ignored", node.getNodeId().getValue());
510                 return false;
511             }
512             if (validateNodeConstraints(pceOtnNode).equals(ConstraintTypes.HARD_EXCLUDE)) {
513                 return false;
514             }
515             if (pceOtnNode.getNodeId().getValue().equals(anodeId) && this.aendPceNode == null) {
516                 this.aendPceNode = pceOtnNode;
517             }
518             if (pceOtnNode.getNodeId().getValue().equals(znodeId) && this.zendPceNode == null) {
519                 this.zendPceNode = pceOtnNode;
520             }
521             allPceNodes.put(pceOtnNode.getNodeId(), pceOtnNode);
522             LOG.info("validateOtnNode: node {} is saved", node.getNodeId().getValue());
523             return true;
524         } else {
525             LOG.error("ValidateOtnNode: no node-type augmentation. Node {} is ignored", node.getNodeId().getValue());
526             return false;
527         }
528
529 //        if (mode == "AZ") {
530 //            pceOtnNode.validateAZxponder(anodeId, znodeId);
531 //        } else if (mode == "intermediate") {
532 //            pceOtnNode.validateIntermediateSwitch();
533 //        } else {
534 //            LOG.error("validateOtnNode: unproper mode passed to the method : {} not supported", mode);
535 //            return null;
536 //        }
537     }
538
539     private ConstraintTypes validateNodeConstraints(PceNode pcenode) {
540         if (pceHardConstraints.getExcludeSupNodes().isEmpty() && pceHardConstraints.getExcludeCLLI().isEmpty()) {
541             return ConstraintTypes.NONE;
542         }
543         if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNetworkNodeId())) {
544             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
545             return ConstraintTypes.HARD_EXCLUDE;
546         }
547         if (pceHardConstraints.getExcludeCLLI().contains(pcenode.getSupClliNodeId())) {
548             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
549             return ConstraintTypes.HARD_EXCLUDE;
550         }
551         return ConstraintTypes.NONE;
552     }
553
554     private ConstraintTypes validateLinkConstraints(PceLink link) {
555         if (pceHardConstraints.getExcludeSRLG().isEmpty()) {
556             return ConstraintTypes.NONE;
557         }
558
559         // for now SRLG is the only constraint for link
560         if (link.getlinkType() != OpenroadmLinkType.ROADMTOROADM) {
561             return ConstraintTypes.NONE;
562         }
563
564         List<Long> constraints = new ArrayList<>(pceHardConstraints.getExcludeSRLG());
565         constraints.retainAll(link.getsrlgList());
566         if (!constraints.isEmpty()) {
567             LOG.info("validateLinkConstraints: {}", link.getLinkId().getValue());
568             return ConstraintTypes.HARD_EXCLUDE;
569         }
570
571         return ConstraintTypes.NONE;
572     }
573
574     private void dropOppositeLink(Link link) {
575         LinkId opplink = MapUtils.extractOppositeLink(link);
576
577         if (allPceLinks.containsKey(opplink)) {
578             allPceLinks.remove(opplink);
579         } else {
580             linksToExclude.add(opplink);
581         }
582     }
583
584     private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceOpticalNode pceNode) {
585         switch (openroadmNodeType) {
586             case SRG:
587                 pceNode.initSrgTps();
588                 this.azSrgs.add(nodeId);
589                 break;
590             case XPONDER:
591                 pceNode.initXndrTps();
592                 break;
593             default:
594                 LOG.warn("endPceNode: Node {} is not SRG or XPONDER !", nodeId);
595                 return false;
596         }
597
598         if (!pceNode.isValid()) {
599             LOG.error("validateNode : there are no availaible wavelengths in node {}", pceNode.getNodeId().getValue());
600             return false;
601         }
602         return true;
603     }
604
605     public PceNode getaendPceNode() {
606         return aendPceNode;
607     }
608
609     public PceNode getzendPceNode() {
610         return zendPceNode;
611     }
612
613     public Map<NodeId, PceNode> getAllPceNodes() {
614         return this.allPceNodes;
615     }
616
617     public Map<LinkId, PceLink> getAllPceLinks() {
618         return this.allPceLinks;
619     }
620
621     public String getServiceType() {
622         return serviceType;
623     }
624
625     public PceResult getReturnStructure() {
626         return returnStructure;
627     }
628
629     private static void printNodesInfo(Map<NodeId, PceNode> allPceNodes) {
630         allPceNodes.forEach(((nodeId, pceNode) -> {
631             LOG.info("In printNodes in node {} : outgoing links {} ", pceNode.getNodeId().getValue(),
632                     pceNode.getOutgoingLinks());
633         }));
634     }
635 }