35ab8504f0d478450bdd1ca39908b1f3e54e6af7
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / service / NetworkModelServiceImpl.java
1 /*
2  * Copyright © 2016 AT&T 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 package org.opendaylight.transportpce.networkmodel.service;
9
10 import com.google.common.util.concurrent.ListenableFuture;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Optional;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 import java.util.stream.Collectors;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.transportpce.common.InstanceIdentifiers;
25 import org.opendaylight.transportpce.common.NetworkUtils;
26 import org.opendaylight.transportpce.common.mapping.PortMapping;
27 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
28 import org.opendaylight.transportpce.networkmodel.R2RLinkDiscovery;
29 import org.opendaylight.transportpce.networkmodel.dto.TopologyShard;
30 import org.opendaylight.transportpce.networkmodel.util.ClliNetwork;
31 import org.opendaylight.transportpce.networkmodel.util.LinkIdUtil;
32 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmNetwork;
33 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmOtnTopology;
34 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology;
35 import org.opendaylight.transportpce.networkmodel.util.TopologyUtils;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResult;
37 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResultBuilder;
38 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChanges;
39 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesKey;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.OpenroadmNodeVersion;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.nodes.NodeInfo;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Link1;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.TerminationPoint1;
47 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
48 import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTpBuilder;
49 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev210511.OtnLinkType;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkKey;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPoint;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.Uint32;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
71
72 public class NetworkModelServiceImpl implements NetworkModelService {
73
74     private static final Logger LOG = LoggerFactory.getLogger(NetworkModelServiceImpl.class);
75
76     private NetworkTransactionService networkTransactionService;
77     private final R2RLinkDiscovery linkDiscovery;
78     private final PortMapping portMapping;
79     private Map<String, TopologyShard> topologyShardMountedDevice;
80     private Map<String, TopologyShard> otnTopologyShardMountedDevice;
81     // Variables for creating and sending topology update notification
82     private final NotificationPublishService notificationPublishService;
83     private Map<TopologyChangesKey, TopologyChanges> topologyChanges;
84     private TopologyUpdateResult notification = null;
85
86     public NetworkModelServiceImpl(final NetworkTransactionService networkTransactionService,
87             final R2RLinkDiscovery linkDiscovery, PortMapping portMapping,
88             final NotificationPublishService notificationPublishService) {
89
90         this.networkTransactionService = networkTransactionService;
91         this.linkDiscovery = linkDiscovery;
92         this.portMapping = portMapping;
93         this.topologyShardMountedDevice = new HashMap<String, TopologyShard>();
94         this.otnTopologyShardMountedDevice = new HashMap<String, TopologyShard>();
95         this.notificationPublishService = notificationPublishService;
96         this.topologyChanges = new HashMap<TopologyChangesKey, TopologyChanges>();
97     }
98
99     public void init() {
100         LOG.info("init ...");
101     }
102
103     public void close() {
104     }
105
106     @Override
107     public void createOpenRoadmNode(String nodeId, String openRoadmVersion) {
108         try {
109             LOG.info("createOpenROADMNode: {} ", nodeId);
110
111             if (!portMapping.createMappingData(nodeId, openRoadmVersion)) {
112                 LOG.warn("Could not generate port mapping for {} skipping network model creation", nodeId);
113                 return;
114             }
115             NodeInfo nodeInfo = portMapping.getNode(nodeId).getNodeInfo();
116             // node creation in clli-network
117             Node clliNode = ClliNetwork.createNode(nodeId, nodeInfo);
118             InstanceIdentifier<Node> iiClliNode = InstanceIdentifier.builder(Networks.class)
119                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID)))
120                 .child(Node.class, clliNode.key())
121                 .build();
122             LOG.info("creating node in {}", NetworkUtils.CLLI_NETWORK_ID);
123             networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode);
124
125             // node creation in openroadm-network
126             Node openroadmNetworkNode = OpenRoadmNetwork.createNode(nodeId, nodeInfo);
127             InstanceIdentifier<Node> iiopenroadmNetworkNode = InstanceIdentifier.builder(Networks.class)
128                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)))
129                 .child(Node.class, openroadmNetworkNode.key())
130                 .build();
131             LOG.info("creating node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
132             networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode,
133                 openroadmNetworkNode);
134
135             // nodes/links creation in openroadm-topology
136             TopologyShard topologyShard = OpenRoadmTopology.createTopologyShard(portMapping.getNode(nodeId));
137             if (topologyShard != null) {
138                 this.topologyShardMountedDevice.put(nodeId, topologyShard);
139                 for (Node openRoadmTopologyNode : topologyShard.getNodes()) {
140                     LOG.info("creating node {} in {}", openRoadmTopologyNode.getNodeId().getValue(),
141                         NetworkUtils.OVERLAY_NETWORK_ID);
142                     InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(Networks.class)
143                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
144                         .child(Node.class, openRoadmTopologyNode.key())
145                         .build();
146                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode,
147                         openRoadmTopologyNode);
148                 }
149                 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
150                     LOG.info("creating link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
151                         NetworkUtils.OVERLAY_NETWORK_ID);
152                     InstanceIdentifier<Link> iiOpenRoadmTopologyLink = InstanceIdentifier.builder(Networks.class)
153                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
154                         .augmentation(Network1.class)
155                         .child(Link.class, openRoadmTopologyLink.key())
156                         .build();
157                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink,
158                         openRoadmTopologyLink);
159                 }
160             } else {
161                 LOG.error("Unable to create openroadm-topology shard for node {}!", nodeId);
162             }
163             // nodes/links creation in otn-topology
164             if (nodeInfo.getNodeType().getIntValue() == 2 && (nodeInfo.getOpenroadmVersion().getIntValue() != 1)) {
165                 createOpenRoadmOtnNode(nodeId);
166             }
167             networkTransactionService.commit().get();
168             // neighbour links through LLDP
169             if (nodeInfo.getNodeType().getIntValue() == 1) {
170                 this.linkDiscovery.readLLDP(new NodeId(nodeId), openRoadmVersion);
171             }
172             LOG.info("all nodes and links created");
173         } catch (InterruptedException | ExecutionException e) {
174             LOG.error("ERROR: ", e);
175         }
176     }
177
178     @Override
179     public void setOpenRoadmNodeStatus(String nodeId, NetconfNodeConnectionStatus.ConnectionStatus connectionStatus) {
180         LOG.info("setOpenROADMNodeStatus: {} {}", nodeId, connectionStatus.name());
181         /*
182           TODO: set connection status of the device in model,
183           TODO: so we don't need to keep it in memory (Set<String> currentMountedDevice)
184           TODO: unfortunately there is no connection status OpenROADM in network models
185           TODO: waiting for new model version
186          */
187     }
188
189     /*
190      @see org.opendaylight.transportpce.networkmodel.service.NetworkModelService# deleteOpenROADMnode(java.lang.String)
191      */
192
193     @Override
194     public boolean deleteOpenRoadmnode(String nodeId) {
195         try {
196             if (!this.portMapping.isNodeExist(nodeId)) {
197                 return false;
198             }
199             NodeKey nodeIdKey = new NodeKey(new NodeId(nodeId));
200
201             LOG.info("deleting node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
202             InstanceIdentifier<Node> iiopenroadmNetworkNode = InstanceIdentifier.builder(Networks.class)
203                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID)))
204                 .child(Node.class, nodeIdKey)
205                 .build();
206             this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode);
207
208             TopologyShard topologyShard = this.topologyShardMountedDevice.get(nodeId);
209             if (topologyShard != null) {
210                 for (Node openRoadmTopologyNode : topologyShard.getNodes()) {
211                     LOG.info("deleting node {} in {}", openRoadmTopologyNode.getNodeId().getValue(),
212                         NetworkUtils.OVERLAY_NETWORK_ID);
213                     InstanceIdentifier<Node> iiOpenRoadmTopologyNode = InstanceIdentifier.builder(Networks.class)
214                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
215                         .child(Node.class, openRoadmTopologyNode.key())
216                         .build();
217                     this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode);
218                 }
219                 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
220                     LOG.info("deleting link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
221                         NetworkUtils.OVERLAY_NETWORK_ID);
222                     InstanceIdentifier<Link> iiOpenRoadmTopologyLink = InstanceIdentifier.builder(Networks.class)
223                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
224                         .augmentation(Network1.class)
225                         .child(Link.class, openRoadmTopologyLink.key())
226                         .build();
227                     this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink);
228                 }
229             } else {
230                 LOG.warn("TopologyShard for node '{}' is not present", nodeId);
231             }
232             @Nullable
233             OpenroadmNodeVersion deviceVersion = this.portMapping.getNode(nodeId).getNodeInfo().getOpenroadmVersion();
234             @Nullable
235             NodeTypes nodeType = this.portMapping.getNode(nodeId).getNodeInfo().getNodeType();
236             if (nodeType.getIntValue() == 2 && deviceVersion.getIntValue() != 1) {
237                 TopologyShard otnTopologyShard = this.otnTopologyShardMountedDevice.get(nodeId);
238                 if (otnTopologyShard != null) {
239                     LOG.info("suppression de otnTopologyShard = {}", otnTopologyShard.toString());
240                     for (Node otnTopologyNode : otnTopologyShard.getNodes()) {
241                         LOG.info("deleting node {} in {}", otnTopologyNode.getNodeId().getValue(),
242                             NetworkUtils.OTN_NETWORK_ID);
243                         InstanceIdentifier<Node> iiotnTopologyNode = InstanceIdentifier.builder(Networks.class)
244                             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
245                             .child(Node.class, otnTopologyNode.key())
246                             .build();
247                         this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiotnTopologyNode);
248                     }
249                     for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
250                         LOG.info("deleting link {} in {}", otnTopologyLink.getLinkId().getValue(),
251                             NetworkUtils.OTN_NETWORK_ID);
252                         InstanceIdentifier<Link> iiotnTopologyLink = InstanceIdentifier.builder(Networks.class)
253                             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
254                             .augmentation(Network1.class)
255                             .child(Link.class, otnTopologyLink.key())
256                             .build();
257                         this.networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiotnTopologyLink);
258                     }
259                 }
260             }
261
262             LOG.info("deleteOpenROADMnode: {} version {}", nodeId, deviceVersion.getName());
263             this.portMapping.deletePortMappingNode(nodeId);
264
265             this.networkTransactionService.commit().get(1, TimeUnit.SECONDS);
266             LOG.info("all nodes and links deleted ! ");
267         } catch (InterruptedException | ExecutionException | TimeoutException e) {
268             LOG.error("Error when trying to delete node : {}", nodeId, e);
269             return false;
270         }
271         return true;
272     }
273
274     @Override
275     public void updateOpenRoadmTopologies(String nodeId, Mapping mapping) {
276         LOG.info("update OpenRoadm topologies after change update from: {} ", nodeId);
277         this.topologyChanges.clear();
278         Network openroadmTopology = null;
279         Network otnTopology = null;
280         Map<LinkKey, Link> openroadmTopologyLinks = null;
281         Map<LinkKey, Link> otnTopologyLinks = null;
282         try {
283             openroadmTopology = this.networkTransactionService
284                 .read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers.OVERLAY_NETWORK_II)
285                 .get().get();
286             if (openroadmTopology.augmentation(Network1.class) != null) {
287                 openroadmTopologyLinks = openroadmTopology.augmentation(Network1.class).getLink();
288             }
289             otnTopology = this.networkTransactionService
290                 .read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers.OTN_NETWORK_II)
291                 .get().get();
292             if (otnTopology.augmentation(Network1.class) != null) {
293                 otnTopologyLinks = otnTopology.augmentation(Network1.class).getLink();
294             }
295         } catch (InterruptedException | ExecutionException e) {
296             LOG.error("Error when trying to update node : {}", nodeId, e);
297         }
298         if (openroadmTopology == null || otnTopology == null) {
299             LOG.warn("Error getting topologies from datastore");
300             return;
301         }
302         String abstractNodeid = String.join("-", nodeId, mapping.getLogicalConnectionPoint().split("-")[0]);
303         // nodes/links update in openroadm-topology
304         if (openroadmTopology.getNode() != null) {
305             TopologyShard topologyShard = TopologyUtils.updateTopologyShard(abstractNodeid, mapping,
306                 openroadmTopology.getNode(), openroadmTopologyLinks);
307             if (topologyShard.getLinks() != null) {
308                 for (Link link : topologyShard.getLinks()) {
309                     LOG.info("updating links {} in {}", link.getLinkId().getValue(),
310                         NetworkUtils.OVERLAY_NETWORK_ID);
311                     InstanceIdentifier<Link> iiTopologyLink = InstanceIdentifier.builder(Networks.class)
312                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
313                         .augmentation(Network1.class)
314                         .child(Link.class, link.key())
315                         .build();
316                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyLink, link);
317                 }
318             }
319             if (topologyShard.getTps() != null) {
320                 for (TerminationPoint tp : topologyShard.getTps()) {
321                     LOG.info("updating TP {} in openroadm-topology", tp.getTpId().getValue());
322                     InstanceIdentifier<TerminationPoint> iiTopologyTp = InstanceIdentifier.builder(Networks.class)
323                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
324                         .child(Node.class, new NodeKey(new NodeId(abstractNodeid)))
325                         .augmentation(Node1.class)
326                         .child(TerminationPoint.class, new TerminationPointKey(tp.getTpId()))
327                         .build();
328                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyTp, tp);
329                     TopologyChanges tc = new TopologyChangesBuilder()
330                         .withKey(new TopologyChangesKey(abstractNodeid, tp.getTpId().getValue()))
331                         .setNodeId(abstractNodeid)
332                         .setTpId(tp.getTpId().getValue())
333                         .setState(tp.augmentation(
334                             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1
335                                 .class).getOperationalState())
336                         .build();
337                     if (!this.topologyChanges.containsKey(tc.key())) {
338                         this.topologyChanges.put(tc.key(), tc);
339                     }
340                 }
341             }
342         }
343         // nodes/links update in otn-topology
344         if (otnTopology.getNode() != null
345             && otnTopology.getNode().containsKey(new NodeKey(new NodeId(abstractNodeid)))) {
346             TopologyShard otnShard = TopologyUtils.updateTopologyShard(abstractNodeid, mapping,
347                 otnTopology.getNode(), otnTopologyLinks);
348             if (otnShard.getLinks() != null) {
349                 for (Link link : otnShard.getLinks()) {
350                     LOG.info("updating links {} in {}", link.getLinkId().getValue(),
351                         NetworkUtils.OVERLAY_NETWORK_ID);
352                     InstanceIdentifier<Link> iiTopologyLink = InstanceIdentifier.builder(Networks.class)
353                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
354                         .augmentation(Network1.class)
355                         .child(Link.class, link.key())
356                         .build();
357                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyLink, link);
358                 }
359             }
360             if (otnShard.getTps() != null) {
361                 for (TerminationPoint tp : otnShard.getTps()) {
362                     LOG.info("updating TP {} in otn-topology", tp.getTpId().getValue());
363                     InstanceIdentifier<TerminationPoint> iiTopologyTp = InstanceIdentifier.builder(Networks.class)
364                         .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
365                         .child(Node.class, new NodeKey(new NodeId(abstractNodeid)))
366                         .augmentation(Node1.class)
367                         .child(TerminationPoint.class, new TerminationPointKey(tp.getTpId()))
368                         .build();
369                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyTp, tp);
370                     TopologyChanges tc = new TopologyChangesBuilder()
371                         .withKey(new TopologyChangesKey(abstractNodeid, tp.getTpId().getValue()))
372                         .setNodeId(abstractNodeid)
373                         .setTpId(tp.getTpId().getValue())
374                         .setState(tp.augmentation(
375                             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1
376                                 .class).getOperationalState())
377                         .build();
378                     if (!this.topologyChanges.containsKey(tc.key())) {
379                         this.topologyChanges.put(tc.key(), tc);
380                     }
381                 }
382             }
383         }
384         // commit datastore updates
385         try {
386             networkTransactionService.commit().get();
387             sendNotification();
388         } catch (InterruptedException | ExecutionException e) {
389             LOG.error("Error updating openroadm-topology", e);
390         }
391     }
392
393     @Override
394     public void createOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
395         TopologyShard otnTopologyShard;
396         switch (linkType) {
397             case OTU4:
398             case OTUC4:
399                 otnTopologyShard = OpenRoadmOtnTopology.createOtnLinks(nodeA, tpA, nodeZ, tpZ, linkType);
400                 break;
401             case ODTU4:
402             case ODUC4:
403                 List<LinkId> linkIdList = new ArrayList<>();
404                 String prefix;
405                 if (OtnLinkType.ODTU4.equals(linkType)) {
406                     prefix = OtnLinkType.OTU4.getName();
407                 } else {
408                     prefix = OtnLinkType.OTUC4.getName();
409                 }
410                 linkIdList.add(LinkIdUtil.buildOtnLinkId(convertNetconfNodeIdToTopoNodeId(nodeA, tpA), tpA,
411                     convertNetconfNodeIdToTopoNodeId(nodeZ, tpZ), tpZ, prefix));
412                 linkIdList.add(LinkIdUtil.buildOtnLinkId(convertNetconfNodeIdToTopoNodeId(nodeZ, tpZ), tpZ,
413                     convertNetconfNodeIdToTopoNodeId(nodeA, tpA), tpA, prefix));
414                 List<Link> supportedOtu4links = getOtnLinks(linkIdList);
415                 List<TerminationPoint> tps = getOtnNodeTps(convertNetconfNodeIdToTopoNodeId(nodeA, tpA), tpA,
416                     convertNetconfNodeIdToTopoNodeId(nodeZ, tpZ), tpZ);
417                 otnTopologyShard = OpenRoadmOtnTopology.createOtnLinks(supportedOtu4links, tps, linkType);
418                 break;
419             default:
420                 LOG.error("unknown otn link type {}", linkType);
421                 otnTopologyShard = new TopologyShard(null, null);
422         }
423         if (otnTopologyShard.getLinks() != null) {
424             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
425                 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
426                     NetworkUtils.OVERLAY_NETWORK_ID);
427                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
428                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
429                     .augmentation(Network1.class)
430                     .child(Link.class, otnTopologyLink.key())
431                     .build();
432                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
433             }
434         }
435         if (otnTopologyShard.getTps() != null) {
436             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
437                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
438                 List<SupportingTerminationPoint> supportingTerminationPoint =
439                     new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
440                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
441                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
442                     .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
443                     .augmentation(Node1.class)
444                     .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
445                     .build();
446                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
447             }
448         }
449         try {
450             networkTransactionService.commit().get();
451         } catch (InterruptedException | ExecutionException e) {
452             LOG.error("Error adding OTN links in otn-topology", e);
453         }
454         LOG.info("OTN links created");
455     }
456
457     @Override
458     public void deleteOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
459         TopologyShard otnTopologyShard;
460         String nodeTopoA = new StringBuilder(nodeA).append("-").append(tpA.split("-")[0]).toString();
461         String nodeTopoZ = new StringBuilder(nodeZ).append("-").append(tpZ.split("-")[0]).toString();
462         List<Link> otuLinks;
463         List<LinkId> linkIdList = new ArrayList<>();
464         String prefix;
465         switch (linkType) {
466             case OTU4:
467             case OTUC4:
468                 if (OtnLinkType.OTU4.equals(linkType)) {
469                     prefix = OtnLinkType.OTU4.getName();
470                 } else {
471                     prefix = OtnLinkType.OTUC4.getName();
472                 }
473                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, prefix));
474                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, prefix));
475                 otuLinks = getOtnLinks(linkIdList);
476                 if (checkLinks(otuLinks)) {
477                     deleteLinks(otuLinks);
478                 } else {
479                     LOG.error("Error deleting OTU4 links");
480                 }
481                 otnTopologyShard = new TopologyShard(null, null);
482                 break;
483             case ODTU4:
484             case ODUC4:
485                 String prefix2;
486                 if (OtnLinkType.ODTU4.equals(linkType)) {
487                     prefix = OtnLinkType.ODTU4.getName();
488                     prefix2 = OtnLinkType.OTU4.getName();
489                 } else {
490                     prefix = OtnLinkType.ODUC4.getName();
491                     prefix2 = OtnLinkType.OTUC4.getName();
492                 }
493                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, prefix));
494                 linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, prefix));
495                 List<Link> oduLinks = getOtnLinks(linkIdList);
496                 List<TerminationPoint> tps = getOtnNodeTps(nodeTopoA, tpA, nodeTopoZ, tpZ);
497                 if (checkLinks(oduLinks) && checkTerminationPoints(tps)) {
498                     deleteLinks(oduLinks);
499                     linkIdList.clear();
500                     linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, tpA, nodeTopoZ, tpZ, prefix2));
501                     linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, tpZ, nodeTopoA, tpA, prefix2));
502                     otuLinks = getOtnLinks(linkIdList);
503                     otnTopologyShard = OpenRoadmOtnTopology.deleteOtnLinks(otuLinks, tps, linkType);
504                 } else {
505                     LOG.error("Error deleting ODU4 links");
506                     otnTopologyShard = new TopologyShard(null, null);
507                 }
508                 break;
509             default:
510                 LOG.error("unknown otn link type {}", linkType);
511                 otnTopologyShard = new TopologyShard(null, null);
512         }
513         if (otnTopologyShard.getLinks() != null) {
514             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
515                 LOG.info("deleting and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
516                     NetworkUtils.OVERLAY_NETWORK_ID);
517                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
518                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
519                     .augmentation(Network1.class)
520                     .child(Link.class, otnTopologyLink.key())
521                     .build();
522                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
523             }
524         }
525         if (otnTopologyShard.getTps() != null) {
526             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
527                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
528                 List<SupportingTerminationPoint> supportingTerminationPoint =
529                     new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
530                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
531                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
532                     .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
533                     .augmentation(Node1.class)
534                     .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
535                     .build();
536                 networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
537             }
538         }
539         try {
540             networkTransactionService.commit().get();
541         } catch (InterruptedException | ExecutionException e) {
542             LOG.error("Error deleting OTN links in otn-topology", e);
543         }
544         LOG.info("OTN links deletion terminated");
545     }
546
547     @Override
548     public void updateOtnLinks(
549         org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link
550             notifLink, Uint32 serviceRate, Short tribPortNb, Short minTribSoltNb, Short maxTribSlotNb,
551             boolean isDeletion) {
552
553         LinkTp atermination = new LinkTpBuilder()
554             .setNodeId(notifLink.getATermination().getNodeId())
555             .setTpId(notifLink.getATermination().getTpId())
556             .build();
557         LinkTp ztermination = new LinkTpBuilder()
558             .setNodeId(notifLink.getZTermination().getNodeId())
559             .setTpId(notifLink.getZTermination().getTpId())
560             .build();
561         List<LinkTp> linkTerminations = new ArrayList<>();
562         linkTerminations.add(atermination);
563         linkTerminations.add(ztermination);
564
565         List<Link> supportedOdu4Links = getSupportingOdu4Links(linkTerminations, serviceRate);
566         List<TerminationPoint> tps = getOtnNodeTps(linkTerminations);
567         TopologyShard otnTopologyShard;
568         otnTopologyShard = OpenRoadmOtnTopology.updateOtnLinks(supportedOdu4Links, tps, serviceRate, tribPortNb,
569             minTribSoltNb, maxTribSlotNb, isDeletion);
570         if (otnTopologyShard.getLinks() != null) {
571             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
572                 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
573                     NetworkUtils.OVERLAY_NETWORK_ID);
574                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
575                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
576                     .augmentation(Network1.class)
577                     .child(Link.class, new LinkKey(new LinkId(otnTopologyLink.getLinkId().getValue())))
578                     .build();
579                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
580             }
581         }
582         if (otnTopologyShard.getTps() != null) {
583             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
584                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
585                 List<SupportingTerminationPoint> supportingTerminationPoint =
586                     new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
587                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
588                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
589                     .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
590                     .augmentation(Node1.class)
591                     .child(TerminationPoint.class, new TerminationPointKey(new TpId(otnTopologyTp.getTpId()
592                         .getValue())))
593                     .build();
594                 if (isDeletion) {
595                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
596                 } else {
597                     networkTransactionService.put(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
598                 }
599             }
600         }
601         try {
602             networkTransactionService.commit().get();
603         } catch (InterruptedException | ExecutionException e) {
604             LOG.error("Error updating OTN links in otn-topology", e);
605         }
606     }
607
608     @Override
609     public void updateOtnLinks(
610         org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210915.renderer.rpc.result.sp.Link
611             notifLink, List<String> suppLinks, boolean isDeletion) {
612
613         List<LinkId> linkIdList = new ArrayList<>();
614         if (notifLink != null) {
615             String nodeTopoA = convertNetconfNodeIdToTopoNodeId(notifLink.getATermination().getNodeId(),
616                 notifLink.getATermination().getTpId());
617             String nodeTopoZ = convertNetconfNodeIdToTopoNodeId(notifLink.getZTermination().getNodeId(),
618                 notifLink.getZTermination().getTpId());
619             linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoA, notifLink.getATermination().getTpId(),
620                 nodeTopoZ, notifLink.getZTermination().getTpId(), OtnLinkType.OTU4.getName()));
621             linkIdList.add(LinkIdUtil.buildOtnLinkId(nodeTopoZ, notifLink.getZTermination().getTpId(),
622                 nodeTopoA, notifLink.getATermination().getTpId(), OtnLinkType.OTU4.getName()));
623         } else if (suppLinks != null) {
624             suppLinks.forEach(lk -> linkIdList.add(new LinkId(lk)));
625         } else {
626             LOG.error("Impossible to determine supported otn links without correct input data");
627         }
628         List<Link> supportedOtu4links = getOtnLinks(linkIdList);
629
630         TopologyShard otnTopologyShard = OpenRoadmOtnTopology.updateOtnLinks(supportedOtu4links, isDeletion);
631         if (otnTopologyShard.getLinks() != null) {
632             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
633                 LOG.info("creating and updating otn links {} in {}", otnTopologyLink.getLinkId().getValue(),
634                     NetworkUtils.OVERLAY_NETWORK_ID);
635                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
636                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
637                     .augmentation(Network1.class)
638                     .child(Link.class, otnTopologyLink.key())
639                     .build();
640                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
641             }
642         }
643         try {
644             networkTransactionService.commit().get();
645         } catch (InterruptedException | ExecutionException e) {
646             LOG.error("Error adding OTN links in otn-topology", e);
647         }
648         LOG.info("OTN links updated");
649     }
650
651     private List<Link> getOtnLinks(List<LinkId> linkIds) {
652         List<Link> links = new ArrayList<>();
653         for (LinkId linkId : linkIds) {
654             InstanceIdentifier<Link> iiLink = InstanceIdentifier.builder(Networks.class)
655                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
656                 .augmentation(Network1.class)
657                 .child(Link.class, new LinkKey(linkId))
658                 .build();
659             ListenableFuture<Optional<Link>> linkOptLf = networkTransactionService
660                 .read(LogicalDatastoreType.CONFIGURATION, iiLink);
661             if (linkOptLf.isDone()) {
662                 try {
663                     if (linkOptLf.get().isPresent()) {
664                         links.add(linkOptLf.get().get());
665                     }
666                 } catch (InterruptedException | ExecutionException e) {
667                     LOG.error("Error retreiving OTN links from otn-topology", e);
668                 }
669             } else {
670                 LOG.error("Error retreiving link {} from otn-topology", linkId.getValue());
671             }
672         }
673         return links;
674     }
675
676     private boolean checkLinks(List<Link> links) {
677         if (links.isEmpty()) {
678             return false;
679         }
680         for (Link link : links) {
681             if (link.augmentation(Link1.class) != null
682                     && !link.augmentation(Link1.class).getUsedBandwidth().equals(Uint32.valueOf(0))) {
683                 return false;
684             }
685         }
686         return true;
687     }
688
689     private boolean checkTerminationPoints(List<TerminationPoint> tps) {
690         if (tps.isEmpty()) {
691             return false;
692         }
693         for (TerminationPoint tp : tps) {
694             if (tp.augmentation(TerminationPoint1.class) != null && tp.augmentation(TerminationPoint1.class)
695                     .getXpdrTpPortConnectionAttributes().getTsPool() != null && tp.augmentation(TerminationPoint1.class)
696                     .getXpdrTpPortConnectionAttributes().getTsPool().size() != 80) {
697                 return false;
698             }
699         }
700         return true;
701     }
702
703     private List<TerminationPoint> getOtnNodeTps(String nodeTopoA, String tpA, String nodeTopoZ, String tpZ) {
704         List<TerminationPoint> tps = new ArrayList<>();
705         InstanceIdentifier<TerminationPoint> iiTpA = InstanceIdentifier.builder(Networks.class)
706             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
707             .child(Node.class, new NodeKey(new NodeId(nodeTopoA)))
708             .augmentation(Node1.class)
709             .child(TerminationPoint.class, new TerminationPointKey(new TpId(tpA)))
710             .build();
711         Optional<TerminationPoint> tpAOpt = Optional.empty();
712         InstanceIdentifier<TerminationPoint> iiTpZ = InstanceIdentifier.builder(Networks.class)
713             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
714             .child(Node.class, new NodeKey(new NodeId(nodeTopoZ)))
715             .augmentation(Node1.class)
716             .child(TerminationPoint.class, new TerminationPointKey(new TpId(tpZ)))
717             .build();
718         Optional<TerminationPoint> tpZOpt = Optional.empty();
719
720         if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).isDone()
721                 && networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).isDone()) {
722             try {
723                 tpAOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).get();
724                 tpZOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).get();
725             } catch (InterruptedException | ExecutionException e) {
726                 LOG.error("Error retreiving tp {} of node {} or tp {} from node {} from otn-topology", tpA, nodeTopoA,
727                     tpZ, nodeTopoZ, e);
728             }
729         } else {
730             LOG.error("error getting node termination points from the datastore");
731         }
732
733         if (tpAOpt.isPresent() && tpZOpt.isPresent()) {
734             tps.add(tpAOpt.get());
735             tps.add(tpZOpt.get());
736         }
737         return tps;
738     }
739
740     private List<TerminationPoint> getOtnNodeTps(List<LinkTp> linkTerminations) {
741         List<TerminationPoint> tps = new ArrayList<>();
742         for (LinkTp linkTp : linkTerminations) {
743             String tp = linkTp.getTpId();
744             String nodeId = new StringBuilder(linkTp.getNodeId()).append("-")
745                 .append(tp.split("-")[0]).toString();
746             InstanceIdentifier<TerminationPoint> iiTp = InstanceIdentifier.builder(Networks.class)
747                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
748                 .child(Node.class, new NodeKey(new NodeId(nodeId)))
749                 .augmentation(Node1.class)
750                 .child(TerminationPoint.class, new TerminationPointKey(new TpId(tp)))
751                 .build();
752             Optional<TerminationPoint> tpOpt;
753             if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTp).isDone()) {
754                 try {
755                     tpOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTp).get();
756                     if (tpOpt.isPresent()) {
757                         tps.add(tpOpt.get());
758                     }
759                 } catch (InterruptedException | ExecutionException e) {
760                     LOG.error("Error retreiving tp {} of node {} from otn-topology", tp, nodeId, e);
761                 }
762             } else {
763                 LOG.error("error getting node termination points from the datastore");
764             }
765         }
766         if (tps.isEmpty()) {
767             LOG.warn("returning null");
768             return null;
769         } else {
770             LOG.info("returning tps = {}", tps.toString());
771             return tps;
772         }
773     }
774
775     private void deleteLinks(List<Link> links) {
776         for (Link otnTopologyLink : links) {
777             LOG.info("deleting link {} from {}", otnTopologyLink.getLinkId().getValue(),
778                 NetworkUtils.OVERLAY_NETWORK_ID);
779             InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
780                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
781                 .augmentation(Network1.class)
782                 .child(Link.class, otnTopologyLink.key())
783                 .build();
784             networkTransactionService.delete(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink);
785         }
786         try {
787             networkTransactionService.commit().get();
788         } catch (InterruptedException | ExecutionException e) {
789             LOG.error("Error deleting OTN links from otn-topology", e);
790         }
791     }
792
793     private List<Link> getSupportingOdu4Links(List<LinkTp> nodesTopoTps, Uint32 serviceRate) {
794         InstanceIdentifier<Network1> iiOtnTopologyLinks = InstanceIdentifier.builder(Networks.class)
795             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
796             .augmentation(Network1.class)
797             .build();
798         ListenableFuture<Optional<Network1>> netw1Fl = networkTransactionService
799             .read(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLinks);
800         Optional<Network1> netw1Opt = Optional.empty();
801         if (netw1Fl.isDone()) {
802             try {
803                 netw1Opt = netw1Fl.get();
804             } catch (InterruptedException | ExecutionException e) {
805                 LOG.error("Error retreiving list of links from otn-topology", e);
806             }
807         }
808         List<Link> odu4links = null;
809         if (netw1Opt.isPresent() && netw1Opt.get().getLink() != null) {
810             odu4links = netw1Opt
811                 .get()
812                 .nonnullLink().values()
813                 .stream().filter(lk -> lk.getLinkId().getValue()
814                     .startsWith(Uint32.valueOf(100).equals(serviceRate) ? "ODUC4" : "ODTU4"))
815                 .collect(Collectors.toList());
816         }
817         if (odu4links == null) {
818             return null;
819         }
820         List<Link> links = new ArrayList<>();
821         for (LinkTp linkTp : nodesTopoTps) {
822             String tp = linkTp.getTpId();
823             String nodeId = new StringBuilder(linkTp.getNodeId()).append("-")
824                 .append(tp.split("-")[0]).toString();
825             Link slink = odu4links.stream().filter(lk -> lk.getSource().getSourceNode().getValue()
826                 .equals(nodeId) && lk.getSource().getSourceTp().getValue().equals(tp)).findFirst().get();
827             if (!links.contains(slink)) {
828                 links.add(slink);
829             }
830             Link dlink = odu4links.stream().filter(lk -> lk.getDestination().getDestNode().getValue()
831                 .equals(nodeId) && lk.getDestination().getDestTp().getValue().equals(tp)).findFirst().get();
832             if (!links.contains(dlink)) {
833                 links.add(dlink);
834             }
835         }
836         LOG.debug("odu4oduC4links = {}", links);
837         return links;
838     }
839
840     private void createOpenRoadmOtnNode(String nodeId) {
841         TopologyShard otnTopologyShard = OpenRoadmOtnTopology.createTopologyShard(portMapping.getNode(nodeId));
842         if (otnTopologyShard != null) {
843             this.otnTopologyShardMountedDevice.put(nodeId, otnTopologyShard);
844             for (Node otnTopologyNode : otnTopologyShard.getNodes()) {
845                 LOG.info("creating otn node {} in {}", otnTopologyNode.getNodeId().getValue(),
846                     NetworkUtils.OTN_NETWORK_ID);
847                 InstanceIdentifier<Node> iiOtnTopologyNode = InstanceIdentifier.builder(Networks.class)
848                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
849                     .child(Node.class, otnTopologyNode.key())
850                     .build();
851                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyNode, otnTopologyNode);
852             }
853             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
854                 LOG.info("creating otn link {} in {}", otnTopologyLink.getLinkId().getValue(),
855                     NetworkUtils.OVERLAY_NETWORK_ID);
856                 InstanceIdentifier<Link> iiOtnTopologyLink = InstanceIdentifier.builder(Networks.class)
857                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
858                     .augmentation(Network1.class)
859                     .child(Link.class, otnTopologyLink.key())
860                     .build();
861                 networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
862             }
863         } else {
864             LOG.error("Unable to create OTN topology shard for node {}!", nodeId);
865         }
866     }
867
868     private String convertNetconfNodeIdToTopoNodeId(String nodeId, String tpId) {
869         return new StringBuilder(nodeId).append("-").append(tpId.split("-")[0]).toString();
870     }
871
872     @SuppressFBWarnings(
873             value = "UPM_UNCALLED_PRIVATE_METHOD",
874             justification = "false positive, this method is used by public updateOpenRoadmNetworkTopology")
875     private void sendNotification() {
876         if (topologyChanges.isEmpty()) {
877             LOG.warn("Empty Topology Change List. No updates in topology");
878             return;
879         }
880         this.notification = new TopologyUpdateResultBuilder()
881             .setTopologyChanges(topologyChanges)
882             .build();
883         try {
884             notificationPublishService.putNotification(this.notification);
885         } catch (InterruptedException e) {
886             LOG.error("Notification offer rejected. Error={}", e.getMessage());
887         }
888     }
889 }