Bug 3864: Notify netconf monitoring about changes in session
[netconf.git] / netconf / mdsal-netconf-monitoring / src / main / java / org / opendaylight / controller / config / yang / netconf / mdsal / monitoring / MonitoringToMdsalWriter.java
index 84322786de099748053d8b936c260d39ad524a08..7c434f2813eae2916abd909a6f4d7882c440a6a8 100644 (file)
@@ -9,25 +9,41 @@
 package org.opendaylight.controller.config.yang.netconf.mdsal.monitoring;
 
 import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import java.util.Collection;
+import java.util.function.Consumer;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-final class MonitoringToMdsalWriter implements AutoCloseable, NetconfMonitoringService.MonitoringListener, BindingAwareProvider {
+/**
+ * Writes netconf server state changes received from NetconfMonitoringService to netconf-state datastore subtree.
+ */
+final class MonitoringToMdsalWriter implements AutoCloseable, NetconfMonitoringService.CapabilitiesListener,
+        NetconfMonitoringService.SessionsListener, BindingAwareProvider {
 
     private static final Logger LOG = LoggerFactory.getLogger(MonitoringToMdsalWriter.class);
 
+    private static final InstanceIdentifier<Capabilities> CAPABILITIES_INSTANCE_IDENTIFIER =
+            InstanceIdentifier.create(NetconfState.class).child(Capabilities.class);
+    private static final InstanceIdentifier<Schemas> SCHEMAS_INSTANCE_IDENTIFIER =
+            InstanceIdentifier.create(NetconfState.class).child(Schemas.class);
+    private static final InstanceIdentifier<Sessions> SESSIONS_INSTANCE_IDENTIFIER =
+            InstanceIdentifier.create(NetconfState.class).child(Sessions.class);
+
     private final NetconfMonitoringService serverMonitoringDependency;
     private DataBroker dataBroker;
 
@@ -37,39 +53,67 @@ final class MonitoringToMdsalWriter implements AutoCloseable, NetconfMonitoringS
 
     @Override
     public void close() {
-        final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-        tx.delete(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(NetconfState.class));
-        final CheckedFuture<Void, TransactionCommitFailedException> submit = tx.submit();
+        runTransaction((tx) -> tx.delete(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(NetconfState.class)));
+    }
 
-        Futures.addCallback(submit, new FutureCallback<Void>() {
-            @Override
-            public void onSuccess(final Void aVoid) {
-                LOG.debug("Netconf state cleared successfully");
-            }
+    @Override
+    public void onSessionStarted(Session session) {
+        final InstanceIdentifier<Session> sessionPath =
+                SESSIONS_INSTANCE_IDENTIFIER.child(Session.class, session.getKey());
+        runTransaction((tx) -> tx.put(LogicalDatastoreType.OPERATIONAL, sessionPath, session));
+    }
 
-            @Override
-            public void onFailure(final Throwable throwable) {
-                LOG.warn("Unable to clear netconf state", throwable);
-            }
-        });
+    @Override
+    public void onSessionEnded(Session session) {
+        final InstanceIdentifier<Session> sessionPath =
+                SESSIONS_INSTANCE_IDENTIFIER.child(Session.class, session.getKey());
+        runTransaction((tx) -> tx.delete(LogicalDatastoreType.OPERATIONAL, sessionPath));
     }
 
     @Override
-    public void onStateChanged(final NetconfState state) {
-        Preconditions.checkState(dataBroker != null);
-        final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-        tx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(NetconfState.class), state);
-        try {
-            tx.submit().checkedGet();
-            LOG.debug("Netconf state updated successfully");
-        } catch (TransactionCommitFailedException e) {
-            LOG.warn("Unable to update netconf state", e);
-        }
+    public void onSessionsUpdated(Collection<Session> sessions) {
+        runTransaction((tx) -> updateSessions(tx, sessions));
+    }
+
+    @Override
+    public void onCapabilitiesChanged(Capabilities capabilities) {
+        runTransaction((tx) -> tx.put(LogicalDatastoreType.OPERATIONAL, CAPABILITIES_INSTANCE_IDENTIFIER, capabilities));
+    }
+
+    @Override
+    public void onSchemasChanged(Schemas schemas) {
+        runTransaction((tx) -> tx.put(LogicalDatastoreType.OPERATIONAL, SCHEMAS_INSTANCE_IDENTIFIER, schemas));
     }
 
     @Override
     public void onSessionInitiated(final BindingAwareBroker.ProviderContext providerContext) {
         dataBroker = providerContext.getSALService(DataBroker.class);
-        serverMonitoringDependency.registerListener(this);
+        serverMonitoringDependency.registerCapabilitiesListener(this);
+        serverMonitoringDependency.registerSessionsListener(this);
+    }
+
+    private void runTransaction(Consumer<WriteTransaction> txUser) {
+        Preconditions.checkState(dataBroker != null);
+        final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        txUser.accept(tx);
+        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(@Nullable Void result) {
+                LOG.debug("Netconf state updated successfully");
+            }
+
+            @Override
+            public void onFailure(Throwable t) {
+                LOG.warn("Unable to update netconf state", t);
+            }
+        });
+    }
+
+    private static void updateSessions(WriteTransaction tx, Collection<Session> sessions) {
+        for (Session session : sessions) {
+            final InstanceIdentifier<Session> sessionPath =
+                    SESSIONS_INSTANCE_IDENTIFIER.child(Session.class, session.getKey());
+            tx.put(LogicalDatastoreType.OPERATIONAL, sessionPath, session);
+        }
     }
 }