Update portmapping YANG model
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / service / NetworkModelServiceImpl.java
index 42665ef5fbea328ba316d89db38c6cb5ee21a2ee..1a1e456f7de827157fe5889dff7200847f2ef0f8 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;
@@ -19,6 +20,7 @@ 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.NetworkUtils;
 import org.opendaylight.transportpce.common.mapping.PortMapping;
@@ -30,8 +32,13 @@ 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.rev201012.network.nodes.NodeInfo;
-import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev201012.network.nodes.NodeInfo.OpenroadmVersion;
+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.OrdTopologyChanges;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.OrdTopologyChangesBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.networkmodel.rev201116.topology.update.result.OrdTopologyChangesKey;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.OpenroadmNodeVersion;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210315.network.nodes.NodeInfo;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1Builder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.TerminationPoint1Builder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
@@ -41,6 +48,7 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.No
 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
 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.d._interface.ord.topology.types.rev201116.TopologyNotificationTypes;
 import org.opendaylight.yang.gen.v1.http.transportpce.topology.rev201019.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;
@@ -80,9 +88,14 @@ public class NetworkModelServiceImpl implements NetworkModelService {
     // Maps that include topology component changed with its new operational state <id, state>
     private Map<String, State> linksChanged;
     private Map<String, State> terminationPointsChanged;
+    // Variables for creating and sending topology update notification
+    private final NotificationPublishService notificationPublishService;
+    private Map<OrdTopologyChangesKey, OrdTopologyChanges> 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;
@@ -91,6 +104,8 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         this.otnTopologyShardMountedDevice = new HashMap<String, TopologyShard>();
         this.linksChanged = new HashMap<String, State>();
         this.terminationPointsChanged = new HashMap<String, State>();
+        this.notificationPublishService = notificationPublishService;
+        this.topologyChanges = new HashMap<OrdTopologyChangesKey, OrdTopologyChanges>();
     }
 
     public void init() {
@@ -224,7 +239,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) {
@@ -268,6 +283,7 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         // Clear maps for each NETCONF notification received
         this.linksChanged.clear();
         this.terminationPointsChanged.clear();
+        this.topologyChanges.clear();
         // 1. Get the list links and nodes of the current openroadm network topology
         List<Link> linkList = null;
         List<Node> nodesList = null;
@@ -304,17 +320,18 @@ public class NetworkModelServiceImpl implements NetworkModelService {
         switch (cpackType) {
             case "ADDROP":
                 LOG.info("ADDROP circuit pack modified");
-                setTerminationPointsChangedMap(changedCpack);
+                setTerminationPointsChangedMap(changedCpack, nodeId);
                 // setTpStateHashmap(changedCpack);
                 break;
             case "WSSDEG":
                 LOG.info("WSSDEG circuit pack modified");
-                setTerminationPointsChangedMap(changedCpack);
+                setTerminationPointsChangedMap(changedCpack, nodeId);
                 // 3. Update the termination points of the node that sent a NETCONF notification
                 updateOpenRoadmNetworkTopologyTPs(nodesList, nodeId);
                 // 4. Update the links of the topology affected by the changes on TPs (if any)
                 updateOpenRoadmNetworkTopologyLinks(linkList, nodesList);
-                // TODO: send notification to service handler
+                // Send notification to service handler
+                sendNotification(TopologyNotificationTypes.OpenroadmTopologyUpdate, this.topologyChanges);
                 break;
             case "port":
                 LOG.info("port circuit pack modified");
@@ -722,12 +739,17 @@ public class NetworkModelServiceImpl implements NetworkModelService {
 
     }
 
-    private void setTerminationPointsChangedMap(CircuitPacks changedCpack) {
+    private void setTerminationPointsChangedMap(CircuitPacks changedCpack, String nodeId) {
         List<Ports> portsList = new ArrayList<>(Objects.requireNonNull(changedCpack.getPorts()).values());
         for (Ports port : portsList) {
             String lcp = port.getLogicalConnectionPoint();
-            if (lcp != null && !this.terminationPointsChanged.containsKey(lcp)) {
-                this.terminationPointsChanged.put(lcp, State.forValue(port.getOperationalState().getIntValue()));
+            if (lcp != null) {
+                String abstractNodeid = nodeId + "-" + lcp.split("-")[0];
+                if (!this.terminationPointsChanged.containsKey(abstractNodeid + "-" + lcp)) {
+                    LOG.info("Node id {}, LCP {}", abstractNodeid, lcp);
+                    this.terminationPointsChanged.put(abstractNodeid + "-" + lcp,
+                            State.forValue(port.getOperationalState().getIntValue()));
+                }
             }
         }
     }
@@ -751,27 +773,40 @@ public class NetworkModelServiceImpl implements NetworkModelService {
                     String tpId = Objects.requireNonNull(tp.getTpId()).getValue();
                     State tpState = Objects.requireNonNull(tp.augmentation(org.opendaylight.yang.gen.v1.http
                         .org.openroadm.common.network.rev200529.TerminationPoint1.class)).getOperationalState();
-                    if (this.terminationPointsChanged.containsKey(tpId) && !this.terminationPointsChanged.get(tpId)
-                            .equals(tpState)) {
+                    String key = abstractNodeId + "-" + tpId;
+                    if (this.terminationPointsChanged.containsKey(key)
+                            && !this.terminationPointsChanged.get(key).equals(tpState)) {
                         // The state of a termination point has changed... updating
                         State newTpOperationalState = null;
                         AdminStates newTpAdminState = null;
                         /* 3. If the TP has changed its state, it has to be added to the links Map, as a Link state
                         is defined by the state of the TPs that model the link. */
-                        switch (this.terminationPointsChanged.get(tpId)) {
+                        switch (this.terminationPointsChanged.get(key)) {
                             case InService:
                                 newTpAdminState = AdminStates.InService;
                                 newTpOperationalState = State.InService;
                                 // Add TP and state inService to the links Map
-                                this.linksChanged.put(tpId, State.InService);
-                                // TODO: update change list for service handler notification
+                                this.linksChanged.put(key, State.InService);
+                                // Update topology change list for service handler notification
+                                this.topologyChanges.put(
+                                    new OrdTopologyChangesKey(node.getNodeId().getValue() + "-" + tpId),
+                                    new OrdTopologyChangesBuilder()
+                                        .setId(node.getNodeId().getValue() + "-" + tpId)
+                                        .setState(newTpOperationalState)
+                                        .build());
                                 break;
                             case OutOfService:
                                 newTpAdminState = AdminStates.OutOfService;
                                 newTpOperationalState = State.OutOfService;
                                 // Add TP and state outOfService to the links Map
-                                this.linksChanged.put(tpId, State.OutOfService);
-                                // TODO: update change list for service handler notification
+                                this.linksChanged.put(key, State.OutOfService);
+                                // Update topology change list for service handler notification
+                                this.topologyChanges.put(
+                                    new OrdTopologyChangesKey(node.getNodeId().getValue() + "-" + tpId),
+                                    new OrdTopologyChangesBuilder()
+                                        .setId(node.getNodeId().getValue() + "-" + tpId)
+                                        .setState(newTpOperationalState)
+                                        .build());
                                 break;
                             case Degraded:
                                 LOG.warn("Operational state Degraded not handled");
@@ -821,6 +856,8 @@ public class NetworkModelServiceImpl implements NetworkModelService {
             String dstNode = link.getDestination().getDestNode().getValue();
             State linkState = link.augmentation(org.opendaylight.yang.gen.v1.http
                 .org.openroadm.common.network.rev200529.Link1.class).getOperationalState();
+            String srcKey = srcNode + "-" + srcTp;
+            String dstKey = dstNode + "-" + dstTp;
             /* 1. Check the current state of the source and dest tps of the link. If these tps exist on the links Map
             and the states are different, then we need to update the link state accordingly.
             There are several cases depending on the current link state:
@@ -832,38 +869,38 @@ public class NetworkModelServiceImpl implements NetworkModelService {
             end. */
             switch (linkState) {
                 case InService:
-                    if (this.linksChanged.containsKey(srcTp) && this.linksChanged.containsKey(dstTp)) {
+                    if (this.linksChanged.containsKey(srcKey) && this.linksChanged.containsKey(dstKey)) {
                         // Both TPs of the link have been updated. If one of them is outOfService --> link outOfService
-                        if (State.OutOfService.equals(this.linksChanged.get(srcTp)) || State.OutOfService.equals(this
-                                .linksChanged.get(dstTp))) {
+                        if (State.OutOfService.equals(this.linksChanged.get(srcKey)) || State.OutOfService.equals(this
+                                .linksChanged.get(dstKey))) {
                             updateLinkStates(link, State.OutOfService, AdminStates.OutOfService);
                         }
-                    } else if (this.linksChanged.containsKey(srcTp) && State.OutOfService.equals(this.linksChanged
-                            .get(srcTp))) {
+                    } else if (this.linksChanged.containsKey(srcKey) && State.OutOfService.equals(this.linksChanged
+                            .get(srcKey))) {
                         // Source TP has been changed to outOfService --> link outOfService
                         updateLinkStates(link, State.OutOfService, AdminStates.OutOfService);
-                    } else if (this.linksChanged.containsKey(dstTp) && State.OutOfService.equals(this.linksChanged
-                            .get(dstTp))) {
+                    } else if (this.linksChanged.containsKey(dstKey) && State.OutOfService.equals(this.linksChanged
+                            .get(dstKey))) {
                         // Destination TP has been changed to outOfService --> link outOfService
                         updateLinkStates(link, State.OutOfService, AdminStates.OutOfService);
                     }
                     break;
                 case OutOfService:
-                    if (this.linksChanged.containsKey(srcTp) && this.linksChanged.containsKey(dstTp)) {
+                    if (this.linksChanged.containsKey(srcKey) && this.linksChanged.containsKey(dstKey)) {
                         // Both TPs of the link have been updated. If both of them are inService --> link inService
-                        if (State.InService.equals(this.linksChanged.get(srcTp)) || State.InService.equals(this
-                                .linksChanged.get(dstTp))) {
+                        if (State.InService.equals(this.linksChanged.get(srcKey)) || State.InService.equals(this
+                                .linksChanged.get(dstKey))) {
                             updateLinkStates(link, State.InService, AdminStates.InService);
                         }
-                    } else if (this.linksChanged.containsKey(srcTp) && State.InService.equals(this.linksChanged
-                            .get(srcTp))) {
+                    } else if (this.linksChanged.containsKey(srcKey) && State.InService.equals(this.linksChanged
+                            .get(srcKey))) {
                         // Source TP has been changed to inService --> check the second TP and update link to inService
                         // only if both TPs are inService
                         if (tpInService(dstNode, dstTp, nodesList)) {
                             updateLinkStates(link, State.InService, AdminStates.InService);
                         }
-                    } else if (this.linksChanged.containsKey(dstTp) && State.InService.equals(this.linksChanged
-                            .get(dstTp))) {
+                    } else if (this.linksChanged.containsKey(dstKey) && State.InService.equals(this.linksChanged
+                            .get(dstKey))) {
                         // Destination TP has been changed to to inService --> check the second TP and update link to
                         // inService only if both TPs are inService
                         if (tpInService(srcNode, srcTp, nodesList)) {
@@ -905,6 +942,9 @@ public class NetworkModelServiceImpl implements NetworkModelService {
 
     private void updateLinkStates(Link link, State state, AdminStates adminStates) {
         // TODO: add change to list of changes
+        // Update topology change list
+        this.topologyChanges.put(new OrdTopologyChangesKey(link.getLinkId().getValue()),
+                new OrdTopologyChangesBuilder().setId(link.getLinkId().getValue()).setState(state).build());
         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1 link1 = new Link1Builder()
             .setOperationalState(state).setAdministrativeState(adminStates).build();
         Link updLink = new LinkBuilder().withKey(link.key()).addAugmentation(link1).build();
@@ -921,4 +961,23 @@ public class NetworkModelServiceImpl implements NetworkModelService {
             LOG.error("Couldnt commit changed to openroadm topology. Error={}", e.getMessage());
         }
     }
+
+    @SuppressFBWarnings(
+            value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "false positive, this method is used by public updateOpenRoadmNetworkTopology")
+    private void sendNotification(TopologyNotificationTypes notificationType,
+                                  Map<OrdTopologyChangesKey, OrdTopologyChanges> topologyChangesMap) {
+        if (topologyChangesMap.isEmpty()) {
+            LOG.warn("Empty Topology Change map. No updates in topology");
+            return;
+        }
+        TopologyUpdateResultBuilder topologyUpdateResultBuilder = new TopologyUpdateResultBuilder()
+                .setNotificationType(notificationType).setOrdTopologyChanges(topologyChangesMap);
+        this.notification = topologyUpdateResultBuilder.build();
+        try {
+            notificationPublishService.putNotification(this.notification);
+        } catch (InterruptedException e) {
+            LOG.error("Notification offer rejected. Error={}", e.getMessage());
+        }
+    }
 }