fix connection state machine 40/104340/1
authorMichael Dürre <michael.duerre@highstreet-technologies.com>
Wed, 25 Mar 2020 07:35:03 +0000 (08:35 +0100)
committerMichael Dürre <michael.duerre@highstreet-technologies.com>
Wed, 25 Mar 2020 07:35:16 +0000 (08:35 +0100)
fixed state handlers for netconf nodes

Issue-ID: SDNC-1134
Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com>
Change-Id: Ibd63e84e4cc891a03ef5bd499760804a8cb89e93

sdnr/wt/devicemanager-onf/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/devicemanager/onf/ne/ONFCoreNetworkElement12Basic.java
sdnr/wt/devicemanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/devicemanager/eventdatahandler/ODLEventListenerHandler.java
sdnr/wt/devicemanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/devicemanager/housekeeping/ConnectionStatusHousekeepingService.java
sdnr/wt/devicemanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/devicemanager/impl/DeviceManagerNetconfConnectHandler.java
sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnode-state.yang [new file with mode: 0644]
sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnodestateservice.yang [deleted file]
sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java
sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java

index de6947d..86d28fe 100644 (file)
@@ -185,8 +185,10 @@ public class ONFCoreNetworkElement12Basic extends ONFCoreNetworkElement12Base {
         // -- Register NE to performance manager
         performanceManager.registration(mountPointNodeName, this);
 
-        eventListenerHandler.registration(mountPointNodeName, acessor.getNetconfNode());
-        eventListenerHandler.connectIndication(mountPointNodeName, getDeviceType());
+        //events will be already pushed by base devmgr (needs more clarification SDNC-1123)  
+        //eventListenerHandler.registration(mountPointNodeName, acessor.getNetconfNode());
+        //LOG.debug("refresh necon entry for {} with type {} not",mountPointNodeName,this.getDeviceType());
+        //eventListenerHandler.connectIndication(mountPointNodeName, getDeviceType());
         LOG.info("Starting Event listener finished. Added Netconf device:{} type:{}", mountPointNodeName, getDeviceType());
 
     }
index 37a9750..9f1b2b2 100644 (file)
@@ -32,6 +32,7 @@ import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.xml.WebSocketServiceCl
 import org.onap.ccsdk.features.sdnr.wt.devicemanager.service.EventHandlingService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.EventlogBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.NetworkElementConnectionEntity;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.data.provider.rev190801.NetworkElementDeviceType;
@@ -113,6 +114,15 @@ public class ODLEventListenerHandler implements EventHandlingService {
         webSocketService.sendViaWebsockets(registrationName, cNotificationXml);
     }
 
+    /**
+     * mountpoint created, connection state not connected
+        * @param mountpointNodeName uuid that is nodeId or mountpointId
+        * @param netconfNode
+        */
+       public void mountpointCreatedIndication(String mountpointNodeName, NetconfNode netconfNode) {
+               LOG.debug("mountpoint create indication for {}", mountpointNodeName);
+               this.registration(mountpointNodeName, netconfNode);
+       }
     /**
      * After registration
      * @param mountpointNodeName uuid that is nodeId or mountpointId
@@ -132,7 +142,18 @@ public class ODLEventListenerHandler implements EventHandlingService {
         webSocketService.sendViaWebsockets(mountpointNodeName, notificationXml);
     }
 
-
+    /**
+     * mountpoint state changed
+        * @param mountpointNodeName
+        * @param netconfNode
+        */
+       public void onStateChangeIndication(String mountpointNodeName, NetconfNode netconfNode) {
+               LOG.debug("mountpoint state changed indication for {}", mountpointNodeName);
+               ConnectionStatus csts = netconfNode.getConnectionStatus();
+               this.updateRegistration(mountpointNodeName, ConnectionStatus.class.getSimpleName(),
+                csts != null ? csts.getName() : "null", netconfNode);
+               
+       }
     /**
      * A deregistration of a mountpoint occured.
      * @param registrationName Name of the event that is used as key in the database.
@@ -155,7 +176,6 @@ public class ODLEventListenerHandler implements EventHandlingService {
      * Mountpoint state changed .. from connected -> connecting or unable-to-connect or vis-e-versa.
      * @param registrationName Name of the event that is used as key in the database.
      */
-
     @Override
     public void updateRegistration(String registrationName, String attribute, String attributeNewValue, NetconfNode nNode) {
         AttributeValueChangedNotificationXml notificationXml = new AttributeValueChangedNotificationXml(ownKeyName,
@@ -238,4 +258,8 @@ public class ODLEventListenerHandler implements EventHandlingService {
         return eventNumber++;
     }
 
+       
+
+       
+
 }
index e1fde70..d63ff5d 100644 (file)
@@ -23,6 +23,8 @@ package org.onap.ccsdk.features.sdnr.wt.devicemanager.housekeeping;
 import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.ArrayList;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Optional;
@@ -33,7 +35,9 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.DataProvider;
+import org.onap.ccsdk.features.sdnr.wt.devicemanager.impl.util.NetworkElementConnectionEntitiyUtil;
 import org.onap.ccsdk.features.sdnr.wt.devicemanager.types.InternalConnectionStatus;
 import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
@@ -104,40 +108,95 @@ public class ConnectionStatusHousekeepingService implements ClusterSingletonServ
             String nodeId;
             if (list == null || list.size() <= 0) {
                 LOG.trace("no items in list.");
-                return;
             }
-            for (NetworkElementConnectionEntity item : list) {
-
-                // compare with MD-SAL
-                nodeId = item.getNodeId();
-                LOG.trace("check status of {}", nodeId);
-                dbStatus = item.getStatus();
-                mdsalStatus = this.getMDSalConnectionStatus(nodeId);
-                if (mdsalStatus == null) {
-                    LOG.trace("unable to get connection status. jump over");
-                    continue;
-                }
-                // if different then update db
-                if (dbStatus != mdsalStatus) {
-                    LOG.trace("status is inconsistent db={}, mdsal={}. updating db", dbStatus, mdsalStatus);
-                    if(!item.isIsRequired() && mdsalStatus==ConnectionLogStatus.Disconnected) {
-                        this.dataProvider.removeNetworkConnection(nodeId);
-                    }
-                    else {
-                    this.dataProvider.updateNetworkConnectionDeviceType(
-                            new NetworkElementConnectionBuilder().setStatus(mdsalStatus).build(), nodeId);
-                    }
-                } else {
-                    LOG.trace("no difference");
-                }
-
+            else {
+                   //check all db entries and sync connection status
+                   for (NetworkElementConnectionEntity item : list) {
+       
+                       // compare with MD-SAL
+                       nodeId = item.getNodeId();
+                       LOG.trace("check status of {}", nodeId);
+                       dbStatus = item.getStatus();
+                       mdsalStatus = this.getMDSalConnectionStatus(nodeId);
+                       if (mdsalStatus == null) {
+                           LOG.trace("unable to get connection status. jump over");
+                           continue;
+                       }
+                       // if different then update db
+                       if (dbStatus != mdsalStatus) {
+                           LOG.trace("status is inconsistent db={}, mdsal={}. updating db", dbStatus, mdsalStatus);
+                           if((item.isIsRequired()==null || item.isIsRequired()==false) && mdsalStatus==ConnectionLogStatus.Disconnected) {
+                               LOG.info("removing entry for node {} ({}) from database due missing MD-SAL entry",item.getNodeId(),mdsalStatus);
+                               this.dataProvider.removeNetworkConnection(nodeId);
+                           }
+                           else {
+                           this.dataProvider.updateNetworkConnectionDeviceType(
+                                   new NetworkElementConnectionBuilder().setStatus(mdsalStatus).build(), nodeId);
+                           }
+                       } else {
+                           LOG.trace("no difference");
+                       }
+       
+                   }
             }
-        } catch (Exception e) {
+                       //check all md-sal entries and add non-existing to db
+//                     List<Node> mdsalNodes = this.getMDSalNodes();
+//                     NodeId nid;
+//                     for (Node mdsalNode : mdsalNodes) {
+//                             nid = mdsalNode.getNodeId();
+//                             if (nid == null) {
+//                                     continue;
+//                             }
+//                             nodeId = nid.getValue();
+//                             if (nodeId == null) {
+//                                     continue;
+//                             }
+//                             if (contains(list, nodeId)) {
+//                                     LOG.debug("found mountpoint for {} without db entry. creating.",nodeId);
+//                                     this.dataProvider.updateNetworkConnection22(NetworkElementConnectionEntitiyUtil
+//                                                     .getNetworkConnection(nodeId, mdsalNode.augmentation(NetconfNode.class)), nodeId);
+//                             }
+//                     }
+
+               } catch (Exception e) {
             LOG.warn("problem executing housekeeping task: {}", e);
         }
         LOG.debug("finish housekeeping");
     }
 
+       /**
+        * @param list
+        * @param nodeId
+        * @return
+        */
+//     private boolean contains(List<NetworkElementConnectionEntity> list, @NonNull String nodeId) {
+//             if(list==null || list.size()<=0) {
+//                     return false;
+//             }
+//             for(NetworkElementConnectionEntity item:list) {
+//                     if(item!=null && nodeId.equals(item.getNodeId())) {
+//                             return true;
+//                     }
+//             }
+//             return false;
+//     }
+//
+//     private List<Node> getMDSalNodes(){
+//     ReadTransaction trans = this.dataBroker.newReadOnlyTransaction();
+//        FluentFuture<Optional<Topology>> optionalTopology =trans.read(LogicalDatastoreType.OPERATIONAL, NETCONF_TOPO_IID);
+//        List<Node> nodes = new ArrayList<>();
+//        try {
+//             Topology topo = optionalTopology.get(20, TimeUnit.SECONDS).get();
+//             List<Node> topoNodes=topo.getNode();
+//             if(topoNodes!=null){
+//                     nodes.addAll(topoNodes);
+//             }
+//        }
+//        catch(Exception e) {
+//             LOG.warn("unable to read netconf topology for housekeeping: {}",e);
+//        }
+//        return nodes;
+//    }
     private ConnectionLogStatus getMDSalConnectionStatus(String nodeId) {
 
         @SuppressWarnings("null")
@@ -173,24 +232,24 @@ public class ConnectionStatusHousekeepingService implements ClusterSingletonServ
         this.scheduler.shutdown();
     }
 
-     @SuppressWarnings("null")
-        @Override
-        public @NonNull ServiceGroupIdentifier getIdentifier() {
-             return IDENT;
-        }
-
-        @Override
-        public void instantiateServiceInstance() {
-            LOG.info("We take Leadership");
-            this.isMaster=true;
-            this.start();
-        }
-
-        @Override
-        public ListenableFuture<? extends Object> closeServiceInstance() {
-            LOG.info("We lost Leadership");
-            this.isMaster=false;
-            this.start();
-            return Futures.immediateFuture(null);
-        }
+       @SuppressWarnings("null")
+       @Override
+       public @NonNull ServiceGroupIdentifier getIdentifier() {
+               return IDENT;
+       }
+
+       @Override
+       public void instantiateServiceInstance() {
+               LOG.info("We take Leadership");
+               this.isMaster = true;
+               this.start();
+       }
+
+       @Override
+       public ListenableFuture<? extends Object> closeServiceInstance() {
+               LOG.info("We lost Leadership");
+               this.isMaster = false;
+               this.start();
+               return Futures.immediateFuture(null);
+       }
 }
index 2d64f37..5f9911b 100644 (file)
@@ -130,11 +130,14 @@ public class DeviceManagerNetconfConnectHandler implements NetconfNodeConnectLis
     @Override
     public void onCreated(NodeId nNodeId, NetconfNode netconfNode) {
         LOG.info("onCreated {}", nNodeId);
+        odlEventListenerHandler.mountpointCreatedIndication(nNodeId.getValue(), netconfNode);
+        
     }
 
     @Override
     public void onStateChange(NodeId nNodeId, NetconfNode netconfNode) {
         LOG.info("onStateChange {}", nNodeId);
+        odlEventListenerHandler.onStateChangeIndication(nNodeId.getValue(),netconfNode);
     }
 
     @Override
@@ -181,6 +184,7 @@ public class DeviceManagerNetconfConnectHandler implements NetconfNodeConnectLis
         if (result != null) {
             LOG.warn("NE list was not empty as expected, but contained {} ", result.getNodeId());
         } else {
+               LOG.debug("refresh necon entry for {} with type {}",mountPointNodeName,ne.getDeviceType());
             odlEventListenerHandler.connectIndication(mountPointNodeName, ne.getDeviceType());
         }
     }
diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnode-state.yang b/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnode-state.yang
new file mode 100644 (file)
index 0000000..cd6c92e
--- /dev/null
@@ -0,0 +1,94 @@
+module netconfnode-state {
+
+  yang-version 1;
+  namespace "urn:opendaylight:params:xml:ns:yang:netconfnode-state";
+  prefix netconfnode-state;
+
+  import data-provider {
+    prefix data-provider;
+  }
+
+  organization
+    "highstreet technologies GmbH";
+  contact
+    "Web:   <https://highstreet-technologies.com>
+     ONAP:  <https://wiki.onap.org/display/DW/ODLUX+DB+API>";
+
+  description
+    "netconfnode-state-service Api Module
+
+     Copyright 2019 highstreet technologies GmbH Intellectual Property.
+     All rights reserved.
+
+     Licensed under the Apache License, Version 2.0 (the 'License');
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an 'AS IS' BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.";
+
+  revision 2019-10-11 {
+    description
+      "Initial revision";
+    reference
+      "https://jira.onap.org/browse/SDNC-877";
+  }
+
+  container fault-notification {
+    description
+      "Handle fault problem notification of a network-element";
+    uses data-provider:object-change-reference;
+    uses data-provider:fault;
+  }
+  container attribute-change-notification {
+    description
+      "Handle  attribute change notification of a network-element";
+    uses data-provider:object-change-reference;
+    uses data-provider:attribute-change;
+  }
+
+  rpc push-fault-notification {
+    description
+      "Forward fault problem notification of a network-element";
+    input {
+      uses data-provider:object-change-reference;
+      uses data-provider:fault;
+    }
+  }
+
+  rpc push-attribute-change-notification {
+    description
+      "Forward attribute change notification of a network-element";
+    input {
+      uses data-provider:object-change-reference;
+      uses data-provider:attribute-change;
+    }
+  }
+
+  rpc get-status {
+    description
+      "Returns status information";
+    output {
+      list status {
+        key "key";
+        leaf key {
+          type string;
+          description
+            "A unique identifier for the status.";
+        }
+        leaf value {
+          type string;
+          description
+            "The value corresponding to the key.";
+        }
+        description
+          "Provides a key value list with status information";
+      }
+    }
+  }
+}
diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnodestateservice.yang b/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnodestateservice.yang
deleted file mode 100644 (file)
index 737f858..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-module netconfnode-state {
-
-    yang-version 1;
-    namespace "urn:opendaylight:params:xml:ns:yang:netconfnode-state";
-    prefix "netconfnode-state";
-
-    import data-provider { prefix "data-provider"; }
-
-    description
-        "sdnr-wt-netconfnode-state-service Api Module";
-
-    revision "2019-10-11" {
-        description
-            "Initial revision";
-    }
-
-    container fault-notification {
-        description
-            "Handle fault problem notification of a network-element";
-        uses data-provider:object-change-reference;
-        uses data-provider:fault;
-    }
-    container attribute-change-notification {
-        description
-            "Handle  attribute change notification of a network-element";
-            uses data-provider:object-change-reference;
-            uses data-provider:attribute-change;
-    }
-    rpc push-fault-notification {
-        description
-            "Forward fault problem notification of a network-element";
-        input {
-            uses data-provider:object-change-reference;
-            uses data-provider:fault;
-        }
-    }
-    rpc push-attribute-change-notification {
-        description
-            "Forward attribute change notification of a network-element";
-        input {
-            uses data-provider:object-change-reference;
-            uses data-provider:attribute-change;
-        }
-    }
-
-    rpc get-status {
-        description
-                "Returns status information";
-
-        output {
-            list status {
-                description "Provides a key value list with status information";
-                key key;
-                leaf key {
-                    type string;
-                }
-                leaf value {
-                    type string;
-                }
-            }
-        }
-    }
-}
-
index 041ab9a..adced6b 100644 (file)
@@ -460,7 +460,7 @@ public class NetconfNodeStateServiceImpl implements NetconfNodeStateService, Rpc
                                 // enterConnected state.after == connected
                                 // => Here create or update by checking root.getDataBefore() != null
 
-                                boolean connectedBefore, connectedAfter;
+                                boolean connectedBefore, connectedAfter, created=false;
                                 NetconfNode nNodeAfter = getNetconfNode(root.getDataAfter());
                                 connectedAfter = isConnected(nNodeAfter);
                                 if (root.getDataBefore() != null) {
@@ -470,6 +470,7 @@ public class NetconfNodeStateServiceImpl implements NetconfNodeStateService, Rpc
                                 } else {
                                     // It is a create
                                     connectedBefore = false;
+                                    created = true;
                                 }
 
                                 LOG.info(
@@ -477,14 +478,16 @@ public class NetconfNodeStateServiceImpl implements NetconfNodeStateService, Rpc
                                         nodeId, connectedBefore, connectedAfter,
                                         getClusteredConnectionStatus(nNodeAfter), isCluster);
 
+                                if(created) {
+                                        netconfNodeStateListenerList.forEach(item -> {
+                                         try {
+                                             item.onCreated(nodeId, nNodeAfter);
+                                         } catch (Exception e) {
+                                             LOG.info("Exception during onCreated listener call", e);
+                                         }
+                                     });
+                                }
                                 if (!connectedBefore && connectedAfter) {
-                                    netconfNodeStateListenerList.forEach(item -> {
-                                        try {
-                                            item.onCreated(nodeId, nNodeAfter);
-                                        } catch (Exception e) {
-                                            LOG.info("Exception during onCreated listener call", e);
-                                        }
-                                    });
                                     enterConnectedState(nodeId, nNodeAfter);
                                 } else {
                                     LOG.debug("State change {} {}", connectedBefore, connectedAfter);
@@ -534,7 +537,7 @@ public class NetconfNodeStateServiceImpl implements NetconfNodeStateService, Rpc
         @Override
         public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) {
             LOG.info("L1 TreeChange enter changes:{}", changes.size());
-            onDataTreeChangedHandler(changes);
+            new Thread( () -> onDataTreeChangedHandler(changes)).start();
             LOG.info("L1 TreeChange leave");
         }
     }
index 372d412..5427c03 100644 (file)
@@ -179,7 +179,7 @@ public class TestNetconfNodeStateService {
 
     @SuppressWarnings("unchecked")
     @Test
-    public void test5OnConnect() {
+    public void test5OnConnect() throws InterruptedException {
         System.out.println("Test5: On Connect");
         NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
         netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected);
@@ -208,7 +208,7 @@ public class TestNetconfNodeStateService {
         Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn);
         dataBrokerNetconf.sendClusteredChanges(changes);
         dataBrokerNetconf.sendChanges(changes);
-
+        Thread.sleep(300);
         //verify that it was called one time and nodeId is the expected
         ArgumentCaptor<NetconfAccessor> varArgs = ArgumentCaptor.forClass(NetconfAccessor.class);
         verify(nCL).onEnterConnected(varArgs.capture());