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