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