Fix issue in PCE
[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.rev200529.Node1;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmLinkType;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.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         if (input.getServiceAEnd().getServiceFormat() == null || input.getServiceZEnd().getServiceFormat() == null
114             || input.getServiceAEnd().getServiceRate() == null) {
115             LOG.error("Service Format and Service Rate are required for a path calculation");
116             return false;
117         }
118         serviceFormatA = input.getServiceAEnd().getServiceFormat().getName();
119         serviceFormatZ = input.getServiceZEnd().getServiceFormat().getName();
120         serviceRate = input.getServiceAEnd().getServiceRate().toJava();
121
122         LOG.info("parseInput: A and Z :[{}] and [{}]", anodeId, znodeId);
123         if (!(serviceFormatA.equals(serviceFormatZ))) {
124             LOG.info("parseInput: different service format for A and Z not handled, will use service format from Aend");
125         } else if (serviceRate == 100L) {
126             switch (serviceFormatA) {
127                 case "Ethernet":
128                 case "OC":
129                     serviceType = "100GE";
130                     break;
131                 case "OTU":
132                     serviceType = "OTU4";
133                     break;
134                 case "ODU":
135                     serviceType = "ODU4";
136                     break;
137                 default:
138                     LOG.debug("parseInput: unsupported service type: Format {} Rate 100L", serviceFormatA);
139                     break;
140             }
141             //switch(serviceRate) may seem a better option at first glance.
142             //But switching on Long or long is not directly possible in Java.
143             //And casting to int bumps the limit here.
144             //Passing by ENUM or String are possible alternatives.
145             //Maybe HashMap and similar options should also be considered here.
146         } else if ("Ethernet".equals(serviceFormatA)) {
147         //only rate 100L is currently supported except in Ethernet
148             if (serviceRate == 10L) {
149                 serviceType = "10GE";
150             } else if (serviceRate == 1L) {
151                 serviceType = "1GE";
152             } else {
153                 LOG.debug("parseInput: unsupported service type: Format Ethernet Rate {}", serviceRate);
154             }
155         } else {
156             LOG.debug("parseInput: unsupported service type: Format {} Rate {}",
157                 serviceFormatA, serviceRate);
158         }
159         if ("ODU4".equals(serviceType) || "10GE".equals(serviceType)  || "1GE".equals(serviceType)) {
160             anodeId = input.getServiceAEnd().getTxDirection().getPort().getPortDeviceName();
161             znodeId = input.getServiceZEnd().getTxDirection().getPort().getPortDeviceName();
162         } else {
163             anodeId = input.getServiceAEnd().getNodeId();
164             znodeId = input.getServiceZEnd().getNodeId();
165         }
166
167         returnStructure.setRate(input.getServiceAEnd().getServiceRate().toJava());
168         returnStructure.setServiceFormat(input.getServiceAEnd().getServiceFormat());
169         return true;
170     }
171
172     private boolean readMdSal() {
173         InstanceIdentifier<Network> nwInstanceIdentifier = null;
174         Network nw = null;
175         if (("OC".equals(serviceFormatA)) || ("OTU".equals(serviceFormatA)) || (("Ethernet".equals(serviceFormatA))
176             && (serviceRate == 100L))) {
177
178             LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID);
179             nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
180                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
181         } else if ("ODU".equals(serviceFormatA) || ("Ethernet".equals(serviceFormatA) && serviceRate == 10L)
182             || ("Ethernet".equals(serviceFormatA) && serviceRate == 1L)) {
183             LOG.info("readMdSal: network {}", NetworkUtils.OTN_NETWORK_ID);
184             nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
185                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID))).build();
186         } else {
187             LOG.info("readMdSal: service-rate {} / service-format not handled {}", serviceRate, serviceFormatA);
188             return false;
189         }
190
191         try {
192             Optional<Network> nwOptional =
193                 networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier).get();
194             if (nwOptional.isPresent()) {
195                 nw = nwOptional.get();
196                 LOG.debug("readMdSal: network nodes: nwOptional.isPresent = true {}", nw);
197             }
198         } catch (InterruptedException | ExecutionException e) {
199             LOG.error("readMdSal: Error reading topology {}", nwInstanceIdentifier);
200             networkTransactionService.close();
201             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
202             throw new RuntimeException(
203                 "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e);
204         }
205         networkTransactionService.close();
206
207         if (nw == null) {
208             LOG.error("readMdSal: network is null: {}", nwInstanceIdentifier);
209             return false;
210         }
211         allNodes = nw.nonnullNode().values().stream().sorted((n1, n2)
212             -> n1.getNodeId().getValue().compareTo(n2.getNodeId().getValue())).collect(Collectors.toList());
213         Network1 nw1 = nw.augmentation(Network1.class);
214         if (nw1 != null) {
215             allLinks = nw1.nonnullLink().values().stream().sorted((l1, l2)
216                 -> l1.getSource().getSourceTp().toString().compareTo(l2.getSource().getSourceTp().toString()))
217                     .collect(Collectors.toList());
218         } else {
219             LOG.warn("no otn links in otn-topology");
220         }
221         if (allNodes == null || allNodes.isEmpty()) {
222             LOG.error("readMdSal: no nodes ");
223             return false;
224         }
225         LOG.info("readMdSal: network nodes: {} nodes added", allNodes.size());
226         LOG.debug("readMdSal: network nodes: {} nodes added", allNodes);
227
228         if (allLinks == null || allLinks.isEmpty()) {
229             LOG.error("readMdSal: no links ");
230             return false;
231         }
232         LOG.info("readMdSal: network links: {} links added", allLinks.size());
233         LOG.debug("readMdSal: network links: {} links added", allLinks);
234
235         return true;
236     }
237
238     private boolean analyzeNw() {
239
240         LOG.debug("analyzeNw: allNodes size {}, allLinks size {}", allNodes.size(), allLinks.size());
241
242         if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
243             // 100GE service and OTU4 service are handled at the openroadm-topology layer
244             for (Node node : allNodes) {
245                 validateNode(node);
246             }
247
248             LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size());
249
250             if (aendPceNode == null || zendPceNode == null) {
251                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
252                 return false;
253             }
254             for (Link link : allLinks) {
255                 validateLink(link);
256             }
257             // debug prints
258             LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size());
259             // debug prints
260             LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size());
261             for (NodeId srg : azSrgs) {
262                 LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue());
263             }
264             // debug prints
265             for (PceLink link : addLinks) {
266                 filteraddLinks(link);
267             }
268             for (PceLink link : dropLinks) {
269                 filterdropLinks(link);
270             }
271
272         } else {
273             // ODU4, 10GE/ODU2e or 1GE/ODU0 services are handled at openroadm-otn layer
274
275             for (Node node : allNodes) {
276                 validateOtnNode(node);
277             }
278
279             LOG.info("analyzeNw: allPceNodes {}", allPceNodes);
280
281             if (aendPceNode == null || zendPceNode == null) {
282                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
283                 return false;
284             }
285             for (Link link : allLinks) {
286                 validateLink(link);
287             }
288         }
289
290         LOG.info("analyzeNw: allPceNodes size {}, allPceLinks size {}", allPceNodes.size(), allPceLinks.size());
291
292         if ((allPceNodes.size() == 0) || (allPceLinks.size() == 0)) {
293             return false;
294         }
295
296         LOG.debug("analyzeNw: allPceNodes {}", allPceNodes);
297         LOG.debug("analyzeNw: allPceLinks {}", allPceLinks);
298
299         return true;
300     }
301
302     private boolean filteraddLinks(PceLink pcelink) {
303
304         NodeId nodeId = pcelink.getSourceId();
305
306         if (azSrgs.contains(nodeId)) {
307             allPceLinks.put(pcelink.getLinkId(), pcelink);
308             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
309             LOG.debug("analyzeNw: Add_LINK added to source and to allPceLinks {}", pcelink.getLinkId());
310             return true;
311         }
312
313         // remove the SRG from PceNodes, as it is not directly connected to A/Z
314         allPceNodes.remove(nodeId);
315         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
316
317         return false;
318     }
319
320     private boolean filterdropLinks(PceLink pcelink) {
321
322         NodeId nodeId = pcelink.getDestId();
323
324         if (azSrgs.contains(nodeId)) {
325             allPceLinks.put(pcelink.getLinkId(), pcelink);
326             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
327             LOG.debug("analyzeNw: Drop_LINK added to dest and to allPceLinks {}", pcelink.getLinkId());
328             return true;
329         }
330
331         // remove the SRG from PceNodes, as it is not directly connected to A/Z
332         allPceNodes.remove(pcelink.getDestId());
333         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
334
335         return false;
336     }
337
338     private boolean validateLink(Link link) {
339         LOG.info("validateLink: link {} ", link);
340
341         NodeId sourceId = link.getSource().getSourceNode();
342         NodeId destId = link.getDestination().getDestNode();
343         PceNode source = allPceNodes.get(sourceId);
344         PceNode dest = allPceNodes.get(destId);
345
346         if (source == null) {
347             LOG.debug("validateLink: Link is ignored due source node is rejected by node validation - {}",
348                 link.getSource().getSourceNode().getValue());
349             return false;
350         }
351         if (dest == null) {
352             LOG.debug("validateLink: Link is ignored due dest node is rejected by node validation - {}",
353                 link.getDestination().getDestNode().getValue());
354             return false;
355         }
356
357         if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
358             // 100GE or OTU4 services are handled at WDM Layer
359             PceLink pcelink = new PceLink(link, source, dest);
360             if (!pcelink.isValid()) {
361                 dropOppositeLink(link);
362                 LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
363                 return false;
364             }
365             LinkId linkId = pcelink.getLinkId();
366             if (validateLinkConstraints(pcelink).equals(ConstraintTypes.HARD_EXCLUDE)) {
367                 dropOppositeLink(link);
368                 LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
369                 return false;
370             }
371             switch (pcelink.getlinkType()) {
372                 case ROADMTOROADM:
373                 case EXPRESSLINK:
374                     allPceLinks.put(linkId, pcelink);
375                     source.addOutgoingLink(pcelink);
376                     LOG.debug("validateLink: {}-LINK added to allPceLinks {}",
377                         pcelink.getlinkType(), pcelink);
378                     break;
379                 case ADDLINK:
380                     pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString()));
381                     addLinks.add(pcelink);
382                     LOG.debug("validateLink: ADD-LINK saved  {}", pcelink);
383                     break;
384                 case DROPLINK:
385                     pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString()));
386                     dropLinks.add(pcelink);
387                     LOG.debug("validateLink: DROP-LINK saved  {}", pcelink);
388                     break;
389                 case XPONDERINPUT:
390                     // store separately all SRG links directly
391                     azSrgs.add(sourceId);
392                     // connected to A/Z
393                     if (!dest.checkTP(pcelink.getDestTP().toString())) {
394                         LOG.debug(
395                             "validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink);
396                         return false;
397                     }
398                     if (dest.getXpdrClient(pcelink.getDestTP().toString()) != null) {
399                         pcelink.setClient(dest.getXpdrClient(pcelink.getDestTP().toString()));
400                     }
401                     allPceLinks.put(linkId, pcelink);
402                     source.addOutgoingLink(pcelink);
403                     LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink);
404                     break;
405                 // does it mean XPONDER==>>SRG ?
406                 case XPONDEROUTPUT:
407                     // store separately all SRG links directly
408                     azSrgs.add(destId);
409                     // connected to A/Z
410                     if (!source.checkTP(pcelink.getSourceTP().toString())) {
411                         LOG.debug(
412                             "validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink);
413                         return false;
414                     }
415                     if (source.getXpdrClient(pcelink.getSourceTP().toString()) != null) {
416                         pcelink.setClient(source.getXpdrClient(pcelink.getSourceTP().toString()));
417                     }
418                     allPceLinks.put(linkId, pcelink);
419                     source.addOutgoingLink(pcelink);
420                     LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink);
421                     break;
422                 default:
423                     LOG.warn("validateLink: link type is not supported {}", pcelink);
424             }
425             return true;
426
427         } else if (("ODU4".equals(serviceType)) || ("10GE".equals(serviceType)) || ("1GE".equals(serviceType))) {
428             // ODU4, 1GE and 10GE services relying on ODU2, ODU2e or ODU0 services are handled at OTN layer
429             PceLink pceOtnLink = new PceLink(link, source, dest);
430
431             if (!pceOtnLink.isOtnValid(link, serviceType)) {
432                 dropOppositeLink(link);
433                 LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
434                 return false;
435             }
436
437             LinkId linkId = pceOtnLink.getLinkId();
438             if (validateLinkConstraints(pceOtnLink).equals(ConstraintTypes.HARD_EXCLUDE)) {
439                 dropOppositeLink(link);
440                 LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
441                 return false;
442             }
443
444             switch (pceOtnLink.getlinkType()) {
445                 case OTNLINK:
446                     if (dest.getXpdrClient(pceOtnLink.getDestTP().toString()) != null) {
447                         pceOtnLink.setClient(dest.getXpdrClient(pceOtnLink.getDestTP().toString()));
448                     }
449
450                     allPceLinks.put(linkId, pceOtnLink);
451                     source.addOutgoingLink(pceOtnLink);
452                     LOG.info("validateLink: OTN-LINK added to allPceLinks {}", pceOtnLink);
453                     break;
454                 default:
455                     LOG.warn("validateLink: link type is not supported {}", pceOtnLink);
456             }
457             return true;
458
459         } else {
460             LOG.error(" validateLink: Unmanaged service type {}", serviceType);
461             return false;
462         }
463
464     }
465
466     private boolean validateNode(Node node) {
467         LOG.debug("validateNode: node {} ", node);
468
469         // PceNode will be used in Graph algorithm
470         Node1 node1 = node.augmentation(Node1.class);
471         if (node1 == null) {
472             LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId());
473             return false;
474         }
475         OpenroadmNodeType nodeType = node1.getNodeType();
476
477         PceOpticalNode pceNode = new PceOpticalNode(node, nodeType, node.getNodeId(),
478             input.getServiceAEnd().getServiceFormat(), "optical");
479         pceNode.validateAZxponder(anodeId, znodeId);
480         pceNode.initWLlist();
481
482         if (!pceNode.isValid()) {
483             LOG.warn(" validateNode: Node is ignored");
484             return false;
485         }
486         if (validateNodeConstraints(pceNode).equals(ConstraintTypes.HARD_EXCLUDE)) {
487             return false;
488         }
489         if (endPceNode(nodeType, pceNode.getNodeId(), pceNode) && this.aendPceNode == null
490             && isAZendPceNode(this.serviceFormatA, pceNode, anodeId, "A")) {
491             this.aendPceNode = pceNode;
492         }
493         if (endPceNode(nodeType, pceNode.getNodeId(), pceNode) && this.zendPceNode == null
494             && isAZendPceNode(this.serviceFormatZ, pceNode, znodeId, "Z")) {
495             this.zendPceNode = pceNode;
496         }
497
498         allPceNodes.put(pceNode.getNodeId(), pceNode);
499         LOG.debug("validateNode: node is saved {}", pceNode.getNodeId().getValue());
500         return true;
501     }
502
503     private boolean isAZendPceNode(String serviceFormat, PceOpticalNode pceNode, String azNodeId, String azEndPoint) {
504         switch (serviceFormat) {
505             case "Ethernet":
506             case "OC":
507                 if (pceNode.getSupNetworkNodeId().equals(azNodeId)) {
508                     return true;
509                 }
510                 return false;
511             case "OTU":
512                 if ("A".equals(azEndPoint) && pceNode.getNodeId().getValue()
513                     .equals(this.input.getServiceAEnd().getRxDirection().getPort().getPortDeviceName())) {
514                     return true;
515                 }
516                 if ("Z".equals(azEndPoint) && pceNode.getNodeId().getValue()
517                     .equals(this.input.getServiceZEnd().getRxDirection().getPort().getPortDeviceName())) {
518                     return true;
519                 }
520                 return false;
521             default:
522                 LOG.debug("Unsupported service Format {} for node {}", serviceFormat, pceNode.getNodeId().getValue());
523                 return false;
524         }
525     }
526
527     private boolean validateOtnNode(Node node) {
528         LOG.info("validateOtnNode: {} ", node.getNodeId().getValue());
529         // PceOtnNode will be used in Graph algorithm
530         if (node.augmentation(Node1.class) != null) {
531             OpenroadmNodeType nodeType = node.augmentation(Node1.class).getNodeType();
532
533             PceOtnNode pceOtnNode = new PceOtnNode(node, nodeType, node.getNodeId(), "otn", serviceType);
534             pceOtnNode.validateXponder(anodeId, znodeId);
535
536             if (!pceOtnNode.isValid()) {
537                 LOG.warn(" validateOtnNode: Node {} is ignored", node.getNodeId().getValue());
538                 return false;
539             }
540             if (validateNodeConstraints(pceOtnNode).equals(ConstraintTypes.HARD_EXCLUDE)) {
541                 return false;
542             }
543             if (pceOtnNode.getNodeId().getValue().equals(anodeId) && this.aendPceNode == null) {
544                 this.aendPceNode = pceOtnNode;
545             }
546             if (pceOtnNode.getNodeId().getValue().equals(znodeId) && this.zendPceNode == null) {
547                 this.zendPceNode = pceOtnNode;
548             }
549             allPceNodes.put(pceOtnNode.getNodeId(), pceOtnNode);
550             LOG.info("validateOtnNode: node {} is saved", node.getNodeId().getValue());
551             return true;
552         } else {
553             LOG.error("ValidateOtnNode: no node-type augmentation. Node {} is ignored", node.getNodeId().getValue());
554             return false;
555         }
556
557 //        if (mode == "AZ") {
558 //            pceOtnNode.validateAZxponder(anodeId, znodeId);
559 //        } else if (mode == "intermediate") {
560 //            pceOtnNode.validateIntermediateSwitch();
561 //        } else {
562 //            LOG.error("validateOtnNode: unproper mode passed to the method : {} not supported", mode);
563 //            return null;
564 //        }
565     }
566
567     private ConstraintTypes validateNodeConstraints(PceNode pcenode) {
568         if (pceHardConstraints.getExcludeSupNodes().isEmpty() && pceHardConstraints.getExcludeCLLI().isEmpty()) {
569             return ConstraintTypes.NONE;
570         }
571         if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNetworkNodeId())) {
572             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
573             return ConstraintTypes.HARD_EXCLUDE;
574         }
575         if (pceHardConstraints.getExcludeCLLI().contains(pcenode.getSupClliNodeId())) {
576             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
577             return ConstraintTypes.HARD_EXCLUDE;
578         }
579         return ConstraintTypes.NONE;
580     }
581
582     private ConstraintTypes validateLinkConstraints(PceLink link) {
583         if (pceHardConstraints.getExcludeSRLG().isEmpty()) {
584             return ConstraintTypes.NONE;
585         }
586
587         // for now SRLG is the only constraint for link
588         if (link.getlinkType() != OpenroadmLinkType.ROADMTOROADM) {
589             return ConstraintTypes.NONE;
590         }
591
592         List<Long> constraints = new ArrayList<>(pceHardConstraints.getExcludeSRLG());
593         constraints.retainAll(link.getsrlgList());
594         if (!constraints.isEmpty()) {
595             LOG.info("validateLinkConstraints: {}", link.getLinkId().getValue());
596             return ConstraintTypes.HARD_EXCLUDE;
597         }
598
599         return ConstraintTypes.NONE;
600     }
601
602     private void dropOppositeLink(Link link) {
603         LinkId opplink = MapUtils.extractOppositeLink(link);
604
605         if (allPceLinks.containsKey(opplink)) {
606             allPceLinks.remove(opplink);
607         } else {
608             linksToExclude.add(opplink);
609         }
610     }
611
612     private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceOpticalNode pceNode) {
613         switch (openroadmNodeType) {
614             case SRG:
615                 pceNode.initSrgTps();
616                 this.azSrgs.add(nodeId);
617                 break;
618             case XPONDER:
619                 pceNode.initXndrTps();
620                 break;
621             default:
622                 LOG.warn("endPceNode: Node {} is not SRG or XPONDER !", nodeId);
623                 return false;
624         }
625
626         if (!pceNode.isValid()) {
627             LOG.error("validateNode : there are no availaible wavelengths in node {}", pceNode.getNodeId().getValue());
628             return false;
629         }
630         return true;
631     }
632
633     public PceNode getaendPceNode() {
634         return aendPceNode;
635     }
636
637     public PceNode getzendPceNode() {
638         return zendPceNode;
639     }
640
641     public Map<NodeId, PceNode> getAllPceNodes() {
642         return this.allPceNodes;
643     }
644
645     public Map<LinkId, PceLink> getAllPceLinks() {
646         return this.allPceLinks;
647     }
648
649     public String getServiceType() {
650         return serviceType;
651     }
652
653     public PceResult getReturnStructure() {
654         return returnStructure;
655     }
656
657     private static void printNodesInfo(Map<NodeId, PceNode> allPceNodes) {
658         allPceNodes.forEach(((nodeId, pceNode) -> {
659             LOG.info("In printNodes in node {} : outgoing links {} ", pceNode.getNodeId().getValue(),
660                     pceNode.getOutgoingLinks());
661         }));
662     }
663 }