BUG-2635 Netconf monitoring for md-sal netconf northbound 68/15468/5
authorMaros Marsalek <mmarsale@cisco.com>
Wed, 18 Feb 2015 16:31:39 +0000 (17:31 +0100)
committerMaros Marsalek <mmarsale@cisco.com>
Mon, 23 Feb 2015 10:45:08 +0000 (11:45 +0100)
Monitoring for mdsal's netconf stores all available monitoring data in the datastore and provides get-schema operation

Change-Id: I573c5d57e5cf25d7688f3355b602327c7af75c65
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
45 files changed:
features/mdsal/pom.xml
features/mdsal/src/main/resources/features.xml
features/netconf-connector/pom.xml
features/netconf/src/main/resources/features.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NotificationHandler.java
opendaylight/netconf/ietf-netconf-monitoring/src/main/yang/ietf-netconf-monitoring.yang
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModule.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java
opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java
opendaylight/netconf/mdsal-netconf-connector/src/main/yang/netconf-mdsal-mapper.yang
opendaylight/netconf/mdsal-netconf-monitoring/pom.xml [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/MonitoringToMdsalWriter.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModule.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModuleFactory.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationService.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationServiceFactory.java [new file with mode: 0644]
opendaylight/netconf/mdsal-netconf-monitoring/src/main/yang/netconf-mdsal-monitoring.yang [new file with mode: 0644]
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/monitoring/NetconfMonitoringService.java
opendaylight/netconf/netconf-artifacts/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModule.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModuleFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModule.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModuleFactory.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/AggregatedNetconfOperationServiceFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java
opendaylight/netconf/netconf-impl/src/main/yang/netconf-northbound-impl.yang
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommitTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTrackerTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceFactoryListener.java [moved from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java with 79% similarity]
opendaylight/netconf/netconf-mapping-api/src/main/yang/netconf-northbound-mapper.yang
opendaylight/netconf/netconf-mdsal-config/src/main/resources/initial/08-netconf-mdsal.xml
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringActivator.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationServiceTest.java
opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java
opendaylight/netconf/pom.xml

index c63b39c74d50df358e2393624a4de99eb97bf839..5559f9277585ded7ba0b77eb12c4b29a9e5dfd98 100644 (file)
       <artifactId>sal-inmemory-datastore</artifactId>
     </dependency>
 
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>mdsal-netconf-connector</artifactId>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>mdsal-netconf-monitoring</artifactId>
+      </dependency>
+
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-netconf-connector</artifactId>
index 5b9f4a674a733a7850a40b83622b34b43b1e9fff..4b9f8c2288cb8db0e509e5b13774867ed1c62af8 100644 (file)
     </feature>
 
     <!-- TODO move to netconf features, however there are some weird dependencies on features-config-persister all over that cause cyclic dependencies-->
-    <feature name='odl-netconf-mdsal' version='${project.version}' description="OpenDaylight :: Netconf :: All">
+    <!-- TODO when installing this in pure karaf distro, many optimistic lock exceptions are thrown from config manager -->
+    <feature name='odl-netconf-mdsal' version='${project.version}' description="OpenDaylight :: Netconf :: Mdsal">
         <feature version='${config.version}'>odl-config-all</feature>
         <feature version='${netconf.version}'>odl-netconf-all</feature>
         <bundle>mvn:org.opendaylight.controller/netconf-ssh/${netconf.version}</bundle>
         <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
         <bundle>mvn:org.opendaylight.controller/mdsal-netconf-connector/${netconf.version}</bundle>
+        <bundle>mvn:org.opendaylight.controller/mdsal-netconf-monitoring/${netconf.version}</bundle>
         <!-- TODO 01-netconf.xml file requires netconf-config-dispatcher to be present and its part of netconf-connector features. Clean Up-->
         <bundle>mvn:org.opendaylight.controller/netconf-config-dispatcher/${config.version}</bundle>
         <configfile finalname='${config.configfile.directory}/${config.netconf.client.configfile}'>mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config</configfile>
index 4e94996634716590376611354356a7085e4e3d38..c69ee197be24dfa8db753ff96a99e13d37e186c3 100644 (file)
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-config-dispatcher</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>mdsal-netconf-connector</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>netconf-tcp</artifactId>
index a65502124bc92aab4fddd4bfae6d5327eab49c40..aa8287d70928690cd9c3f4c30247b4597f167fe4 100644 (file)
@@ -27,6 +27,7 @@
     <bundle>mvn:org.opendaylight.controller/ietf-netconf-monitoring-extension/${project.version}</bundle>
     <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf-inet-types.version}</bundle>
     <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf-yang-types.version}</bundle>
+    <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types-20130715/2013.07.15.7-SNAPSHOT</bundle>
   </feature>
   <feature name='odl-netconf-mapping-api' version='${project.version}' description="OpenDaylight :: Netconf :: Mapping API">
     <feature version='${project.version}'>odl-netconf-api</feature>
index b5927f0bd540519ca60aadd4b095df3e81acbc89..80451a1027713174d66a90ead14bd184ee4a3721 100644 (file)
@@ -55,7 +55,10 @@ final class NotificationHandler {
         passNotifications = true;
 
         for (final NetconfMessage cachedNotification : queue) {
-            passNotification(messageTransformer.toNotification(cachedNotification));
+            final CompositeNode parsedNotification = messageTransformer.toNotification(cachedNotification);
+            // TODO possible race condition here, because this exception is thrown occasionally
+            Preconditions.checkNotNull(parsedNotification, "Unable to parse received notification %s", cachedNotification);
+            passNotification(parsedNotification);
         }
 
         queue.clear();
@@ -74,7 +77,6 @@ final class NotificationHandler {
 
     private synchronized void passNotification(final CompositeNode parsedNotification) {
         logger.debug("{}: Forwarding notification {}", id, parsedNotification);
-        Preconditions.checkNotNull(parsedNotification);
 
         if(filter == null || filter.filterNotification(parsedNotification).isPresent()) {
             salFacade.onNotification(parsedNotification);
index b4ad89b55867a78b25d08f8682d438aee82f7e38..84756fc7135acae05a1aeccb7aed726a9027bf65 100644 (file)
@@ -9,7 +9,9 @@ module ietf-netconf-monitoring {
 
     import ietf-yang-types {
       prefix yang;
+      revision-date "2010-09-24";
     }
+
     import ietf-inet-types {
       prefix inet;
     }
index ccf751285a39c5675eaee79c5ec2c346d6c903ec..bf8bdb06f31dd37c3a27bb2e8236f041fad22f4f 100644 (file)
@@ -26,7 +26,15 @@ public class NetconfMdsalMapperModule extends org.opendaylight.controller.config
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return new MdsalNetconfOperationServiceFactory(getRootSchemaServiceDependency(), getDomBrokerDependency());
+        final MdsalNetconfOperationServiceFactory mdsalNetconfOperationServiceFactory = new MdsalNetconfOperationServiceFactory(getRootSchemaServiceDependency(), getDomBrokerDependency()) {
+            @Override
+            public void close() throws Exception {
+                super.close();
+                getMapperAggregatorDependency().onRemoveNetconfOperationServiceFactory(this);
+            }
+        };
+        getMapperAggregatorDependency().onAddNetconfOperationServiceFactory(mdsalNetconfOperationServiceFactory);
+        return mdsalNetconfOperationServiceFactory;
     }
 
 }
index df671e8f4f2ab07fd38e31d7cda55c2736f04f8b..1aa38eb80c0a1fab17ea8512cacce4bf83fd1fe7 100644 (file)
@@ -9,7 +9,12 @@
 package org.opendaylight.controller.netconf.mdsal.connector;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
+import org.opendaylight.controller.netconf.api.Capability;
+import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
 import org.opendaylight.controller.sal.core.api.model.SchemaService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -18,6 +23,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 public class CurrentSchemaContext implements SchemaContextListener, AutoCloseable {
     final AtomicReference<SchemaContext> currentContext = new AtomicReference<SchemaContext>();
     private final ListenerRegistration<SchemaContextListener> schemaContextListenerListenerRegistration;
+    private final Set<CapabilityListener> listeners = Collections.synchronizedSet(Sets.<CapabilityListener>newHashSet());
 
     public SchemaContext getCurrentContext() {
         Preconditions.checkState(currentContext.get() != null, "Current context not received");
@@ -31,11 +37,28 @@ public class CurrentSchemaContext implements SchemaContextListener, AutoCloseabl
     @Override
     public void onGlobalContextUpdated(final SchemaContext schemaContext) {
         currentContext.set(schemaContext);
+        // FIXME is notifying all the listeners from this callback wise ?
+        final Set<Capability> addedCaps = MdsalNetconfOperationServiceFactory.transformCapabilities(currentContext.get());
+        for (final CapabilityListener listener : listeners) {
+            listener.onCapabilitiesAdded(addedCaps);
+        }
     }
 
     @Override
     public void close() throws Exception {
+        listeners.clear();
         schemaContextListenerListenerRegistration.close();
         currentContext.set(null);
     }
+
+    public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
+        listener.onCapabilitiesAdded(MdsalNetconfOperationServiceFactory.transformCapabilities(currentContext.get()));
+        listeners.add(listener);
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+                listeners.remove(listener);
+            }
+        };
+    }
 }
\ No newline at end of file
index 9bd71c3c7ca9d893289f1753a59fc61403a44657..ebb0e9d3d1ac2d9bf364afcb236e151ebecb8af2 100644 (file)
@@ -49,11 +49,15 @@ public class MdsalNetconfOperationServiceFactory implements NetconfOperationServ
 
     @Override
     public Set<Capability> getCapabilities() {
+        return transformCapabilities(currentSchemaContext.getCurrentContext());
+    }
+
+    static Set<Capability> transformCapabilities(final SchemaContext currentContext1) {
         final Set<Capability> capabilities = new HashSet<>();
         // [RFC6241] 8.3.  Candidate Configuration Capability
         capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
 
-        final SchemaContext currentContext = currentSchemaContext.getCurrentContext();
+        final SchemaContext currentContext = currentContext1;
         final Set<Module> modules = currentContext.getModules();
         for (final Module module : modules) {
             if(currentContext.getModuleSource(module).isPresent()) {
@@ -69,13 +73,7 @@ public class MdsalNetconfOperationServiceFactory implements NetconfOperationServ
 
     @Override
     public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
-        // TODO provide notifications about changed schemas
-        return new AutoCloseable() {
-            @Override
-            public void close() throws Exception {
-
-            }
-        };
+        return currentSchemaContext.registerCapabilityListener(listener);
     }
 
     private static class BasicCapability implements Capability {
index b1d04106d70dd2b3f6c35a3bf614a2ed4097fda8..9d9966e8f1d5e922c193c80140297069782741ee 100644 (file)
@@ -44,6 +44,15 @@ module netconf-mdsal-mapper {
                     }
                 }
             }
+
+            container mapper-aggregator {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity nnm:netconf-mapper-registry;
+                    }
+                }
+            }
         }
     }
 
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/pom.xml b/opendaylight/netconf/mdsal-netconf-monitoring/pom.xml
new file mode 100644 (file)
index 0000000..3e78dd1
--- /dev/null
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>netconf-subsystem</artifactId>
+    <version>0.3.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>mdsal-netconf-monitoring</artifactId>
+  <packaging>bundle</packaging>
+  <name>${project.artifactId}</name>
+
+  <dependencies>
+    <!-- compile dependencies -->
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-mapping-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-monitoring</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>netconf-util</artifactId>
+    </dependency>
+      <dependency>
+          <groupId>org.opendaylight.controller</groupId>
+          <artifactId>sal-binding-config</artifactId>
+      </dependency>
+
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>mockito-configuration</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-inet-types</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+      </plugin>
+        <plugin>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin</artifactId>
+            <executions>
+                <execution>
+                    <id>config</id>
+                    <goals>
+                        <goal>generate-sources</goal>
+                    </goals>
+                    <configuration>
+                        <codeGenerators>
+                            <generator>
+                                <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                                <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                                <additionalConfiguration>
+                                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                                </additionalConfiguration>
+                            </generator>
+                            <generator>
+                                <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                            </generator>
+                        </codeGenerators>
+                        <inspectDependencies>true</inspectDependencies>
+                    </configuration>
+                </execution>
+            </executions>
+            <dependencies>
+                <dependency>
+                    <groupId>org.opendaylight.controller</groupId>
+                    <artifactId>yang-jmx-generator-plugin</artifactId>
+                    <version>${config.version}</version>
+                </dependency>
+            </dependencies>
+        </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/MonitoringToMdsalWriter.java b/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/MonitoringToMdsalWriter.java
new file mode 100644 (file)
index 0000000..50958e4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+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 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.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class MonitoringToMdsalWriter implements AutoCloseable, NetconfMonitoringService.MonitoringListener, BindingAwareProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MonitoringToMdsalWriter.class);
+
+    private final NetconfMonitoringService serverMonitoringDependency;
+    private DataBroker dataBroker;
+
+    public MonitoringToMdsalWriter(final NetconfMonitoringService serverMonitoringDependency) {
+        this.serverMonitoringDependency = serverMonitoringDependency;
+    }
+
+    @Override
+    public void close() {
+        final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        tx.delete(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(NetconfState.class));
+        final CheckedFuture<Void, TransactionCommitFailedException> submit = tx.submit();
+
+        Futures.addCallback(submit, new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(final Void aVoid) {
+                LOG.debug("Netconf state cleared successfully");
+            }
+
+            @Override
+            public void onFailure(final Throwable throwable) {
+                LOG.warn("Unable to clear netconf state", throwable);
+            }
+        });
+    }
+
+    @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);
+        // FIXME first attempt (right after we register to binding broker) always fails
+        // Is it due to the fact that we are writing from the onSessionInitiated callback ?
+        final CheckedFuture<Void, TransactionCommitFailedException> submit = tx.submit();
+
+        Futures.addCallback(submit, new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(final Void aVoid) {
+                LOG.debug("Netconf state updated successfully");
+            }
+
+            @Override
+            public void onFailure(final Throwable throwable) {
+                LOG.warn("Unable to update netconf state", throwable);
+            }
+        });
+    }
+
+    @Override
+    public void onSessionInitiated(final BindingAwareBroker.ProviderContext providerContext) {
+        dataBroker = providerContext.getSALService(DataBroker.class);
+        serverMonitoringDependency.registerListener(this);
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModule.java b/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModule.java
new file mode 100644 (file)
index 0000000..dadc0f4
--- /dev/null
@@ -0,0 +1,149 @@
+package org.opendaylight.controller.config.yang.netconf.mdsal.monitoring;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.controller.netconf.api.Capability;
+import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.monitoring.GetSchema;
+import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
+
+public class NetconfMdsalMonitoringMapperModule extends org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.AbstractNetconfMdsalMonitoringMapperModule {
+    public NetconfMdsalMonitoringMapperModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NetconfMdsalMonitoringMapperModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.NetconfMdsalMonitoringMapperModule oldModule, final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        final NetconfMonitoringService serverMonitoringDependency = getServerMonitoringDependency();
+
+        final MonitoringToMdsalWriter monitoringToMdsalWriter = new MonitoringToMdsalWriter(serverMonitoringDependency);
+        getBindingAwareBrokerDependency().registerProvider(monitoringToMdsalWriter);
+
+        final MdSalMonitoringMapperFactory mdSalMonitoringMapperFactory = new MdSalMonitoringMapperFactory(new MdsalMonitoringMapper(serverMonitoringDependency)) {
+            @Override
+            public void close() {
+                super.close();
+                monitoringToMdsalWriter.close();
+                getAggregatorDependency().onRemoveNetconfOperationServiceFactory(this);
+            }
+        };
+
+        getAggregatorDependency().onAddNetconfOperationServiceFactory(mdSalMonitoringMapperFactory);
+        return mdSalMonitoringMapperFactory;
+
+    }
+
+    // FIXME almost exactly same code as in netconf-monitoring, refactor
+    private static class MdSalMonitoringMapperFactory implements NetconfOperationServiceFactory, AutoCloseable {
+
+        private final NetconfOperationService operationService;
+
+        private static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
+
+            @Override
+            public String getCapabilityUri() {
+                return MonitoringConstants.URI;
+            }
+
+            @Override
+            public Optional<String> getModuleNamespace() {
+                return Optional.of(MonitoringConstants.NAMESPACE);
+            }
+
+            @Override
+            public Optional<String> getModuleName() {
+                return Optional.of(MonitoringConstants.MODULE_NAME);
+            }
+
+            @Override
+            public Optional<String> getRevision() {
+                return Optional.of(MonitoringConstants.MODULE_REVISION);
+            }
+
+            @Override
+            public Optional<String> getCapabilitySchema() {
+                return Optional.absent();
+            }
+
+            @Override
+            public Collection<String> getLocation() {
+                return Collections.emptyList();
+            }
+        });
+
+        private static final AutoCloseable AUTO_CLOSEABLE = new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+                // NOOP
+            }
+        };
+
+        private final List<CapabilityListener> listeners = new ArrayList<>();
+
+        public MdSalMonitoringMapperFactory(final NetconfOperationService operationService) {
+            this.operationService = operationService;
+        }
+
+        @Override
+        public NetconfOperationService createService(final String netconfSessionIdForReporting) {
+            return operationService;
+        }
+
+        @Override
+        public Set<Capability> getCapabilities() {
+            return CAPABILITIES;
+        }
+
+        @Override
+        public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
+            listener.onCapabilitiesAdded(getCapabilities());
+            listeners.add(listener);
+            return AUTO_CLOSEABLE;
+        }
+
+        @Override
+        public void close() {
+            for (final CapabilityListener listener : listeners) {
+                listener.onCapabilitiesRemoved(getCapabilities());
+            }
+        }
+    }
+
+
+    private static class MdsalMonitoringMapper implements NetconfOperationService {
+
+        private final NetconfMonitoringService serverMonitoringDependency;
+
+        public MdsalMonitoringMapper(final NetconfMonitoringService serverMonitoringDependency) {
+            this.serverMonitoringDependency = serverMonitoringDependency;
+        }
+
+        @Override
+        public Set<NetconfOperation> getNetconfOperations() {
+            return Collections.<NetconfOperation>singleton(new GetSchema(serverMonitoringDependency));
+        }
+
+        @Override
+        public void close() {
+            // NOOP
+        }
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModuleFactory.java b/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/monitoring/NetconfMdsalMonitoringMapperModuleFactory.java
new file mode 100644 (file)
index 0000000..e0d4593
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: netconf-mdsal-monitoring yang module local name: netconf-mdsal-monitoring-mapper
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Feb 18 10:22:17 CET 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netconf.mdsal.monitoring;
+public class NetconfMdsalMonitoringMapperModuleFactory extends org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.AbstractNetconfMdsalMonitoringMapperModuleFactory {
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationService.java b/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationService.java
new file mode 100644 (file)
index 0000000..9ae4df4
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+* Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.netconf.monitoring;
+
+import com.google.common.collect.Sets;
+import java.util.Set;
+import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.monitoring.Get;
+import org.opendaylight.controller.netconf.monitoring.GetSchema;
+
+public class NetconfMonitoringOperationService implements NetconfOperationService {
+
+    private final NetconfMonitoringService monitor;
+
+    public NetconfMonitoringOperationService(final NetconfMonitoringService monitor) {
+        this.monitor = monitor;
+    }
+
+    @Override
+    public Set<NetconfOperation> getNetconfOperations() {
+        return Sets.<NetconfOperation>newHashSet(new Get(monitor), new GetSchema(monitor));
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationServiceFactory.java b/opendaylight/netconf/mdsal-netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/NetconfMonitoringOperationServiceFactory.java
new file mode 100644 (file)
index 0000000..78c2368
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.monitoring;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.controller.netconf.api.Capability;
+import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+
+/**
+* Created by mmarsale on 18.2.2015.
+*/
+public class NetconfMonitoringOperationServiceFactory implements NetconfOperationServiceFactory, AutoCloseable {
+
+    private final NetconfMonitoringOperationService operationService;
+
+    private static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
+
+        @Override
+        public String getCapabilityUri() {
+            return MonitoringConstants.URI;
+        }
+
+        @Override
+        public Optional<String> getModuleNamespace() {
+            return Optional.of(MonitoringConstants.NAMESPACE);
+        }
+
+        @Override
+        public Optional<String> getModuleName() {
+            return Optional.of(MonitoringConstants.MODULE_NAME);
+        }
+
+        @Override
+        public Optional<String> getRevision() {
+            return Optional.of(MonitoringConstants.MODULE_REVISION);
+        }
+
+        @Override
+        public Optional<String> getCapabilitySchema() {
+            return Optional.absent();
+        }
+
+        @Override
+        public Collection<String> getLocation() {
+            return Collections.emptyList();
+        }
+    });
+
+    private static final AutoCloseable AUTO_CLOSEABLE = new AutoCloseable() {
+        @Override
+        public void close() throws Exception {
+            // NOOP
+        }
+    };
+
+    private final List<CapabilityListener> listeners = new ArrayList<>();
+
+    public NetconfMonitoringOperationServiceFactory(final NetconfMonitoringOperationService operationService) {
+        this.operationService = operationService;
+    }
+
+    @Override
+    public NetconfOperationService createService(final String netconfSessionIdForReporting) {
+        return operationService;
+    }
+
+    @Override
+    public Set<Capability> getCapabilities() {
+        return CAPABILITIES;
+    }
+
+    @Override
+    public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
+        listener.onCapabilitiesAdded(getCapabilities());
+        listeners.add(listener);
+        return AUTO_CLOSEABLE;
+    }
+
+    @Override
+    public void close() {
+        for (final CapabilityListener listener : listeners) {
+            listener.onCapabilitiesRemoved(getCapabilities());
+        }
+    }
+}
diff --git a/opendaylight/netconf/mdsal-netconf-monitoring/src/main/yang/netconf-mdsal-monitoring.yang b/opendaylight/netconf/mdsal-netconf-monitoring/src/main/yang/netconf-mdsal-monitoring.yang
new file mode 100644 (file)
index 0000000..68a248e
--- /dev/null
@@ -0,0 +1,60 @@
+module netconf-mdsal-monitoring {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:monitoring";
+    prefix "nmmonitor";
+
+    import netconf-northbound-mapper { prefix nnm; revision-date 2015-01-14; }
+    import opendaylight-md-sal-binding {prefix md-sal-binding; revision-date 2013-10-28;}
+    import netconf-northbound { prefix nn; revision-date 2015-01-14; }
+    import config { prefix config; revision-date 2013-04-05; }
+
+    organization "Cisco Systems, Inc.";
+
+    description
+        "This module contains the base YANG definitions for
+         an MD-SAL monitoring mapper implementation";
+
+    revision "2015-02-18" {
+        description
+            "Initial revision.";
+    }
+
+    identity netconf-mdsal-monitoring-mapper {
+        base config:module-type;
+        config:provided-service nnm:netconf-northbound-mapper;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case netconf-mdsal-monitoring-mapper {
+            when "/config:modules/config:module/config:type = 'netconf-mdsal-monitoring-mapper'";
+
+            container server-monitoring {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity nn:netconf-server-monitoring;
+                    }
+                }
+            }
+
+            container aggregator {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity nnm:netconf-mapper-registry;
+                    }
+                }
+            }
+
+            container binding-aware-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+        }
+    }
+
+}
index 3f0e1a1aa58b795ec501d1e0790da041306aa384..d22412c7cf11df2447d19a184c7c5966159a5f86 100644 (file)
@@ -8,7 +8,8 @@
 package org.opendaylight.controller.netconf.api.monitoring;
 
 import com.google.common.base.Optional;
-import java.util.Set;
+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;
 
@@ -20,6 +21,16 @@ public interface NetconfMonitoringService extends CapabilityListener, SessionLis
 
     String getSchemaForCapability(String moduleName, Optional<String> revision);
 
-    Set<String> getCapabilities();
+    Capabilities getCapabilities();
 
+    /**
+     * Allows push based state information transfer. After the listener is registered, current state is pushed to the listener.
+     */
+    AutoCloseable registerListener(MonitoringListener listener);
+
+    interface MonitoringListener {
+
+        // TODO more granular updates would make sense
+        void onStateChanged(NetconfState state);
+    }
 }
index 12489339154075ae01545c2083c531cfd6e2f3e2..d27ea558126ece253720b77832a9783a13f855ee 100644 (file)
                 <artifactId>netconf-monitoring</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>mdsal-netconf-monitoring</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>${project.groupId}</groupId>
                 <artifactId>netconf-netty-util</artifactId>
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModule.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModule.java
new file mode 100644 (file)
index 0000000..284c600
--- /dev/null
@@ -0,0 +1,22 @@
+package org.opendaylight.controller.config.yang.config.netconf.northbound.impl;
+
+import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
+
+public class NetconfMapperAggregatorModule extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfMapperAggregatorModule {
+    public NetconfMapperAggregatorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NetconfMapperAggregatorModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.config.netconf.northbound.impl.NetconfMapperAggregatorModule oldModule, final java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {}
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new AggregatedNetconfOperationServiceFactory();
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModuleFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfMapperAggregatorModuleFactory.java
new file mode 100644 (file)
index 0000000..0e415bd
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: netconf-northbound-impl yang module local name: netconf-mapper-aggregator
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Feb 17 17:24:19 CET 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.netconf.northbound.impl;
+public class NetconfMapperAggregatorModuleFactory extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfMapperAggregatorModuleFactory {
+
+}
index c1570f4311f67f9b7badfb609e30f55144e308bc..3c476608a2126b7a4a60eece2a03deca71037636 100644 (file)
@@ -7,7 +7,6 @@ import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
 import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 
 public class NetconfServerDispatcherModule extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfServerDispatcherModule {
@@ -28,7 +27,7 @@ public class NetconfServerDispatcherModule extends org.opendaylight.controller.c
     public java.lang.AutoCloseable createInstance() {
 
         final AggregatedNetconfOperationServiceFactory aggregatedOpProvider = getAggregatedOpProvider();
-        final NetconfMonitoringService monitoringService = startMonitoringService(aggregatedOpProvider);
+        final NetconfMonitoringService monitoringService = getServerMonitorDependency();
         final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
                 getTimerDependency(), aggregatedOpProvider, new SessionIdProvider(), getConnectionTimeoutMillis(), CommitNotifier.NoopCommitNotifier.getInstance(), monitoringService);
         final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer(
@@ -44,10 +43,6 @@ public class NetconfServerDispatcherModule extends org.opendaylight.controller.c
 
     }
 
-    private NetconfMonitoringServiceImpl startMonitoringService(final AggregatedNetconfOperationServiceFactory netconfOperationProvider) {
-        return new NetconfMonitoringServiceImpl(netconfOperationProvider);
-    }
-
     private AggregatedNetconfOperationServiceFactory getAggregatedOpProvider() {
         final AggregatedNetconfOperationServiceFactory netconfOperationProvider = new AggregatedNetconfOperationServiceFactory();
         for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getMappersDependency()) {
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModule.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModule.java
new file mode 100644 (file)
index 0000000..dc18cd3
--- /dev/null
@@ -0,0 +1,24 @@
+package org.opendaylight.controller.config.yang.config.netconf.northbound.impl;
+
+import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
+
+public class NetconfServerMonitoringModule extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfServerMonitoringModule {
+    public NetconfServerMonitoringModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public NetconfServerMonitoringModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.netconf.northbound.impl.NetconfServerMonitoringModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new NetconfMonitoringServiceImpl(getAggregatorDependency());
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModuleFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerMonitoringModuleFactory.java
new file mode 100644 (file)
index 0000000..fe74486
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: netconf-northbound-impl yang module local name: netconf-server-monitoring-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Feb 17 17:24:19 CET 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.netconf.northbound.impl;
+public class NetconfServerMonitoringModuleFactory extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfServerMonitoringModuleFactory {
+
+}
index 8f2c39df063a813696735daa66d8e7831f9a756c..0cf2dbc281e1503e0ff1dd8d362285919c527c9a 100644 (file)
@@ -55,9 +55,9 @@ public final class NetconfServerSession extends AbstractNetconfSession<NetconfSe
 
     @Override
     protected void sessionUp() {
-        super.sessionUp();
         Preconditions.checkState(loginTime == null, "Session is already up");
         this.loginTime = new Date();
+        super.sessionUp();
     }
 
     public void onIncommingRpcSuccess() {
index 9510a61a6edd0a234ea9ee1fc5237c144fdd59ec..a6531d3c63d09b6fc64a1c0afd08e3f21041b2df 100644 (file)
@@ -45,6 +45,8 @@ public class NetconfServerSessionListener implements NetconfSessionListener<Netc
     @Override
     public void onSessionUp(final NetconfServerSession netconfNetconfServerSession) {
         monitoringService.onSessionUp(netconfNetconfServerSession);
+        // FIXME monitoring service should be also notified about all the other changes to netconf session (from ietf-netconf-monitoring point of view)
+        // This means also notifying after every message is processed
     }
 
     @Override
index 996bb275877dd74f336db4a410e765fb12f25424..cf489608cab7c2a5ff36e2253c7fcc9516a296e4 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
@@ -120,7 +121,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF
     }
 
     private NetconfHelloMessage createHelloMessage(final long sessionId, final NetconfMonitoringService capabilityProvider) throws NetconfDocumentedException {
-        return NetconfHelloMessage.createServerHello(Sets.union(capabilityProvider.getCapabilities(), baseCapabilities), sessionId);
+        return NetconfHelloMessage.createServerHello(Sets.union(DefaultCommit.transformCapabilities(capabilityProvider.getCapabilities()), baseCapabilities), sessionId);
     }
 
 }
index ca41338c36e523fcd1a84f7d15cb157d1c53eeb0..8b2c02bcd42cd916c2597b109762b686f68ea6c8 100644 (file)
@@ -8,8 +8,12 @@
 
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
+import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
 import java.io.InputStream;
+import java.util.Set;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
@@ -20,6 +24,8 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedEx
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -73,12 +79,22 @@ public class DefaultCommit extends AbstractNetconfOperation {
             removePersisterAttributes(requestMessage);
             Element cfgSnapshot = getConfigSnapshot(operationRouter);
             LOG.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
-            notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
+            notificationProducer.sendCommitNotification("ok", cfgSnapshot, transformCapabilities(cap.getCapabilities()));
         }
 
         return subsequentOperation.execute(requestMessage);
     }
 
+    // FIXME move somewhere to util since this is required also by negotiatiorFactory
+    public static Set<String> transformCapabilities(final Capabilities capabilities) {
+        return Sets.newHashSet(Collections2.transform(capabilities.getCapability(), new Function<Uri, String>() {
+            @Override
+            public String apply(final Uri uri) {
+                return uri.getValue();
+            }
+        }));
+    }
+
     @Override
     protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
         throw new UnsupportedOperationException("Never gets called");
index c299ac7d1a4f5623e89dbfd8bade655b8044cc89..ae68ecc120b5fb502a0c362d023ff81b7f469509 100644 (file)
@@ -22,12 +22,13 @@ import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactoryListener;
 import org.opendaylight.controller.netconf.util.CloseableUtil;
 
 /**
  * NetconfOperationService aggregator. Makes a collection of operation services accessible as one.
  */
-public class AggregatedNetconfOperationServiceFactory implements NetconfOperationServiceFactory, NetconfOperationServiceFactoryListener {
+public class AggregatedNetconfOperationServiceFactory implements NetconfOperationServiceFactory, NetconfOperationServiceFactoryListener, AutoCloseable {
 
     private final Set<NetconfOperationServiceFactory> factories = new HashSet<>();
     private final Multimap<NetconfOperationServiceFactory, AutoCloseable> registrations = HashMultimap.create();
@@ -96,6 +97,16 @@ public class AggregatedNetconfOperationServiceFactory implements NetconfOperatio
         return new AggregatedNetconfOperation(factories, netconfSessionIdForReporting);
     }
 
+    @Override
+    public synchronized void close() throws Exception {
+        factories.clear();
+        for (AutoCloseable reg : registrations.values()) {
+            reg.close();
+        }
+        registrations.clear();
+        listeners.clear();
+    }
+
     private static final class AggregatedNetconfOperation implements NetconfOperationService {
 
         private final Set<NetconfOperationService> services;
index 63e837fc18d5c97b4de8f31692b9b5d6c6cc29bf..1e35597d9a6239d8566005b8bf3775b86282b082 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProduce
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactoryListener;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
index 8e5c1a7da3e1b947f1de1429f11bddcc81fb6cb6..b02137b748c71584841df04817a9f8bb552147e2 100644 (file)
@@ -13,7 +13,9 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import io.netty.util.internal.ConcurrentSet;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -27,7 +29,11 @@ import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSessi
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+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.NetconfStateBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
+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.CapabilitiesBuilder;
 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.SchemasBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
@@ -39,7 +45,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class NetconfMonitoringServiceImpl implements NetconfMonitoringService {
+public class NetconfMonitoringServiceImpl implements NetconfMonitoringService, AutoCloseable {
 
     private static final Schema.Location NETCONF_LOCATION = new Schema.Location(Schema.Location.Enumeration.NETCONF);
     private static final List<Schema.Location> NETCONF_LOCATIONS = ImmutableList.of(NETCONF_LOCATION);
@@ -50,18 +56,18 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService {
             return input.toManagementSession();
         }
     };
-
-    private final Set<NetconfManagementSession> sessions = new ConcurrentSet<>();
-    private final NetconfOperationServiceFactory netconfOperationProvider;
-    private final Map<String, Capability> capabilities = new ConcurrentHashMap<>();
-    private static final Function<Capability, String> CAPABILITY_TO_URI = new Function<Capability, String>() {
+    private static final Function<Capability, Uri> CAPABILITY_TO_URI = new Function<Capability, Uri>() {
         @Override
-        public String apply(final Capability input) {
-            return input.getCapabilityUri();
+        public Uri apply(final Capability input) {
+            return new Uri(input.getCapabilityUri());
         }
     };
 
-    // FIXME check threadsafety
+    private final Set<NetconfManagementSession> sessions = new ConcurrentSet<>();
+    private final NetconfOperationServiceFactory netconfOperationProvider;
+    private final Map<Uri, Capability> capabilities = new ConcurrentHashMap<>();
+
+    private final Set<MonitoringListener> listeners = Sets.newHashSet();
 
     public NetconfMonitoringServiceImpl(final NetconfOperationServiceFactory netconfOperationProvider) {
         this.netconfOperationProvider = netconfOperationProvider;
@@ -69,26 +75,28 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService {
     }
 
     @Override
-    public void onSessionUp(final NetconfManagementSession session) {
+    public synchronized void onSessionUp(final NetconfManagementSession session) {
         LOG.debug("Session {} up", session);
         Preconditions.checkState(!sessions.contains(session), "Session %s was already added", session);
         sessions.add(session);
+        notifyListeners();
     }
 
     @Override
-    public void onSessionDown(final NetconfManagementSession session) {
+    public synchronized void onSessionDown(final NetconfManagementSession session) {
         LOG.debug("Session {} down", session);
         Preconditions.checkState(sessions.contains(session), "Session %s not present", session);
         sessions.remove(session);
+        notifyListeners();
     }
 
     @Override
-    public Sessions getSessions() {
+    public synchronized Sessions getSessions() {
         return new SessionsBuilder().setSession(ImmutableList.copyOf(Collections2.transform(sessions, SESSION_FUNCTION))).build();
     }
 
     @Override
-    public Schemas getSchemas() {
+    public synchronized Schemas getSchemas() {
         try {
             return transformSchemas(netconfOperationProvider.getCapabilities());
         } catch (final RuntimeException e) {
@@ -99,7 +107,7 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService {
     }
 
     @Override
-    public String getSchemaForCapability(final String moduleName, final Optional<String> revision) {
+    public synchronized String getSchemaForCapability(final String moduleName, final Optional<String> revision) {
 
         // FIXME not effective at all
 
@@ -146,8 +154,28 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService {
     }
 
     @Override
-    public Set<String> getCapabilities() {
-        return capabilities.keySet();
+    public synchronized Capabilities getCapabilities() {
+        return new CapabilitiesBuilder().setCapability(Lists.newArrayList(capabilities.keySet())).build();
+    }
+
+    @Override
+    public synchronized AutoCloseable registerListener(final MonitoringListener listener) {
+        listeners.add(listener);
+        listener.onStateChanged(getCurrentNetconfState());
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+                listeners.remove(listener);
+            }
+        };
+    }
+
+    private NetconfState getCurrentNetconfState() {
+        return new NetconfStateBuilder()
+                .setCapabilities(getCapabilities())
+                .setSchemas(getSchemas())
+                .setSessions(getSessions())
+                .build();
     }
 
     private static Schemas transformSchemas(final Set<Capability> caps) {
@@ -195,15 +223,30 @@ public class NetconfMonitoringServiceImpl implements NetconfMonitoringService {
     }
 
     @Override
-    public void onCapabilitiesAdded(final Set<Capability> addedCaps) {
-        // FIXME what check for duplicates
+    public synchronized void onCapabilitiesAdded(final Set<Capability> addedCaps) {
+        // FIXME howto check for duplicates
         this.capabilities.putAll(Maps.uniqueIndex(addedCaps, CAPABILITY_TO_URI));
+        notifyListeners();
+    }
+
+    private void notifyListeners() {
+        for (final MonitoringListener listener : listeners) {
+            listener.onStateChanged(getCurrentNetconfState());
+        }
     }
 
     @Override
-    public void onCapabilitiesRemoved(final Set<Capability> addedCaps) {
+    public synchronized void onCapabilitiesRemoved(final Set<Capability> addedCaps) {
         for (final Capability addedCap : addedCaps) {
             capabilities.remove(addedCap.getCapabilityUri());
         }
+        notifyListeners();
+    }
+
+    @Override
+    public synchronized void close() throws Exception {
+        listeners.clear();
+        sessions.clear();
+        capabilities.clear();
     }
 }
index fb5a2b325efb1301befb8bb7882644d7dd25d131..9d58bd911c828bfcba3b185b3db20dc9c0d87985 100644 (file)
@@ -143,8 +143,8 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
             if (!handlingPriority.equals(HandlingPriority.CANNOT_HANDLE)) {
 
                 Preconditions.checkState(!sortedPriority.containsKey(handlingPriority),
-                        "Multiple %s available to handle message %s with priority %s",
-                        NetconfOperation.class.getName(), message, handlingPriority);
+                        "Multiple %s available to handle message %s with priority %s, %s and %s",
+                        NetconfOperation.class.getName(), message, handlingPriority, netconfOperation, sortedPriority.get(handlingPriority));
                 sortedPriority.put(handlingPriority, netconfOperation);
             }
         }
index 9a077a6130bb630cf9fdf5923e78a46eaaf6933b..d97ac909227fa937054ed18dd3ff159b29efedc3 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.netconf.impl.osgi;
 
 import org.opendaylight.controller.netconf.api.util.NetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactoryListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
@@ -40,8 +41,9 @@ class NetconfOperationServiceFactoryTracker extends
     @Override
     public void removedService(ServiceReference<NetconfOperationServiceFactory> reference,
             NetconfOperationServiceFactory netconfOperationServiceFactory) {
-        if (netconfOperationServiceFactory != null)
+        if (netconfOperationServiceFactory != null) {
             factoriesListener.onRemoveNetconfOperationServiceFactory(netconfOperationServiceFactory);
+        }
     }
 
 }
index 6ca0a7781c815d08966397941080b1394d793863..7ad1fef55da1975e486012e690b8de0d929f3a15 100644 (file)
@@ -67,6 +67,15 @@ module netconf-northbound-impl {
                 }
             }
 
+            container server-monitor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity nn:netconf-server-monitoring;
+                    }
+                }
+            }
+
             container timer {
                 uses config:service-ref {
                     refine type {
@@ -77,4 +86,43 @@ module netconf-northbound-impl {
         }
     }
 
+
+    identity netconf-server-monitoring-impl {
+            base config:module-type;
+            config:provided-service nn:netconf-server-monitoring;
+            config:java-name-prefix NetconfServerMonitoring;
+    }
+
+    // TODO Monitoring could expose the monitoring data over JMX...
+
+    augment "/config:modules/config:module/config:configuration" {
+        case netconf-server-monitoring-impl {
+            when "/config:modules/config:module/config:type = 'netconf-server-monitoring-impl'";
+
+            container aggregator {
+                uses config:service-ref {
+                    refine type {
+                        config:required-identity nnm:netconf-northbound-mapper;
+                    }
+                }
+            }
+
+        }
+    }
+
+    identity netconf-mapper-aggregator {
+        base config:module-type;
+        config:provided-service nnm:netconf-northbound-mapper;
+        config:provided-service nnm:netconf-mapper-registry;
+        config:java-name-prefix NetconfMapperAggregator;
+        description "Aggregated operation provider for netconf servers. Joins all the operations and capabilities of all the mappers it aggregates and exposes them as a single service. The dependency orientation is reversed in order to prevent cyclic dependencies when monitoring service is considered";
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case netconf-mapper-aggregator {
+            when "/config:modules/config:module/config:type = 'netconf-mapper-aggregator'";
+
+        }
+    }
+
 }
\ No newline at end of file
index 36dfb6f31baf16892b2f556fee707892a86ee4f6..512a127d224f80190757d85d98b5682e91e038a7 100644 (file)
@@ -12,6 +12,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anySetOf;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -73,6 +74,8 @@ import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.CapabilitiesBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -121,7 +124,15 @@ public class ConcurrentClientsTest {
         NetconfMonitoringService monitoring = mock(NetconfMonitoringService.class);
         doNothing().when(monitoring).onSessionUp(any(NetconfServerSession.class));
         doNothing().when(monitoring).onSessionDown(any(NetconfServerSession.class));
-        doReturn(Collections.emptySet()).when(monitoring).getCapabilities();
+        doReturn(new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+
+            }
+        }).when(monitoring).registerListener(any(NetconfMonitoringService.MonitoringListener.class));
+        doNothing().when(monitoring).onCapabilitiesAdded(anySetOf(Capability.class));
+        doNothing().when(monitoring).onCapabilitiesRemoved(anySetOf(Capability.class));
+        doReturn(new CapabilitiesBuilder().setCapability(Collections.<Uri>emptyList()).build()).when(monitoring).getCapabilities();
         return monitoring;
     }
 
index aa8c0a0f60f0a6ccb8ede18eef89a47549ee8f36..0c7406543fb7ba3456c20f71b8ae718c8fbbe04f 100644 (file)
@@ -18,7 +18,7 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import com.google.common.collect.Sets;
+import java.util.Collections;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
@@ -29,6 +29,8 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.CapabilitiesBuilder;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
@@ -50,7 +52,7 @@ public class DefaultCommitTest {
         notifier = mock(DefaultCommitNotificationProducer.class);
         doNothing().when(notifier).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
         cap = mock(NetconfMonitoringService.class);
-        doReturn(Sets.newHashSet()).when(cap).getCapabilities();
+        doReturn(new CapabilitiesBuilder().setCapability(Collections.<Uri>emptyList()).build()).when(cap).getCapabilities();
         Document rpcData = XmlFileLoader.xmlFileToDocument("netconfMessages/editConfig_expectedResult.xml");
         doReturn(rpcData).when(router).onNetconfMessage(any(Document.class), any(NetconfServerSession.class));
         commit = new DefaultCommit(notifier, cap, "", router);
index 8cb569eaa283a974726ce3fab657f663fc72abb5..c75cdcd27a139db748db23d03c6fed5f8f767fc6 100644 (file)
@@ -22,6 +22,7 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.netconf.api.util.NetconfConstants;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactoryListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.ServiceReference;
index 379c23af3ca1797eea4a4a01addfa142cff76d4d..c421a46fdf1662405b18390e81df1c6945a660fe 100644 (file)
@@ -80,8 +80,8 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
         }
 
         notificationVerifier.assertNotificationCount(2);
-        notificationVerifier.assertNotificationContent(0, 0, 0, 9);
-        notificationVerifier.assertNotificationContent(1, 4, 3, 9);
+        notificationVerifier.assertNotificationContent(0, 0, 0, 8);
+        notificationVerifier.assertNotificationContent(1, 4, 3, 8);
 
         mockedAggregator.assertSnapshotCount(2);
         // Capabilities are stripped for persister
index a709665c63a1e2293a70c2b4d4f118fdd863750a..3ffecde700e894dd144d935eab4d806e061aadde 100644 (file)
@@ -19,4 +19,9 @@ module netconf-northbound-mapper {
         config:java-class "org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory";
     }
 
+    identity netconf-mapper-registry {
+        base "config:service-type";
+        config:java-class "org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactoryListener";
+    }
+
 }
\ No newline at end of file
index 042447b1e65cca2d20d28664f4c690e22baefc1f..4ca3c99e813c0711865a3ef704f60e52014c8c93 100644 (file)
                   <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
                   <name>inmemory-data-broker</name>
               </dom-broker>
+              <mapper-aggregator xmlns="urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:mapper">
+                  <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">prefix:netconf-mapper-registry</type>
+                  <name>mapper-aggregator-registry</name>
+              </mapper-aggregator>
           </module>
 
           <module>
               <name>netconf-mdsal-server-dispatcher</name>
               <mappers xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl">
                   <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">dom:netconf-northbound-mapper</type>
-                  <name>netconf-mdsal-mapper</name>
+                  <name>mapper-aggregator</name>
               </mappers>
+              <server-monitor xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl">
+                  <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound">prefix:netconf-server-monitoring</type>
+                  <name>server-monitor</name>
+              </server-monitor>
               <boss-thread-group xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl">
                   <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netty">prefix:netty-threadgroup</type>
                   <name>global-boss-group</name>
               </timer>
           </module>
 
+          <module>
+              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:monitoring">prefix:netconf-mdsal-monitoring-mapper</type>
+              <name>netconf-mdsal-monitoring-mapper</name>
+              <server-monitoring xmlns="urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:monitoring">
+                  <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound">prefix:netconf-server-monitoring</type>
+                  <name>server-monitor</name>
+              </server-monitoring>
+              <binding-aware-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:monitoring">
+                  <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">prefix:binding-broker-osgi-registry</type>
+                  <name>binding-osgi-broker</name>
+              </binding-aware-broker>
+              <aggregator xmlns="urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:monitoring">
+                  <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">prefix:netconf-mapper-registry</type>
+                  <name>mapper-aggregator-registry</name>
+              </aggregator>
+          </module>
+
+          <module>
+              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl">prefix:netconf-mapper-aggregator</type>
+              <name>mapper-aggregator</name>
+          </module>
+
+          <module>
+              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl">prefix:netconf-server-monitoring-impl</type>
+              <name>server-monitor</name>
+              <aggregator xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl">
+                  <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">dom:netconf-northbound-mapper</type>
+                  <name>mapper-aggregator</name>
+              </aggregator>
+          </module>
+
           <module>
               <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:ssh">prefix:netconf-northbound-ssh</type>
               <name>netconf-mdsal-ssh-server</name>
       </modules>
 
         <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+            <service>
+                <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound">prefix:netconf-server-monitoring</type>
+                <instance>
+                    <name>server-monitor</name>
+                    <provider>/modules/module[type='netconf-server-monitoring-impl'][name='server-monitor']</provider>
+                </instance>
+            </service>
             <service>
                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">prefix:netconf-northbound-mapper</type>
                 <instance>
                     <provider>/modules/module[type='netconf-mdsal-mapper'][name='netconf-mdsal-mapper']</provider>
                 </instance>
             </service>
+            <service>
+                <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">prefix:netconf-northbound-mapper</type>
+                <instance>
+                    <name>mapper-aggregator</name>
+                    <provider>/modules/module[type='netconf-mapper-aggregator'][name='mapper-aggregator']</provider>
+                </instance>
+            </service>
+            <service>
+                <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper">prefix:netconf-mapper-registry</type>
+                <instance>
+                    <name>mapper-aggregator-registry</name>
+                    <provider>/modules/module[type='netconf-mapper-aggregator'][name='mapper-aggregator']</provider>
+                </instance>
+            </service>
             <service>
                 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound">prefix:netconf-server-dispatcher</type>
                 <instance>
   </configuration>
   <required-capabilities>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:mapper?module=netconf-mdsal-mapper&amp;revision=2015-01-14</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:monitoring?module=netconf-mdsal-monitoring&amp;revision=2015-02-18</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:ssh?module=netconf-northbound-ssh&amp;revision=2015-01-14</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl?module=netconf-northbound-impl&amp;revision=2015-01-12</capability>
       <capability>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled?module=threadpool-impl-scheduled&amp;revision=2013-12-01</capability>
index 1b0a50b8304dbcd335eea01df0038737f46958af..1f094f1caf3d8f57c7301a9a42cf6f0ea2c5d922 100644 (file)
@@ -7,18 +7,12 @@
 */
 package org.opendaylight.controller.netconf.monitoring.osgi;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.Set;
 import org.opendaylight.controller.netconf.api.Capability;
 import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
-import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -51,39 +45,6 @@ public class NetconfMonitoringActivator implements BundleActivator {
 
         private final NetconfMonitoringOperationService operationService;
 
-        private static final Set<Capability> CAPABILITIES = Sets.<Capability>newHashSet(new Capability() {
-
-            @Override
-            public String getCapabilityUri() {
-                return MonitoringConstants.URI;
-            }
-
-            @Override
-            public Optional<String> getModuleNamespace() {
-                return Optional.of(MonitoringConstants.NAMESPACE);
-            }
-
-            @Override
-            public Optional<String> getModuleName() {
-                return Optional.of(MonitoringConstants.MODULE_NAME);
-            }
-
-            @Override
-            public Optional<String> getRevision() {
-                return Optional.of(MonitoringConstants.MODULE_REVISION);
-            }
-
-            @Override
-            public Optional<String> getCapabilitySchema() {
-                return Optional.absent();
-            }
-
-            @Override
-            public Collection<String> getLocation() {
-                return Collections.emptyList();
-            }
-        });
-
         private static final AutoCloseable AUTO_CLOSEABLE = new AutoCloseable() {
             @Override
             public void close() throws Exception {
@@ -91,8 +52,6 @@ public class NetconfMonitoringActivator implements BundleActivator {
             }
         };
 
-        private final List<CapabilityListener> listeners = new ArrayList<>();
-
         public NetconfMonitoringOperationServiceFactory(final NetconfMonitoringOperationService operationService) {
             this.operationService = operationService;
         }
@@ -104,21 +63,15 @@ public class NetconfMonitoringActivator implements BundleActivator {
 
         @Override
         public Set<Capability> getCapabilities() {
-            return CAPABILITIES;
+            return Collections.emptySet();
         }
 
         @Override
         public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
-            listener.onCapabilitiesAdded(getCapabilities());
-            listeners.add(listener);
             return AUTO_CLOSEABLE;
         }
 
         @Override
-        public void close() {
-            for (final CapabilityListener listener : listeners) {
-                listener.onCapabilitiesRemoved(getCapabilities());
-            }
-        }
+        public void close() {}
     }
 }
index 3a0362277ed9d97b8609e4a2bda6ecc6c78acbe8..67a54366cdcb9f189aabc89d31753e0232d6b7aa 100644 (file)
@@ -11,11 +11,8 @@ package org.opendaylight.controller.netconf.monitoring.osgi;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
 
-import com.google.common.base.Optional;
-import java.util.Collections;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
-import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
 
 public class NetconfMonitoringOperationServiceTest {
     @Test
@@ -26,11 +23,5 @@ public class NetconfMonitoringOperationServiceTest {
 
         assertEquals(2, service.getNetconfOperations().size());
 
-        assertEquals(Optional.<String>absent(), serviceFactory.getCapabilities().iterator().next().getCapabilitySchema());
-        assertEquals(Collections.<String>emptyList(), serviceFactory.getCapabilities().iterator().next().getLocation());
-        assertEquals(Optional.of(MonitoringConstants.MODULE_REVISION), serviceFactory.getCapabilities().iterator().next().getRevision());
-        assertEquals(Optional.of(MonitoringConstants.MODULE_NAME), serviceFactory.getCapabilities().iterator().next().getModuleName());
-        assertEquals(Optional.of(MonitoringConstants.NAMESPACE), serviceFactory.getCapabilities().iterator().next().getModuleNamespace());
-        assertEquals(MonitoringConstants.URI, serviceFactory.getCapabilities().iterator().next().getCapabilityUri());
     }
 }
index b81d2c144fd38f088db974dba8cd19952ac0dde7..a8236b2ebc38017a64af7a2ad1619a9a129d1f3e 100644 (file)
@@ -29,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Transport;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
+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.SchemasBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Sessions;
@@ -82,9 +83,19 @@ public class JaxBSerializerTest {
             }
 
             @Override
-            public Set<String> getCapabilities() {
+            public Capabilities getCapabilities() {
                 return null;
             }
+
+            @Override
+            public AutoCloseable registerListener(final MonitoringListener listener) {
+                return new AutoCloseable() {
+                    @Override
+                    public void close() throws Exception {
+                        // NOOP
+                    }
+                };
+            }
         };
         final NetconfState model = new NetconfState(service);
         final String xml = XmlUtil.toString(new JaxBSerializer().toXml(model)).replaceAll("\\s", "");
index 4566845e4f88fe7b3c1ee23e12b6ef41a5e6a653..a990b5c6cb935d1139f54353a5282329f9fd3b0e 100644 (file)
@@ -21,6 +21,7 @@
     <module>netconf-impl</module>
     <module>config-netconf-connector</module>
     <module>mdsal-netconf-connector</module>
+    <module>mdsal-netconf-monitoring</module>
     <module>netconf-util</module>
     <module>netconf-netty-util</module>
     <module>config-persister-impl</module>