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