Move otn link update from renderer to SH
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / service / NetworkModelServiceImpl.java
index 57e398eb08d965ee0a947e07bf4a1a71847e8652..fb8059c2ff3ed08225ebe2dd24f4d80fe4bd415a 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.transportpce.networkmodel.service;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -18,7 +19,9 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.transportpce.common.InstanceIdentifiers;
 import org.opendaylight.transportpce.common.NetworkUtils;
 import org.opendaylight.transportpce.common.mapping.PortMapping;
 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
@@ -29,12 +32,21 @@ import org.opendaylight.transportpce.networkmodel.util.LinkIdUtil;
 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmNetwork;
 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmOtnTopology;
 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology;
-import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev200429.network.nodes.NodeInfo;
-import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev200429.network.nodes.NodeInfo.OpenroadmVersion;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.NodeTypes;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.Link1;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev181130.TerminationPoint1;
-import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev200129.OtnLinkType;
+import org.opendaylight.transportpce.networkmodel.util.TopologyUtils;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResult;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.TopologyUpdateResultBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChanges;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.TopologyChangesKey;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.OpenroadmNodeVersion;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.mapping.Mapping;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.network.nodes.NodeInfo;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.Link1;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev200529.TerminationPoint1;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTp;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev210618.link.tp.LinkTpBuilder;
+import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev210511.OtnLinkType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
@@ -50,32 +62,38 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.top
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.LinkKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.termination.point.SupportingTerminationPoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.Uint32;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 public class NetworkModelServiceImpl implements NetworkModelService {
 
     private static final Logger LOG = LoggerFactory.getLogger(NetworkModelServiceImpl.class);
-    private static final boolean CREATE_MISSING_PARENTS = true;
 
     private NetworkTransactionService networkTransactionService;
     private final R2RLinkDiscovery linkDiscovery;
     private final PortMapping portMapping;
     private Map<String, TopologyShard> topologyShardMountedDevice;
     private Map<String, TopologyShard> otnTopologyShardMountedDevice;
+    // Variables for creating and sending topology update notification
+    private final NotificationPublishService notificationPublishService;
+    private Map<TopologyChangesKey, TopologyChanges> topologyChanges;
+    private TopologyUpdateResult notification = null;
 
     public NetworkModelServiceImpl(final NetworkTransactionService networkTransactionService,
-        final R2RLinkDiscovery linkDiscovery, PortMapping portMapping) {
+            final R2RLinkDiscovery linkDiscovery, PortMapping portMapping,
+            final NotificationPublishService notificationPublishService) {
 
         this.networkTransactionService = networkTransactionService;
         this.linkDiscovery = linkDiscovery;
         this.portMapping = portMapping;
         this.topologyShardMountedDevice = new HashMap<String, TopologyShard>();
         this.otnTopologyShardMountedDevice = new HashMap<String, TopologyShard>();
+        this.notificationPublishService = notificationPublishService;
+        this.topologyChanges = new HashMap<TopologyChangesKey, TopologyChanges>();
     }
 
     public void init() {
@@ -95,9 +113,6 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                 return;
             }
             NodeInfo nodeInfo = portMapping.getNode(nodeId).getNodeInfo();
-            if (nodeInfo.getNodeType().getIntValue() == 1) {
-                this.linkDiscovery.readLLDP(new NodeId(nodeId), openRoadmVersion);
-            }
             // node creation in clli-network
             Node clliNode = ClliNetwork.createNode(nodeId, nodeInfo);
             InstanceIdentifier<Node> iiClliNode = InstanceIdentifier.builder(Networks.class)
@@ -105,8 +120,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                 .child(Node.class, clliNode.key())
                 .build();
             LOG.info("creating node in {}", NetworkUtils.CLLI_NETWORK_ID);
-            networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode,
-                CREATE_MISSING_PARENTS);
+            networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiClliNode, clliNode);
 
             // node creation in openroadm-network
             Node openroadmNetworkNode = OpenRoadmNetwork.createNode(nodeId, nodeInfo);
@@ -116,7 +130,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                 .build();
             LOG.info("creating node in {}", NetworkUtils.UNDERLAY_NETWORK_ID);
             networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiopenroadmNetworkNode,
-                openroadmNetworkNode, CREATE_MISSING_PARENTS);
+                openroadmNetworkNode);
 
             // nodes/links creation in openroadm-topology
             TopologyShard topologyShard = OpenRoadmTopology.createTopologyShard(portMapping.getNode(nodeId));
@@ -130,7 +144,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                         .child(Node.class, openRoadmTopologyNode.key())
                         .build();
                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyNode,
-                        openRoadmTopologyNode, CREATE_MISSING_PARENTS);
+                        openRoadmTopologyNode);
                 }
                 for (Link openRoadmTopologyLink : topologyShard.getLinks()) {
                     LOG.info("creating link {} in {}", openRoadmTopologyLink.getLinkId().getValue(),
@@ -141,17 +155,20 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                         .child(Link.class, openRoadmTopologyLink.key())
                         .build();
                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOpenRoadmTopologyLink,
-                        openRoadmTopologyLink, CREATE_MISSING_PARENTS);
+                        openRoadmTopologyLink);
                 }
             } else {
                 LOG.error("Unable to create openroadm-topology shard for node {}!", nodeId);
             }
-
             // nodes/links creation in otn-topology
             if (nodeInfo.getNodeType().getIntValue() == 2 && (nodeInfo.getOpenroadmVersion().getIntValue() != 1)) {
                 createOpenRoadmOtnNode(nodeId);
             }
             networkTransactionService.commit().get();
+            // neighbour links through LLDP
+            if (nodeInfo.getNodeType().getIntValue() == 1) {
+                this.linkDiscovery.readLLDP(new NodeId(nodeId), openRoadmVersion);
+            }
             LOG.info("all nodes and links created");
         } catch (InterruptedException | ExecutionException e) {
             LOG.error("ERROR: ", e);
@@ -210,7 +227,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                 LOG.warn("TopologyShard for node '{}' is not present", nodeId);
             }
             @Nullable
-            OpenroadmVersion deviceVersion = this.portMapping.getNode(nodeId).getNodeInfo().getOpenroadmVersion();
+            OpenroadmNodeVersion deviceVersion = this.portMapping.getNode(nodeId).getNodeInfo().getOpenroadmVersion();
             @Nullable
             NodeTypes nodeType = this.portMapping.getNode(nodeId).getNodeInfo().getNodeType();
             if (nodeType.getIntValue() == 2 && deviceVersion.getIntValue() != 1) {
@@ -249,6 +266,125 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         }
     }
 
+    @Override
+    public void updateOpenRoadmTopologies(String nodeId, Mapping mapping) {
+        LOG.info("update OpenRoadm topologies after change update from: {} ", nodeId);
+        this.topologyChanges.clear();
+        Network openroadmTopology = null;
+        Network otnTopology = null;
+        Map<LinkKey, Link> openroadmTopologyLinks = null;
+        Map<LinkKey, Link> otnTopologyLinks = null;
+        try {
+            openroadmTopology = this.networkTransactionService
+                .read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers.OVERLAY_NETWORK_II)
+                .get().get();
+            if (openroadmTopology.augmentation(Network1.class) != null) {
+                openroadmTopologyLinks = openroadmTopology.augmentation(Network1.class).getLink();
+            }
+            otnTopology = this.networkTransactionService
+                .read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers.OTN_NETWORK_II)
+                .get().get();
+            if (otnTopology.augmentation(Network1.class) != null) {
+                otnTopologyLinks = otnTopology.augmentation(Network1.class).getLink();
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error when trying to update node : {}", nodeId, e);
+        }
+        if (openroadmTopology == null || otnTopology == null) {
+            LOG.warn("Error getting topologies from datastore");
+            return;
+        }
+        String abstractNodeid = String.join("-", nodeId, mapping.getLogicalConnectionPoint().split("-")[0]);
+        // nodes/links update in openroadm-topology
+        if (openroadmTopology.getNode() != null) {
+            TopologyShard topologyShard = TopologyUtils.updateTopologyShard(abstractNodeid, mapping,
+                openroadmTopology.getNode(), openroadmTopologyLinks);
+            if (topologyShard.getLinks() != null) {
+                for (Link link : topologyShard.getLinks()) {
+                    LOG.info("updating links {} in {}", link.getLinkId().getValue(),
+                        NetworkUtils.OVERLAY_NETWORK_ID);
+                    InstanceIdentifier<Link> iiTopologyLink = InstanceIdentifier.builder(Networks.class)
+                        .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                        .augmentation(Network1.class)
+                        .child(Link.class, link.key())
+                        .build();
+                    networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyLink, link);
+                }
+            }
+            if (topologyShard.getTps() != null) {
+                for (TerminationPoint tp : topologyShard.getTps()) {
+                    LOG.info("updating TP {} in openroadm-topology", tp.getTpId().getValue());
+                    InstanceIdentifier<TerminationPoint> iiTopologyTp = InstanceIdentifier.builder(Networks.class)
+                        .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)))
+                        .child(Node.class, new NodeKey(new NodeId(abstractNodeid)))
+                        .augmentation(Node1.class)
+                        .child(TerminationPoint.class, new TerminationPointKey(tp.getTpId()))
+                        .build();
+                    networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyTp, tp);
+                    TopologyChanges tc = new TopologyChangesBuilder()
+                        .withKey(new TopologyChangesKey(abstractNodeid, tp.getTpId().getValue()))
+                        .setNodeId(abstractNodeid)
+                        .setTpId(tp.getTpId().getValue())
+                        .setState(tp.augmentation(
+                            org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1
+                                .class).getOperationalState())
+                        .build();
+                    if (!this.topologyChanges.containsKey(tc.key())) {
+                        this.topologyChanges.put(tc.key(), tc);
+                    }
+                }
+            }
+        }
+        // nodes/links update in otn-topology
+        if (otnTopology.getNode() != null
+            && otnTopology.getNode().containsKey(new NodeKey(new NodeId(abstractNodeid)))) {
+            TopologyShard otnShard = TopologyUtils.updateTopologyShard(abstractNodeid, mapping,
+                otnTopology.getNode(), otnTopologyLinks);
+            if (otnShard.getLinks() != null) {
+                for (Link link : otnShard.getLinks()) {
+                    LOG.info("updating links {} in {}", link.getLinkId().getValue(),
+                        NetworkUtils.OVERLAY_NETWORK_ID);
+                    InstanceIdentifier<Link> iiTopologyLink = InstanceIdentifier.builder(Networks.class)
+                        .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
+                        .augmentation(Network1.class)
+                        .child(Link.class, link.key())
+                        .build();
+                    networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyLink, link);
+                }
+            }
+            if (otnShard.getTps() != null) {
+                for (TerminationPoint tp : otnShard.getTps()) {
+                    LOG.info("updating TP {} in otn-topology", tp.getTpId().getValue());
+                    InstanceIdentifier<TerminationPoint> iiTopologyTp = InstanceIdentifier.builder(Networks.class)
+                        .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
+                        .child(Node.class, new NodeKey(new NodeId(abstractNodeid)))
+                        .augmentation(Node1.class)
+                        .child(TerminationPoint.class, new TerminationPointKey(tp.getTpId()))
+                        .build();
+                    networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiTopologyTp, tp);
+                    TopologyChanges tc = new TopologyChangesBuilder()
+                        .withKey(new TopologyChangesKey(abstractNodeid, tp.getTpId().getValue()))
+                        .setNodeId(abstractNodeid)
+                        .setTpId(tp.getTpId().getValue())
+                        .setState(tp.augmentation(
+                            org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1
+                                .class).getOperationalState())
+                        .build();
+                    if (!this.topologyChanges.containsKey(tc.key())) {
+                        this.topologyChanges.put(tc.key(), tc);
+                    }
+                }
+            }
+        }
+        // commit datastore updates
+        try {
+            networkTransactionService.commit().get();
+            sendNotification();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error updating openroadm-topology", e);
+        }
+    }
+
     @Override
     public void createOtnLinks(String nodeA, String tpA, String nodeZ, String tpZ, OtnLinkType linkType) {
         TopologyShard otnTopologyShard;
@@ -280,16 +416,17 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                     .augmentation(Network1.class)
                     .child(Link.class, otnTopologyLink.key())
                     .build();
-                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink,
-                    otnTopologyLink, CREATE_MISSING_PARENTS);
+                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
             }
         }
         if (otnTopologyShard.getTps() != null) {
             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
+                List<SupportingTerminationPoint> supportingTerminationPoint =
+                    new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
-                    .child(Node.class, new NodeKey(otnTopologyTp.getSupportingTerminationPoint().get(0).getNodeRef()))
+                    .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
                     .augmentation(Node1.class)
                     .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
                     .build();
@@ -353,16 +490,17 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                     .augmentation(Network1.class)
                     .child(Link.class, otnTopologyLink.key())
                     .build();
-                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink,
-                    CREATE_MISSING_PARENTS);
+                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
             }
         }
         if (otnTopologyShard.getTps() != null) {
             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
+                List<SupportingTerminationPoint> supportingTerminationPoint =
+                    new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
-                    .child(Node.class, new NodeKey(otnTopologyTp.getSupportingTerminationPoint().get(0).getNodeRef()))
+                    .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
                     .augmentation(Node1.class)
                     .child(TerminationPoint.class, new TerminationPointKey(otnTopologyTp.getTpId()))
                     .build();
@@ -378,10 +516,24 @@ public class NetworkModelServiceImpl implements NetworkModelService {
     }
 
     @Override
-    public void updateOtnLinks(List<String> nodeTps, String serviceRate, Short tribPortNb, Short tribSoltNb,
-        boolean isDeletion) {
-        List<Link> supportedOdu4Links = getSupportingOdu4Links(nodeTps);
-        List<TerminationPoint> tps = getOtnNodeTps(nodeTps);
+    public void updateOtnLinks(
+        org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.renderer.rev210618.renderer.rpc.result.sp.Link
+            notifLink, Uint32 serviceRate, Short tribPortNb, Short tribSoltNb, boolean isDeletion) {
+
+        LinkTp atermination = new LinkTpBuilder()
+            .setNodeId(notifLink.getATermination().getNodeId())
+            .setTpId(notifLink.getATermination().getTpId())
+            .build();
+        LinkTp ztermination = new LinkTpBuilder()
+            .setNodeId(notifLink.getZTermination().getNodeId())
+            .setTpId(notifLink.getZTermination().getTpId())
+            .build();
+        List<LinkTp> linkTerminations = new ArrayList<>();
+        linkTerminations.add(atermination);
+        linkTerminations.add(ztermination);
+
+        List<Link> supportedOdu4Links = getSupportingOdu4Links(linkTerminations);
+        List<TerminationPoint> tps = getOtnNodeTps(linkTerminations);
         TopologyShard otnTopologyShard;
         otnTopologyShard = OpenRoadmOtnTopology.updateOtnLinks(supportedOdu4Links, tps, serviceRate, tribPortNb,
             tribSoltNb, isDeletion);
@@ -394,19 +546,20 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                     .augmentation(Network1.class)
                     .child(Link.class, new LinkKey(new LinkId(otnTopologyLink.getLinkId().getValue())))
                     .build();
-                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink,
-                    otnTopologyLink, CREATE_MISSING_PARENTS);
+                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
             }
         }
         if (otnTopologyShard.getTps() != null) {
             for (TerminationPoint otnTopologyTp : otnTopologyShard.getTps()) {
                 LOG.info("updating otn nodes TP {} in otn-topology", otnTopologyTp.getTpId().getValue());
+                List<SupportingTerminationPoint> supportingTerminationPoint =
+                    new ArrayList<>(otnTopologyTp.nonnullSupportingTerminationPoint().values());
                 InstanceIdentifier<TerminationPoint> iiOtnTopologyTp = InstanceIdentifier.builder(Networks.class)
                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
-                    .child(Node.class, new NodeKey(otnTopologyTp.getSupportingTerminationPoint().get(0).getNodeRef()))
+                    .child(Node.class, new NodeKey(supportingTerminationPoint.get(0).getNodeRef()))
                     .augmentation(Node1.class)
-                    .child(TerminationPoint.class, new TerminationPointKey(
-                        new TpId(otnTopologyTp.getTpId().getValue())))
+                    .child(TerminationPoint.class, new TerminationPointKey(new TpId(otnTopologyTp.getTpId()
+                        .getValue())))
                     .build();
                 if (isDeletion) {
                     networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyTp, otnTopologyTp);
@@ -448,35 +601,30 @@ public class NetworkModelServiceImpl implements NetworkModelService {
     }
 
     private boolean checkLinks(List<Link> links) {
-        boolean canBeDeleted = true;
         if (links.isEmpty()) {
             return false;
-        } else {
-            for (Link link : links) {
-                if (link.augmentation(Link1.class) != null
+        }
+        for (Link link : links) {
+            if (link.augmentation(Link1.class) != null
                     && !link.augmentation(Link1.class).getUsedBandwidth().equals(Uint32.valueOf(0))) {
-                    canBeDeleted = false;
-                }
+                return false;
             }
         }
-        return canBeDeleted;
+        return true;
     }
 
     private boolean checkTerminationPoints(List<TerminationPoint> tps) {
-        boolean canBeDeleted = true;
         if (tps.isEmpty()) {
             return false;
-        } else {
-            for (TerminationPoint tp : tps) {
-                if (tp.augmentation(TerminationPoint1.class) != null
-                    && tp.augmentation(TerminationPoint1.class).getXpdrTpPortConnectionAttributes().getTsPool() != null
-                    && tp.augmentation(TerminationPoint1.class).getXpdrTpPortConnectionAttributes().getTsPool()
-                    .size() != 80) {
-                    canBeDeleted = false;
-                }
+        }
+        for (TerminationPoint tp : tps) {
+            if (tp.augmentation(TerminationPoint1.class) != null && tp.augmentation(TerminationPoint1.class)
+                    .getXpdrTpPortConnectionAttributes().getTsPool() != null && tp.augmentation(TerminationPoint1.class)
+                    .getXpdrTpPortConnectionAttributes().getTsPool().size() != 80) {
+                return false;
             }
         }
-        return canBeDeleted;
+        return true;
     }
 
     private List<TerminationPoint> getOtnNodeTps(String nodeTopoA, String tpA, String nodeTopoZ, String tpZ) {
@@ -497,7 +645,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         Optional<TerminationPoint> tpZOpt = Optional.empty();
 
         if (networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).isDone()
-            && networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).isDone()) {
+                && networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).isDone()) {
             try {
                 tpAOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpA).get();
                 tpZOpt = networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, iiTpZ).get();
@@ -516,11 +664,12 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         return tps;
     }
 
-    private List<TerminationPoint> getOtnNodeTps(List<String> nodeTopoTps) {
+    private List<TerminationPoint> getOtnNodeTps(List<LinkTp> linkTerminations) {
         List<TerminationPoint> tps = new ArrayList<>();
-        for (String str : nodeTopoTps) {
-            String nodeId = str.split("--")[0];
-            String tp = str.split("--")[1];
+        for (LinkTp linkTp : linkTerminations) {
+            String tp = linkTp.getTpId();
+            String nodeId = new StringBuilder(linkTp.getNodeId()).append("-")
+                .append(tp.split("-")[0]).toString();
             InstanceIdentifier<TerminationPoint> iiTp = InstanceIdentifier.builder(Networks.class)
                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
                 .child(Node.class, new NodeKey(new NodeId(nodeId)))
@@ -568,7 +717,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         }
     }
 
-    private List<Link> getSupportingOdu4Links(List<String> nodesTopoTps) {
+    private List<Link> getSupportingOdu4Links(List<LinkTp> nodesTopoTps) {
         InstanceIdentifier<Network1> iiOtnTopologyLinks = InstanceIdentifier.builder(Networks.class)
             .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
             .augmentation(Network1.class)
@@ -585,28 +734,27 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         }
         List<Link> odu4links = null;
         if (netw1Opt.isPresent() && netw1Opt.get().getLink() != null) {
-            odu4links = netw1Opt.get().getLink().stream().filter(lk -> lk.getLinkId().getValue().startsWith("ODU4"))
+            odu4links = netw1Opt
+                .get()
+                .nonnullLink().values()
+                .stream().filter(lk -> lk.getLinkId().getValue().startsWith("ODU4"))
                 .collect(Collectors.toList());
         }
         List<Link> links = new ArrayList<>();
         if (odu4links != null) {
-            for (String str : nodesTopoTps) {
-                String[] nodeAndTp = str.split("--");
-                if (nodeAndTp.length >= 2) {
-                    String nodeId = nodeAndTp[0];
-                    String tp = nodeAndTp[1];
-                    Link slink = odu4links.stream().filter(lk -> lk.getSource().getSourceNode().getValue()
-                        .equals(nodeId) && lk.getSource().getSourceTp().toString().equals(tp))
-                        .findFirst().get();
-                    if (!links.contains(slink)) {
-                        links.add(slink);
-                    }
-                    Link dlink = odu4links.stream().filter(lk -> lk.getDestination().getDestNode().getValue()
-                        .equals(nodeId) && lk.getDestination().getDestTp().toString().equals(tp))
-                        .findFirst().get();
-                    if (!links.contains(dlink)) {
-                        links.add(dlink);
-                    }
+            for (LinkTp linkTp : nodesTopoTps) {
+                String tp = linkTp.getTpId();
+                String nodeId = new StringBuilder(linkTp.getNodeId()).append("-")
+                    .append(tp.split("-")[0]).toString();
+                Link slink = odu4links.stream().filter(lk -> lk.getSource().getSourceNode().getValue()
+                    .equals(nodeId) && lk.getSource().getSourceTp().toString().equals(tp)).findFirst().get();
+                if (!links.contains(slink)) {
+                    links.add(slink);
+                }
+                Link dlink = odu4links.stream().filter(lk -> lk.getDestination().getDestNode().getValue()
+                    .equals(nodeId) && lk.getDestination().getDestTp().toString().equals(tp)).findFirst().get();
+                if (!links.contains(dlink)) {
+                    links.add(dlink);
                 }
             }
             LOG.debug("odu4links = {}", links.toString());
@@ -627,8 +775,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID)))
                     .child(Node.class, otnTopologyNode.key())
                     .build();
-                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyNode,
-                    otnTopologyNode);
+                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyNode, otnTopologyNode);
             }
             for (Link otnTopologyLink : otnTopologyShard.getLinks()) {
                 LOG.info("creating otn link {} in {}", otnTopologyLink.getLinkId().getValue(),
@@ -638,12 +785,28 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                     .augmentation(Network1.class)
                     .child(Link.class, otnTopologyLink.key())
                     .build();
-                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink,
-                    otnTopologyLink, CREATE_MISSING_PARENTS);
+                networkTransactionService.merge(LogicalDatastoreType.CONFIGURATION, iiOtnTopologyLink, otnTopologyLink);
             }
         } else {
             LOG.error("Unable to create OTN topology shard for node {}!", nodeId);
         }
+    }
 
+    @SuppressFBWarnings(
+            value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "false positive, this method is used by public updateOpenRoadmNetworkTopology")
+    private void sendNotification() {
+        if (topologyChanges.isEmpty()) {
+            LOG.warn("Empty Topology Change List. No updates in topology");
+            return;
+        }
+        this.notification = new TopologyUpdateResultBuilder()
+            .setTopologyChanges(topologyChanges)
+            .build();
+        try {
+            notificationPublishService.putNotification(this.notification);
+        } catch (InterruptedException e) {
+            LOG.error("Notification offer rejected. Error={}", e.getMessage());
+        }
     }
 }