summaryrefslogtreecommitdiffstats
path: root/infra/northbound/netconf/src
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2017-07-11 17:56:04 +0200
committerMarek Gradzki <mgradzki@cisco.com>2017-07-14 12:20:49 +0000
commit7d22608d89d8ff8c32e72d15039f1f27b7d659a8 (patch)
treea189335e86d6321b3fd3ba708f3c686ef1b2c566 /infra/northbound/netconf/src
parentb65cd89989ead7082089bf6f333e56b03f619606 (diff)
HONEYCOMB-360 - Netconf Northbound Intefaces provider separation
- Netconf configuration included under netconf.json Change-Id: If2a51d689e9bfc950da73f15a438277839140f8a Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Diffstat (limited to 'infra/northbound/netconf/src')
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java130
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java36
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java29
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java47
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java145
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java83
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java62
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java37
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java98
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java57
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java48
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java72
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java160
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java91
-rw-r--r--infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java35
-rw-r--r--infra/northbound/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json10
16 files changed, 1140 insertions, 0 deletions
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java
new file mode 100644
index 000000000..26ecf3a44
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/HoneycombNotification2NetconfProvider.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.fd.honeycomb.notification.NotificationCollector;
+import io.fd.honeycomb.notification.impl.NotificationProducerRegistry;
+import io.fd.honeycomb.notification.impl.TranslationUtil;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.netconf.notifications.NetconfNotificationCollector;
+import org.opendaylight.netconf.notifications.NotificationPublisherRegistration;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.netconf.streams.StreamBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class HoneycombNotification2NetconfProvider
+ extends ProviderTrait<HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HoneycombNotification2NetconfProvider.class);
+
+ @Inject
+ private DOMNotificationRouter notificationRouter;
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ private NetconfConfiguration cfgAttributes;
+ @Inject
+ private NotificationCollector hcNotificationCollector;
+ @Inject
+ private NetconfNotificationCollector netconfNotificationCollector;
+
+ @Override
+ protected HoneycombNotification2Netconf create() {
+ final StreamNameType streamType = new StreamNameType(cfgAttributes.netconfNotificationStreamName.get());
+
+ // Register as HONEYCOMB_NETCONF notification publisher under configured name
+ final NotificationPublisherRegistration netconfNotifReg = netconfNotificationCollector
+ .registerNotificationPublisher(new StreamBuilder().setName(streamType).setReplaySupport(false)
+ .setDescription(cfgAttributes.netconfNotificationStreamName.get()).build());
+
+ // Notification Translator, get notification from HC producers and put into HONEYCOMB_NETCONF notification collector
+ final DOMNotificationListener domNotificationListener =
+ new TranslatingNotificationListener(netconfNotifReg, streamType, schemaService);
+
+ // NotificationManager is used to provide list of available notifications (which are all of the notifications registered)
+ // TODO HONEYCOMB-165 make available notifications configurable here so that any number of notification streams for netconf
+ // can be configured on top of a single notification manager
+ LOG.debug("Current notifications to be exposed over HONEYCOMB_NETCONF: {}",
+ hcNotificationCollector.getNotificationTypes());
+ List<SchemaPath> currentNotificationSchemaPaths = hcNotificationCollector.getNotificationTypes().stream()
+ .map(notifType -> SchemaPath.create(true, NotificationProducerRegistry.getQName(notifType)))
+ .collect(Collectors.toList());
+
+ // Register as listener to HC'OPERATIONAL DOM notification service
+ // TODO HONEYCOMB-166 This should only be triggered when HONEYCOMB_NETCONF notifications are activated
+ // Because this way we actually start all notification producers
+ // final Collection<QName> notificationQNames =
+ ListenerRegistration<DOMNotificationListener> domNotifListenerReg = notificationRouter
+ .registerNotificationListener(domNotificationListener, currentNotificationSchemaPaths);
+
+ LOG.info("Exposing HONEYCOMB_NETCONF notification stream: {}", streamType.getValue());
+ return new HoneycombNotification2Netconf(domNotifListenerReg, netconfNotifReg);
+ }
+
+ public static final class HoneycombNotification2Netconf {
+ private final ListenerRegistration<DOMNotificationListener> domNotifListenerReg;
+ private final NotificationPublisherRegistration netconfNotifReg;
+
+ public HoneycombNotification2Netconf(final ListenerRegistration<DOMNotificationListener> domNotifListenerReg,
+ final NotificationPublisherRegistration netconfNotifReg) {
+ this.domNotifListenerReg = domNotifListenerReg;
+ this.netconfNotifReg = netconfNotifReg;
+ }
+
+ public ListenerRegistration<DOMNotificationListener> getDomNotifListenerReg() {
+ return domNotifListenerReg;
+ }
+
+ public NotificationPublisherRegistration getNetconfNotifReg() {
+ return netconfNotifReg;
+ }
+ }
+
+ private static final class TranslatingNotificationListener implements DOMNotificationListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TranslatingNotificationListener.class);
+
+ private final NotificationPublisherRegistration netconfNotifReg;
+ private final StreamNameType streamType;
+ private final SchemaService schemaService;
+
+ TranslatingNotificationListener(final NotificationPublisherRegistration netconfNotifReg,
+ final StreamNameType streamType, final SchemaService schemaService) {
+ this.netconfNotifReg = netconfNotifReg;
+ this.streamType = streamType;
+ this.schemaService = schemaService;
+ }
+
+ @Override
+ public void onNotification(@Nonnull final DOMNotification notif) {
+ LOG.debug("Propagating notification: {} into HONEYCOMB_NETCONF", notif.getType());
+ netconfNotifReg.onNotification(streamType, TranslationUtil.notificationToXml(notif, schemaService.getGlobalContext()));
+ }
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java
new file mode 100644
index 000000000..bafd4ea3c
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfBindingBrokerProvider.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.impl.FakeBindingAwareBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public final class NetconfBindingBrokerProvider extends ProviderTrait<BindingAwareBroker> {
+
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF)
+ private DataBroker dataBroker;
+
+ @Override
+ protected FakeBindingAwareBroker create() {
+ return new FakeBindingAwareBroker(dataBroker);
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java
new file mode 100644
index 000000000..aba254b8a
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfConfigurationModule.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.AbstractModule;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+public class NetconfConfigurationModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ install(ConfigurationModule.create());
+ requireBinding(NetconfConfiguration.class);
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java
new file mode 100644
index 000000000..4f0c00655
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMdsalMapperProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
+import org.opendaylight.netconf.mdsal.connector.MdsalNetconfOperationServiceFactory;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+
+public final class NetconfMdsalMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> {
+
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ private NetconfOperationServiceFactoryListener aggregator;
+ @Inject
+ private ModuleInfoBackedContext moduleInfoBackedContext;
+ @Inject
+ private Broker domBroker;
+
+ @Override
+ protected MdsalNetconfOperationServiceFactory create() {
+ MdsalNetconfOperationServiceFactory mdsalNetconfOperationServiceFactory =
+ new MdsalNetconfOperationServiceFactory(schemaService, moduleInfoBackedContext);
+ domBroker.registerConsumer(mdsalNetconfOperationServiceFactory);
+ aggregator.onAddNetconfOperationServiceFactory(mdsalNetconfOperationServiceFactory);
+ return mdsalNetconfOperationServiceFactory;
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java
new file mode 100644
index 000000000..01f57ed73
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfModule.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Singleton;
+import com.google.inject.binder.AnnotatedElementBuilder;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider;
+import io.fd.honeycomb.infra.distro.data.DataStoreProvider;
+import io.fd.honeycomb.infra.distro.data.HoneycombNotificationManagerProvider;
+import io.fd.honeycomb.infra.distro.data.InmemoryDOMDataBrokerProvider;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.fd.honeycomb.northbound.NorthboundPrivateModule;
+import io.fd.honeycomb.notification.NotificationCollector;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
+import org.opendaylight.netconf.notifications.NetconfNotificationCollector;
+import org.opendaylight.netconf.notifications.NetconfNotificationListener;
+import org.opendaylight.netconf.notifications.NetconfNotificationRegistry;
+import org.opendaylight.netconf.notifications.impl.NetconfNotificationManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfModule extends NorthboundPrivateModule<NetconfConfiguration> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfModule.class);
+
+ public static final String HONEYCOMB_NETCONF = "honeycomb-netconf";
+ public static final String HONEYCOMB_NETCONF_MAPPER_AGGR = "netconf-mapper-aggregator";
+ public static final String HONEYCOMB_NETCONF_MAPPER_NOTIF = "netconf-mapper-notification";
+ public static final String HONEYCOMB_NETCONF_MAPPER_CORE = "netconf-mapper-honeycomb";
+ public static final String HONEYCOMB_NETCONF_MAPPER_OPER = "netconf-mapper-monitoring";
+
+ public NetconfModule() {
+ super(new NetconfConfigurationModule(), NetconfConfiguration.class);
+ }
+
+ @Override
+ protected void configure() {
+ if (!getConfiguration().isNetconfEnabled()) {
+ LOG.debug("Netconf disabled, skipping initialization");
+ return;
+ }
+ install(getConfigurationModule());
+ LOG.info("Starting NETCONF Northbound");
+ // Create inmemory data store for HONEYCOMB_NETCONF config metadata
+ bind(InMemoryDOMDataStore.class).annotatedWith(Names.named(InmemoryDOMDataBrokerProvider.CONFIG))
+ .toProvider(
+ new DataStoreProvider(InmemoryDOMDataBrokerProvider.CONFIG, LogicalDatastoreType.CONFIGURATION))
+ .in(Singleton.class);
+
+ // Create inmemory data store for HONEYCOMB_NETCONF operational metadata
+ bind(InMemoryDOMDataStore.class).annotatedWith(Names.named(InmemoryDOMDataBrokerProvider.OPERATIONAL))
+ .toProvider(new DataStoreProvider(InmemoryDOMDataBrokerProvider.OPERATIONAL,
+ LogicalDatastoreType.OPERATIONAL))
+ .in(Singleton.class);
+ // Wrap datastores as DOMDataBroker
+ bind(DOMDataBroker.class).toProvider(InmemoryDOMDataBrokerProvider.class).in(Singleton.class);
+
+ // Wrap DOMDataBroker as BA data broker
+ bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_NETCONF)).toProvider(BindingDataBrokerProvider.class)
+ .in(Singleton.class);
+ expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_NETCONF));
+
+ // Wrap BA data broker as BindingAwareBroker (requied by HONEYCOMB_NETCONF)
+ bind(BindingAwareBroker.class).annotatedWith(Names.named(HONEYCOMB_NETCONF))
+ .toProvider(NetconfBindingBrokerProvider.class).in(Singleton.class);
+
+ // Create netconf operation service factory aggregator to aggregate different services
+ AggregatedNetconfOperationServiceFactory factory = new AggregatedNetconfOperationServiceFactory();
+ bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_AGGR))
+ .toInstance(factory);
+ bind(NetconfOperationServiceFactoryListener.class).toInstance(factory);
+
+ // Create netconf notification manager
+ NetconfNotificationManager manager = new NetconfNotificationManager();
+ bind(NetconfNotificationCollector.class).toInstance(manager);
+ bind(NetconfNotificationRegistry.class).toInstance(manager);
+ bind(NetconfNotificationListener.class).toInstance(manager);
+
+ // Netconf notification service factory
+ bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_NOTIF))
+ .toProvider(NetconfNotificationMapperProvider.class).asEagerSingleton();
+ expose(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_NOTIF));
+
+ // Netconf core part - mapping between Honeycomb and Netconf
+ bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_CORE))
+ .toProvider(NetconfMdsalMapperProvider.class).asEagerSingleton();
+ expose(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_CORE));
+
+ // Netconf monitoring service factory
+ bind(NetconfMonitoringService.class).toProvider(NetconfMonitoringServiceProvider.class).in(Singleton.class);
+ bind(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_OPER))
+ .toProvider(NetconfMonitoringMapperProvider.class).asEagerSingleton();
+ expose(NetconfOperationServiceFactory.class).annotatedWith(Names.named(HONEYCOMB_NETCONF_MAPPER_OPER));
+
+ // Create HC notification manager + HC2Netconf translator
+ bind(NotificationCollector.class).toProvider(HoneycombNotificationManagerProvider.class).in(Singleton.class);
+ bind(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf.class)
+ .toProvider(HoneycombNotification2NetconfProvider.class).in(Singleton.class);
+ expose(HoneycombNotification2NetconfProvider.HoneycombNotification2Netconf.class);
+
+ configureServer();
+ }
+
+ /**
+ * Provide HONEYCOMB_NETCONF TCP and SSH servers.
+ */
+ private AnnotatedElementBuilder configureServer() {
+ bind(NioEventLoopGroup.class).toProvider(NettyThreadGroupProvider.class).in(Singleton.class);
+ bind(Timer.class).toInstance(new HashedWheelTimer());
+ bind(NetconfServerDispatcher.class).toProvider(NetconfServerDispatcherProvider.class).in(Singleton.class);
+ bind(NetconfTcpServerProvider.NetconfTcpServer.class).toProvider(NetconfTcpServerProvider.class)
+ .asEagerSingleton();
+ expose(NetconfTcpServerProvider.NetconfTcpServer.class);
+ bind(NetconfSshServerProvider.NetconfSshServer.class).toProvider(NetconfSshServerProvider.class)
+ .asEagerSingleton();
+ return expose(NetconfSshServerProvider.NetconfSshServer.class);
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java
new file mode 100644
index 000000000..516df2aa5
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringMapperProvider.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import java.lang.reflect.Constructor;
+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.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public final class NetconfMonitoringMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfMonitoringMapperProvider.class);
+
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF)
+ private BindingAwareBroker bindingAwareBroker;
+ @Inject
+ private NetconfOperationServiceFactoryListener aggregator;
+ @Inject
+ private NetconfMonitoringService monitoringService;
+
+ @Override
+ protected NetconfOperationServiceFactory create() {
+ try {
+ final Class<?> monitoringWriterCls = Class.forName(
+ "org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.MonitoringToMdsalWriter");
+ Constructor<?> declaredConstructor =
+ monitoringWriterCls.getDeclaredConstructor(NetconfMonitoringService.class);
+ declaredConstructor.setAccessible(true);
+ final BindingAwareProvider writer = (BindingAwareProvider) declaredConstructor.newInstance(monitoringService);
+ bindingAwareBroker.registerProvider(writer);
+
+ final Class<?> moduleClass = Class.forName(
+ "org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.NetconfMdsalMonitoringMapperModule");
+ final Class<?> monitoringMapperCls = Class.forName(
+ "org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.NetconfMdsalMonitoringMapperModule$MdsalMonitoringMapper");
+ declaredConstructor =
+ monitoringMapperCls.getDeclaredConstructor(NetconfMonitoringService.class);
+ declaredConstructor.setAccessible(true);
+ final NetconfOperationService mdSalMonitoringMapper =
+ (NetconfOperationService) declaredConstructor.newInstance(monitoringService);
+
+ final Class<?> monitoringMpperFactory = Class.forName(
+ "org.opendaylight.controller.config.yang.netconf.mdsal.monitoring.NetconfMdsalMonitoringMapperModule$MdSalMonitoringMapperFactory");
+ declaredConstructor =
+ monitoringMpperFactory.getDeclaredConstructor(NetconfOperationService.class, moduleClass, monitoringWriterCls);
+ declaredConstructor.setAccessible(true);
+ // The second argument is null, it should be the parent cfg-subsystem module class instance, that we dont have
+ // it's used only during close so dont close the factory using its close() method
+ final NetconfOperationServiceFactory mdSalMonitoringMapperFactory =
+ (NetconfOperationServiceFactory) declaredConstructor.newInstance(mdSalMonitoringMapper, null, writer);
+ aggregator.onAddNetconfOperationServiceFactory(mdSalMonitoringMapperFactory);
+ return mdSalMonitoringMapperFactory;
+ } catch (final ReflectiveOperationException e) {
+ final String msg = "Unable to instantiate operation service factory using reflection";
+ LOG.error(msg, e);
+ throw new IllegalStateException(msg, e);
+ }
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java
new file mode 100644
index 000000000..50e0e8ac6
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringReaderFactoryProvider.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.BindingBrokerReader;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.yangtools.yang.binding.InstanceIdentifier;
+
+
+public final class NetconfMonitoringReaderFactoryProvider extends ProviderTrait<ReaderFactory> {
+
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF)
+ private DataBroker netconfDataBroker;
+
+ @Override
+ protected NetconfMonitoringReaderFactory create() {
+ return new NetconfMonitoringReaderFactory(netconfDataBroker);
+ }
+
+ /**
+ * {@link io.fd.honeycomb.translate.read.ReaderFactory} initiating reader into NETCONF's dedicated data store.
+ * Making NETCONF operational data available over NETCONF/RESTCONF
+ */
+ private static final class NetconfMonitoringReaderFactory implements ReaderFactory {
+
+ private final DataBroker netconfMonitoringBindingBrokerDependency;
+
+ NetconfMonitoringReaderFactory(final DataBroker netconfMonitoringBindingBrokerDependency) {
+ this.netconfMonitoringBindingBrokerDependency = netconfMonitoringBindingBrokerDependency;
+ }
+
+ @Override
+ public void init(final ModifiableReaderRegistryBuilder registry) {
+ registry.add(new BindingBrokerReader<>(InstanceIdentifier.create(NetconfState.class),
+ netconfMonitoringBindingBrokerDependency,
+ LogicalDatastoreType.OPERATIONAL, NetconfStateBuilder.class));
+ }
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java
new file mode 100644
index 000000000..1a99dd140
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfMonitoringServiceProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.impl.osgi.NetconfMonitoringServiceImpl;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+
+
+public class NetconfMonitoringServiceProvider extends ProviderTrait<NetconfMonitoringService> {
+
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF_MAPPER_AGGR)
+ private NetconfOperationServiceFactory aggregator;
+
+ @Override
+ protected NetconfMonitoringServiceImpl create() {
+ return new NetconfMonitoringServiceImpl(aggregator);
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java
new file mode 100644
index 000000000..b2155fac1
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationMapperProvider.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import java.lang.reflect.Constructor;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactoryListener;
+import org.opendaylight.netconf.mdsal.notification.NetconfNotificationOperationServiceFactory;
+import org.opendaylight.netconf.notifications.BaseNotificationPublisherRegistration;
+import org.opendaylight.netconf.notifications.NetconfNotificationCollector;
+import org.opendaylight.netconf.notifications.NetconfNotificationRegistry;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NetconfNotificationMapperProvider extends ProviderTrait<NetconfOperationServiceFactory> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfNotificationMapperProvider.class);
+
+ public static final InstanceIdentifier<Capabilities> capabilitiesIdentifier =
+ InstanceIdentifier.create(NetconfState.class).child(Capabilities.class).builder().build();
+ @Inject
+ private NetconfNotificationCollector notificationCollector;
+ @Inject
+ private NetconfNotificationRegistry notificationRegistry;
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF)
+ private BindingAwareBroker bindingAwareBroker;
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF)
+ private DataBroker dataBroker;
+ @Inject
+ private NetconfOperationServiceFactoryListener aggregator;
+
+ @Override
+ protected NetconfNotificationOperationServiceFactory create() {
+ try {
+ final Class<?> notificationWriter = Class.forName(
+ "org.opendaylight.controller.config.yang.netconf.mdsal.notification.NotificationToMdsalWriter");
+ Constructor<?> declaredConstructor =
+ notificationWriter.getDeclaredConstructor(NetconfNotificationCollector.class);
+ declaredConstructor.setAccessible(true);
+ final BindingAwareProvider writer =
+ (BindingAwareProvider) declaredConstructor.newInstance(notificationCollector);
+ bindingAwareBroker.registerProvider(writer);
+
+ final Class<?> notifPublisherCls = Class.forName(
+ "org.opendaylight.controller.config.yang.netconf.mdsal.notification.CapabilityChangeNotificationProducer");
+ declaredConstructor =
+ notifPublisherCls.getDeclaredConstructor(BaseNotificationPublisherRegistration.class);
+ declaredConstructor.setAccessible(true);
+ final DataTreeChangeListener<Capabilities> publisher =
+ (DataTreeChangeListener<Capabilities>) declaredConstructor.newInstance(
+ notificationCollector.registerBaseNotificationPublisher());
+
+ ListenerRegistration<DataTreeChangeListener<Capabilities>> capabilityChangeListenerRegistration = dataBroker
+ .registerDataTreeChangeListener(
+ new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, capabilitiesIdentifier),
+ publisher);
+ NetconfNotificationOperationServiceFactory netconfNotificationOperationServiceFactory =
+ new NetconfNotificationOperationServiceFactory(notificationRegistry);
+ aggregator.onAddNetconfOperationServiceFactory(netconfNotificationOperationServiceFactory);
+
+ return netconfNotificationOperationServiceFactory;
+ } catch (final ReflectiveOperationException e) {
+ final String msg = "Unable to instantiate notification mapper using reflection";
+ LOG.error(msg, e);
+ throw new IllegalStateException(msg, e);
+ }
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java
new file mode 100644
index 000000000..4ed682ff0
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfNotificationsReaderFactoryProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.honeycomb.translate.util.read.BindingBrokerReader;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.Netconf;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netmod.notification.rev080714.NetconfBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class NetconfNotificationsReaderFactoryProvider extends ProviderTrait<ReaderFactory> {
+
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF)
+ private DataBroker netconfDataBroker;
+
+ @Override
+ protected ReaderFactory create() {
+ return new NotificationReaderFactory(netconfDataBroker);
+ }
+
+ private static final class NotificationReaderFactory implements ReaderFactory {
+ private final DataBroker netconfDataBroker;
+
+ NotificationReaderFactory(final DataBroker netconfDataBroker) {
+ this.netconfDataBroker = netconfDataBroker;
+ }
+
+ @Override
+ public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+ registry.add(new BindingBrokerReader<>(InstanceIdentifier.create(Netconf.class), netconfDataBroker,
+ LogicalDatastoreType.OPERATIONAL, NetconfBuilder.class));
+ }
+
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java
new file mode 100644
index 000000000..88d7a1c02
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfReadersModule.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.fd.honeycomb.northbound.NorthboundAbstractModule;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetconfReadersModule extends NorthboundAbstractModule<NetconfConfiguration> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfReadersModule.class);
+
+ public NetconfReadersModule() {
+ super(new NetconfConfigurationModule(), NetconfConfiguration.class);
+ }
+
+ protected void configure() {
+ if (!getConfiguration().isNetconfEnabled()) {
+ LOG.debug("NETCONF Northbound disabled, skipping readers initialization");
+ return;
+ }
+ LOG.info("Initializing NETCONF Northbound readers");
+ // This should be part of NetconfModule, but that one is Private and Multibinders + private BASE_MODULES
+ // do not work together, that's why there's a dedicated module here
+ // https://github.com/google/guice/issues/906
+ final Multibinder<ReaderFactory> binder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
+ binder.addBinding().toProvider(NetconfMonitoringReaderFactoryProvider.class).in(Singleton.class);
+ binder.addBinding().toProvider(NetconfNotificationsReaderFactoryProvider.class).in(Singleton.class);
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java
new file mode 100644
index 000000000..b6c22bfd8
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfServerDispatcherProvider.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.Timer;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.impl.NetconfServerDispatcherImpl;
+import org.opendaylight.netconf.impl.SessionIdProvider;
+import org.opendaylight.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+
+public final class NetconfServerDispatcherProvider extends ProviderTrait<NetconfServerDispatcher> {
+ private static final long CONNECTION_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20);
+
+ @Inject
+ @Named(NetconfModule.HONEYCOMB_NETCONF_MAPPER_AGGR)
+ private NetconfOperationServiceFactory aggregator;
+ @Inject
+ private NetconfMonitoringService monitoringService;
+ @Inject
+ private Timer timer;
+ @Inject
+ private NioEventLoopGroup nettyThreadgroup;
+
+ @Override
+ protected NetconfServerDispatcherImpl create() {
+ AggregatedNetconfOperationServiceFactory netconfOperationProvider =
+ new AggregatedNetconfOperationServiceFactory();
+ netconfOperationProvider.onAddNetconfOperationServiceFactory(aggregator);
+
+ NetconfServerSessionNegotiatorFactory serverNegotiatorFactory =
+ new NetconfServerSessionNegotiatorFactory(timer, netconfOperationProvider, new SessionIdProvider(),
+ CONNECTION_TIMEOUT_MILLIS, monitoringService);
+ NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer =
+ new NetconfServerDispatcherImpl.ServerChannelInitializer(serverNegotiatorFactory);
+
+ return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
+ }
+
+ private static final class NetconfServerSessionNegotiatorFactory extends
+ org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory {
+
+ NetconfServerSessionNegotiatorFactory(final Timer timer,
+ final AggregatedNetconfOperationServiceFactory netconfOperationProvider,
+ final SessionIdProvider sessionIdProvider,
+ final long connectionTimeoutMillis,
+ final NetconfMonitoringService monitoringService) {
+ super(timer, netconfOperationProvider, sessionIdProvider, connectionTimeoutMillis, monitoringService,
+ org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory.DEFAULT_BASE_CAPABILITIES);
+ }
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java
new file mode 100644
index 000000000..bc1d95c09
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfSshServerProvider.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.infra.distro.InitializationException;
+import io.fd.honeycomb.northbound.CredentialsConfiguration;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.local.LocalAddress;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.opendaylight.netconf.auth.AuthProvider;
+import org.opendaylight.netconf.ssh.SshProxyServer;
+import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public final class NetconfSshServerProvider extends ProviderTrait<NetconfSshServerProvider.NetconfSshServer> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfSshServerProvider.class);
+
+ @Inject
+ private NetconfServerDispatcher dispatcher;
+ @Inject
+ private NetconfConfiguration cfgAttributes;
+ @Inject
+ private NioEventLoopGroup nettyThreadgroup;
+ @Inject
+ private CredentialsConfiguration credentialsCfg;
+
+ private ScheduledExecutorService pool =
+ Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat("netconf-ssh-%d").build());
+
+ @Override
+ protected NetconfSshServer create() {
+ if (!cfgAttributes.isNetconfSshEnabled()) {
+ LOG.info("NETCONF SSH disabled, skipping initialization");
+ return null;
+ }
+ LOG.info("Starting NETCONF SSH");
+ InetAddress sshBindingAddress = null;
+ try {
+ sshBindingAddress = InetAddress.getByName(cfgAttributes.netconfSshBindingAddress.get());
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Illegal binding address", e);
+ }
+
+ final InetSocketAddress bindingAddress =
+ new InetSocketAddress(sshBindingAddress, cfgAttributes.netconfSshBindingPort.get());
+
+ LocalAddress localAddress = new LocalAddress(cfgAttributes.netconfSshBindingPort.toString());
+ ChannelFuture localServer = dispatcher.createLocalServer(localAddress);
+
+ final SshProxyServer sshProxyServer = new SshProxyServer(pool, nettyThreadgroup, GlobalEventExecutor.INSTANCE);
+
+ final SshProxyServerConfigurationBuilder sshConfigBuilder = new SshProxyServerConfigurationBuilder();
+ sshConfigBuilder.setBindingAddress(bindingAddress);
+ sshConfigBuilder.setLocalAddress(localAddress);
+ // Only simple authProvider checking ConfigAttributes, checking the config file
+ sshConfigBuilder.setAuthenticator(new SimplelAuthProvider(credentialsCfg));
+ sshConfigBuilder.setIdleTimeout(Integer.MAX_VALUE);
+ sshConfigBuilder.setKeyPairProvider(new PEMGeneratorHostKeyProvider());
+
+ localServer.addListener(new SshServerBinder(sshProxyServer, sshConfigBuilder, bindingAddress));
+
+ return new NetconfSshServer(localServer, sshProxyServer);
+ }
+
+ public static final class NetconfSshServer {
+ private ChannelFuture localServer;
+ private SshProxyServer sshProxyServer;
+
+ NetconfSshServer(final ChannelFuture localServer,
+ final SshProxyServer sshProxyServer) {
+ this.localServer = localServer;
+ this.sshProxyServer = sshProxyServer;
+ }
+
+ public Object getLocalServer() {
+ return localServer;
+ }
+
+ public Object getSshProxyServer() {
+ return sshProxyServer;
+ }
+ }
+
+ private static final class SimplelAuthProvider implements AuthProvider {
+
+ private final CredentialsConfiguration cfgAttributes;
+
+ SimplelAuthProvider(final CredentialsConfiguration cfgAttributes) {
+ this.cfgAttributes = cfgAttributes;
+ }
+
+ @Override
+ public boolean authenticated(final String uname, final String passwd) {
+ return cfgAttributes.username.equals(uname) && cfgAttributes.password.equals(passwd);
+ }
+ }
+
+ private static final class SshServerBinder implements GenericFutureListener<ChannelFuture> {
+ private final SshProxyServer sshProxyServer;
+ private final SshProxyServerConfigurationBuilder sshConfigBuilder;
+ private final InetSocketAddress bindingAddress;
+
+ SshServerBinder(final SshProxyServer sshProxyServer,
+ final SshProxyServerConfigurationBuilder sshConfigBuilder,
+ final InetSocketAddress bindingAddress) {
+ this.sshProxyServer = sshProxyServer;
+ this.sshConfigBuilder = sshConfigBuilder;
+ this.bindingAddress = bindingAddress;
+ }
+
+ @Override
+ public void operationComplete(final ChannelFuture future) {
+ if (future.isDone() && !future.isCancelled()) {
+ try {
+ sshProxyServer.bind(sshConfigBuilder.createSshProxyServerConfiguration());
+ LOG.info("Netconf SSH endpoint started successfully at {}", bindingAddress);
+ } catch (final IOException e) {
+ throw new InitializationException("Unable to start SSH netconf server", e);
+ }
+
+ } else {
+ LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause());
+ throw new InitializationException("Unable to start SSH netconf server", future.cause());
+ }
+
+ }
+
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java
new file mode 100644
index 000000000..c1fc0a594
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NetconfTcpServerProvider.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.infra.distro.InitializationException;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.concurrent.GenericFutureListener;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import org.opendaylight.netconf.api.NetconfServerDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class NetconfTcpServerProvider extends ProviderTrait<NetconfTcpServerProvider.NetconfTcpServer> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetconfTcpServerProvider.class);
+
+ @Inject
+ private NetconfServerDispatcher dispatcher;
+ @Inject
+ private NetconfConfiguration cfgAttributes;
+
+ @Override
+ protected NetconfTcpServer create() {
+ if (!cfgAttributes.isNetconfTcpEnabled()) {
+ LOG.debug("NETCONF TCP disabled, skipping initalization");
+ return null;
+ }
+ LOG.info("Starting NETCONF TCP");
+ InetAddress name = null;
+ try {
+ name = InetAddress.getByName(cfgAttributes.netconfTcpBindingAddress.get());
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Illegal binding address", e);
+ }
+
+ final InetSocketAddress unresolved = new InetSocketAddress(name, cfgAttributes.netconfTcpBindingPort.get());
+
+ ChannelFuture tcpServer = dispatcher.createServer(unresolved);
+ tcpServer.addListener(new TcpLoggingListener(unresolved));
+ return new NetconfTcpServer(tcpServer);
+ }
+
+ public static final class NetconfTcpServer {
+ private Object tcpServer;
+
+ NetconfTcpServer(final ChannelFuture tcpServer) {
+ this.tcpServer = tcpServer;
+ }
+
+ public Object getTcpServer() {
+ return tcpServer;
+ }
+ }
+
+ private static final class TcpLoggingListener implements GenericFutureListener<ChannelFuture> {
+ private final InetSocketAddress unresolved;
+
+ TcpLoggingListener(final InetSocketAddress unresolved) {
+ this.unresolved = unresolved;
+ }
+
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+ if (future.isDone() && future.isSuccess()) {
+ LOG.info("Netconf TCP endpoint started successfully at {}", unresolved);
+ } else {
+ LOG.warn("Unable to start TCP netconf server at {}", unresolved, future.cause());
+ throw new InitializationException("Unable to start TCP netconf server", future.cause());
+ }
+ }
+ }
+}
diff --git a/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java
new file mode 100644
index 000000000..b36a31d83
--- /dev/null
+++ b/infra/northbound/netconf/src/main/java/io/fd/honeycomb/northbound/netconf/NettyThreadGroupProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.netconf;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.northbound.NetconfConfiguration;
+import io.netty.channel.nio.NioEventLoopGroup;
+
+public final class NettyThreadGroupProvider extends ProviderTrait<NioEventLoopGroup> {
+
+ @Inject
+ private NetconfConfiguration cfgAttributes;
+
+ @Override
+ protected NioEventLoopGroup create() {
+ return new NioEventLoopGroup(cfgAttributes.netconfNettyThreads,
+ new ThreadFactoryBuilder().setNameFormat("netconf-netty-%d").build());
+ }
+}
diff --git a/infra/northbound/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json b/infra/northbound/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json
new file mode 100644
index 000000000..459e90235
--- /dev/null
+++ b/infra/northbound/netconf/src/main/resources/honeycomb-minimal-resources/config/netconf.json
@@ -0,0 +1,10 @@
+{
+ "netconf-netty-threads": 2,
+ "netconf-tcp-enabled": "true",
+ "netconf-tcp-binding-address": "127.0.0.1",
+ "netconf-tcp-binding-port": 7777,
+ "netconf-ssh-enabled": "true",
+ "netconf-ssh-binding-address": "0.0.0.0",
+ "netconf-ssh-binding-port": 2831,
+ "netconf-notification-stream-name": "honeycomb"
+} \ No newline at end of file