summaryrefslogtreecommitdiffstats
path: root/infra/minimal-distribution-core
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2017-06-30 12:46:56 +0200
committerMarek Gradzki <mgradzki@cisco.com>2017-06-30 13:15:59 +0000
commit84ff4e5fd52c064437d0b6dcf43b2223f440b3c5 (patch)
tree45485b3df79423a42922c946724bdc55ee075067 /infra/minimal-distribution-core
parenta90863760d1ae1a92520ce29841aec600d25a83a (diff)
HONEYCOMB-373 - Separate minimal distribution modules to core module
Change-Id: I5278f91ea06f57c84b44a8458ef44469ebd0cf84 Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Diffstat (limited to 'infra/minimal-distribution-core')
-rw-r--r--infra/minimal-distribution-core/asciidoc/Readme.adoc3
-rw-r--r--infra/minimal-distribution-core/pom.xml174
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java31
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.java36
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java41
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java32
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java150
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.java57
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java33
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java185
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.java37
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java106
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java33
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java43
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java56
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java44
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java38
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java38
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java68
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java61
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java51
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java99
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java39
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java34
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java41
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java74
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java33
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java34
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.java37
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.java47
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java41
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.java48
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java101
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java54
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java50
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.java78
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/HoneycombNotification2NetconfProvider.java130
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfBindingBrokerProvider.java36
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMdsalMapperProvider.java47
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.java131
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringMapperProvider.java83
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringReaderFactoryProvider.java62
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringServiceProvider.java37
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationMapperProvider.java98
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationsReaderFactoryProvider.java57
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.java34
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfServerDispatcherProvider.java72
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.java152
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.java86
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyThreadGroupProvider.java35
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpConnectorProvider.java41
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpsConnectorProvider.java75
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/JettyServerProvider.java90
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.java39
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.java41
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java51
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java135
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java33
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java81
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java46
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java30
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java69
-rw-r--r--infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java97
63 files changed, 4015 insertions, 0 deletions
diff --git a/infra/minimal-distribution-core/asciidoc/Readme.adoc b/infra/minimal-distribution-core/asciidoc/Readme.adoc
new file mode 100644
index 0000000..e8306c2
--- /dev/null
+++ b/infra/minimal-distribution-core/asciidoc/Readme.adoc
@@ -0,0 +1,3 @@
+= minimal-distribution-core
+
+Project contains core modules for minimal distribution \ No newline at end of file
diff --git a/infra/minimal-distribution-core/pom.xml b/infra/minimal-distribution-core/pom.xml
new file mode 100644
index 0000000..117ec11
--- /dev/null
+++ b/infra/minimal-distribution-core/pom.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<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">
+ <parent>
+ <artifactId>impl-parent</artifactId>
+ <groupId>io.fd.honeycomb.common</groupId>
+ <version>1.17.07-SNAPSHOT</version>
+ <relativePath>../../common/impl-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>io.fd.honeycomb</groupId>
+ <artifactId>minimal-distribution-core</artifactId>
+ <version>1.17.07-SNAPSHOT</version>
+ <name>${project.artifactId}</name>
+
+ <properties>
+ <commons-io.version>2.5</commons-io.version>
+ <jersey.version>1.19.1</jersey.version>
+ <servlet.version>3.1.0</servlet.version>
+ <!-- Used by mdsal as provided/runtime dependency-->
+ <osgi.core.version>5.0.0</osgi.core.version>
+ </properties>
+
+ <dependencies>
+ <!-- DI-->
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.jmob</groupId>
+ <artifactId>guice.conf</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject.extensions</groupId>
+ <artifactId>guice-multibindings</artifactId>
+ </dependency>
+ <!-- ODL -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ </dependency>
+ <!-- ODL-Restconf -->
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>sal-rest-connector</artifactId>
+ </dependency>
+ <!-- ODL-Netconf -->
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-ssh</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>mdsal-netconf-notification</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>mdsal-netconf-monitoring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>mdsal-netconf-connector</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>ietf-netconf-monitoring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>ietf-netconf-monitoring-extension</artifactId>
+ </dependency>
+ <!-- Jersey + Jetty for RESTCONF -->
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-server</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <!-- OSGI Even tough not running in OSGI, dependency needs to be here since some deprecated MD-SAL APIs rely on osgi core -->
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.core.version}</version>
+ </dependency>
+
+ <!-- HC -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>data-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>honeycomb-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>notification-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rpc-impl</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Utilities -->
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons-io.version}</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java
new file mode 100644
index 0000000..0ed530c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/InitializationException.java
@@ -0,0 +1,31 @@
+/*
+ * 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.infra.distro;
+
+/**
+ * Exception thrown when a failure occurs during HC initialization.
+ */
+public class InitializationException extends RuntimeException {
+
+ public InitializationException(final String s) {
+ super(s);
+ }
+
+ public InitializationException(final String s, final Throwable throwable) {
+ super(s, throwable);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.java
new file mode 100644
index 0000000..a762a16
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/ProviderTrait.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.infra.distro;
+
+import com.google.inject.Provider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class ProviderTrait<T> implements Provider<T> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ProviderTrait.class);
+
+ @Override
+ public T get() {
+ LOG.info("Providing: {}", this);
+ T create = create();
+ LOG.debug("Provided: {}", create);
+ return create;
+ }
+
+ protected abstract T create();
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java
new file mode 100644
index 0000000..a17f5d6
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationConfig.java
@@ -0,0 +1,41 @@
+/*
+ * 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.infra.distro.activation;
+
+import java.util.Optional;
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+@BindConfig(value = "activation", syntax = Syntax.JSON)
+public class ActivationConfig {
+
+ @InjectConfig("modules-resource-path")
+ private String modulesResourcePath;
+
+ @InjectConfig("yang-modules-index-path")
+ private String yangModulesIndexPath;
+
+ public String getModulesResourcePath() {
+ return Optional.ofNullable(modulesResourcePath).orElse("../modules/");
+ }
+
+ public String getYangModulesIndexPath() {
+ return Optional.ofNullable(yangModulesIndexPath).orElse("../yang-mapping/");
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java
new file mode 100644
index 0000000..00f77a6
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActivationModule.java
@@ -0,0 +1,32 @@
+/*
+ * 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.infra.distro.activation;
+
+import com.google.inject.AbstractModule;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+/**
+ * Module that provides set of modules activated by distribution and binds this set to be available
+ */
+public class ActivationModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ install(ConfigurationModule.create());
+ requestInjection(ActivationConfig.class);
+ bind(ActiveModules.class).toProvider(ActiveModuleProvider.class).asEagerSingleton();
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java
new file mode 100644
index 0000000..d31024c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModuleProvider.java
@@ -0,0 +1,150 @@
+/*
+ * 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.infra.distro.activation;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.google.inject.Provider;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides list of active modules for distribution
+ */
+class ActiveModuleProvider implements Provider<ActiveModules> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ActiveModuleProvider.class);
+
+ @Inject
+ private ActivationConfig config;
+
+ @Override
+ public ActiveModules get() {
+ return new ActiveModules(loadActiveModules(
+ aggregateResources(config.getModulesResourcePath(), Thread.currentThread().getContextClassLoader())));
+ }
+
+ /**
+ * Provide unique set of active modules filtered from provided resources
+ */
+ static Set<Class<? extends Module>> loadActiveModules(@Nonnull final List<String> moduleNames) {
+ final ClassLoader classLoader = ActiveModuleProvider.class.getClassLoader();
+ LOG.info("Reading active modules configuration for distribution");
+
+ // process resources to resource modules
+ return moduleNames.stream()
+ .map(String::trim)
+ .filter(trimmedLine -> trimmedLine.length() != 0)
+ // filter out commented lines
+ .filter(nonEmptyLine -> !nonEmptyLine.startsWith("//"))
+ // filter duplicates
+ .distinct()
+ .map(validLine -> moduleNameToClass(validLine, classLoader))
+ // filters out classes that are not modules
+ .filter(ActiveModuleProvider::filterNonModules)
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Aggregate all resources from provided relative path into a {@code List<String>}
+ */
+ public static List<String> aggregateResources(final String relativePath, final ClassLoader classLoader) {
+ try {
+ return Collections.list(classLoader.getResources(relativePath)).stream()
+ .map(ActiveModuleProvider::toURI)
+ .flatMap(ActiveModuleProvider::folderToFile)
+ .map(File::toURI)
+ .map(Paths::get)
+ // readAll lines and add them to iteration
+ .flatMap(ActiveModuleProvider::readLines)
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+ LOG.error("Unable to load resources from relative path {}", relativePath, e);
+ throw new IllegalStateException("Unable to load resources from relative path " + relativePath, e);
+ }
+ }
+
+ private static Stream<File> folderToFile(final URI uri) {
+ final File[] files = new File(uri).listFiles(File::isFile);
+
+ return files != null
+ ? ImmutableList.copyOf(files).stream()
+ : Collections.<File>emptyList().stream();
+ }
+
+ private static boolean filterNonModules(final Class<?> clazz) {
+ final boolean isModule = Module.class.isAssignableFrom(clazz);
+ if (!isModule) {
+ LOG.warn("Class {} is provided in modules configuration, but is not a Module and will be ignored", clazz);
+ }
+ return isModule;
+ }
+
+ /**
+ * Read lines from {@code Path}
+ */
+ private static Stream<String> readLines(final Path path) {
+ try {
+ return Files.readAllLines(path).stream();
+ } catch (IOException e) {
+ LOG.error("Unable to read content of {}", path, e);
+ throw new IllegalStateException("Unable to read content of " + path, e);
+ }
+ }
+
+ /**
+ * Converts {@code URL} to {@code URI}
+ */
+ private static URI toURI(final URL url) {
+ try {
+ return url.toURI();
+ } catch (URISyntaxException e) {
+ LOG.error("Unable to convert {} to uri", url);
+ throw new IllegalStateException("Unable to convert " + url + " to uri", e);
+ }
+ }
+
+ /**
+ * Loads class by provided name
+ */
+ private static Class<? extends Module> moduleNameToClass(final String name,
+ final ClassLoader classLoader) {
+ try {
+ LOG.debug("Loading module class {}", name);
+ return (Class<? extends Module>) classLoader.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ LOG.error("Unable to convert {} to class, make sure you've provided sources to classpath", name);
+ throw new IllegalStateException(
+ "Unable to convert " + name + " to class, make sure you've provided sources to classpath", e);
+ }
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.java
new file mode 100644
index 0000000..f729f00
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/activation/ActiveModules.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.infra.distro.activation;
+
+import static java.lang.String.format;
+
+import com.google.inject.Module;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Provides static set of active activeModulesClasses
+ */
+public class ActiveModules {
+ private final Set<Class<? extends Module>> activeModulesClasses;
+
+ public ActiveModules(final Set<Class<? extends Module>> activeModulesClasses) {
+ this.activeModulesClasses = activeModulesClasses;
+ }
+
+ public Set<Class<? extends Module>> getActiveModulesClasses() {
+ return activeModulesClasses;
+ }
+
+ public Set<? extends Module> createModuleInstances() {
+ return activeModulesClasses.stream()
+ .map(moduleClass -> {
+ try {
+ return moduleClass.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new IllegalStateException(format("Unable to create instance of module %s", moduleClass),
+ e);
+ }
+ }).collect(Collectors.toSet());
+ }
+
+ @Override
+ public String toString() {
+ return "ActiveModules{" +
+ "activeModulesClasses=" + activeModulesClasses +
+ '}';
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java
new file mode 100644
index 0000000..b22e885
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/CfgAttrsModule.java
@@ -0,0 +1,33 @@
+/*
+ * 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.infra.distro.cfgattrs;
+
+import com.google.inject.AbstractModule;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+/**
+ * Load the configuration from json into HoneycombConfiguration and make it available.
+ */
+public class CfgAttrsModule extends AbstractModule {
+
+ protected void configure() {
+ install(ConfigurationModule.create());
+ // Inject non-dependency configuration
+ requestInjection(HoneycombConfiguration.class);
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java
new file mode 100644
index 0000000..cc46f7b
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/cfgattrs/HoneycombConfiguration.java
@@ -0,0 +1,185 @@
+/*
+ * 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.infra.distro.cfgattrs;
+
+import com.google.common.base.MoreObjects;
+import java.util.Optional;
+import net.jmob.guice.conf.core.BindConfig;
+import net.jmob.guice.conf.core.InjectConfig;
+import net.jmob.guice.conf.core.Syntax;
+
+/**
+ * This is the Java equivalent for honeyconb.json file. We use guice-config library to load all the config attributes
+ * into this class instance.
+ *
+ * The BindConfig annotation tells that honeycomb.json file should be looked up on classpath root.
+ */
+@BindConfig(value = "honeycomb", syntax = Syntax.JSON)
+public class HoneycombConfiguration {
+
+ public boolean isRestconfHttpEnabled() {
+ return Boolean.valueOf(restconfHttp);
+ }
+
+ public boolean isRestconfHttpsEnabled() {
+ return Boolean.valueOf(restconfHttps);
+ }
+
+ public boolean isRestconfEnabled() {
+ return isRestconfHttpEnabled() || isRestconfHttpsEnabled();
+ }
+
+ public boolean isNetconfTcpEnabled() {
+ return Boolean.valueOf(netconfTcp);
+ }
+
+ public boolean isNetconfSshEnabled() {
+ return Boolean.valueOf(netconfSsh);
+ }
+
+ public boolean isNetconfEnabled() {
+ return isNetconfTcpEnabled() || isNetconfSshEnabled();
+ }
+
+ public boolean isConfigPersistenceEnabled() {
+ return persistConfig.isPresent() && Boolean.valueOf(persistConfig.get());
+ }
+ public boolean isContextPersistenceEnabled() {
+ return persistContext.isPresent() && Boolean.valueOf(persistContext.get());
+ }
+
+ @InjectConfig("persist-context")
+ public Optional<String> persistContext = Optional.of("true");
+ @InjectConfig("persisted-context-path")
+ public String peristContextPath;
+ @InjectConfig("persisted-context-restoration-type")
+ public String persistedContextRestorationType;
+ @InjectConfig("persist-config")
+ public Optional<String> persistConfig = Optional.of("true");
+ @InjectConfig("persisted-config-path")
+ public String peristConfigPath;
+ @InjectConfig("persisted-config-restoration-type")
+ public String persistedConfigRestorationType;
+ @InjectConfig("notification-service-queue-depth")
+ public int notificationServiceQueueDepth;
+ @InjectConfig("restconf-http-enabled")
+ public String restconfHttp;
+ @InjectConfig("restconf-binding-address")
+ public Optional<String> restconfBindingAddress;
+ @InjectConfig("restconf-port")
+ public Optional<Integer> restconfPort;
+ @InjectConfig("restconf-https-enabled")
+ public String restconfHttps;
+ @InjectConfig("restconf-https-binding-address")
+ public Optional<String> restconfHttpsBindingAddress;
+ @InjectConfig("restconf-https-port")
+ public Optional<Integer> restconfHttpsPort;
+ /**
+ * Restconf keystore file name. It will be loaded from the classpath so must be present in one of the folders
+ * packaged with the distribution e.g. cert/
+ */
+ @InjectConfig("restconf-keystore")
+ public Optional<String> restconfKeystore = Optional.of("/honeycomb-keystore");
+ @InjectConfig("restconf-keystore-password")
+ public Optional<String> keystorePassword;
+ @InjectConfig("restconf-keystore-manager-password")
+ public Optional<String> keystoreManagerPassword;
+ /**
+ * Restconf truststore file name. It will be loaded from the classpath so must be present in one of the folders
+ * packaged with the distribution e.g. cert/
+ */
+ @InjectConfig("restconf-truststore")
+ public Optional<String> restconfTruststore;
+ @InjectConfig("restconf-truststore-password")
+ public Optional<String> truststorePassword;
+ @InjectConfig("restconf-websocket-port")
+ public Optional<Integer> restconfWebsocketPort = Optional.of(7779);
+ @InjectConfig("restconf-root-path")
+ public Optional<String> restconfRootPath = Optional.of("/restconf");
+ @InjectConfig("restconf-pool-max-size")
+ public Optional<Integer> restPoolMaxSize = Optional.of(10);
+ @InjectConfig("restconf-pool-min-size")
+ public Optional<Integer> restPoolMinSize = Optional.of(1);
+ @InjectConfig("restconf-acceptors-size")
+ public Optional<Integer> acceptorsSize = Optional.of(1);
+ @InjectConfig("restconf-selectors-size")
+ public Optional<Integer> selectorsSize = Optional.of(1);
+ @InjectConfig("restconf-https-acceptors-size")
+ public Optional<Integer> httpsAcceptorsSize = Optional.of(1);
+ @InjectConfig("restconf-https-selectors-size")
+ public Optional<Integer> httpsSelectorsSize = Optional.of(1);
+ @InjectConfig("netconf-netty-threads")
+ public Integer netconfNettyThreads;
+ @InjectConfig("netconf-tcp-enabled")
+ public String netconfTcp;
+ @InjectConfig("netconf-tcp-binding-address")
+ public Optional<String> netconfTcpBindingAddress;
+ @InjectConfig("netconf-tcp-binding-port")
+ public Optional<Integer> netconfTcpBindingPort;
+ @InjectConfig("netconf-ssh-enabled")
+ public String netconfSsh;
+ @InjectConfig("netconf-ssh-binding-address")
+ public Optional<String> netconfSshBindingAddress;
+ @InjectConfig("netconf-ssh-binding-port")
+ public Optional<Integer> netconfSshBindingPort;
+ @InjectConfig("netconf-notification-stream-name")
+ public Optional<String> netconfNotificationStreamName = Optional.of("honeycomb");
+ @InjectConfig("username")
+ public String username;
+ @InjectConfig("password")
+ public String password;
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("peristContextPath", peristContextPath)
+ .add("persistedContextRestorationType", persistedContextRestorationType)
+ .add("peristConfigPath", peristConfigPath)
+ .add("persistedConfigRestorationType", persistedConfigRestorationType)
+ .add("notificationServiceQueueDepth", notificationServiceQueueDepth)
+ .add("restconfHttp", restconfHttp)
+ .add("restconfBindingAddress", restconfBindingAddress)
+ .add("restconfPort", restconfPort)
+ .add("restconfHttps", restconfHttps)
+ .add("restconfHttpsBindingAddress", restconfHttpsBindingAddress)
+ .add("restconfHttpsPort", restconfHttpsPort)
+ .add("restconfKeystore", restconfKeystore)
+ .add("keystorePassword", keystorePassword)
+ .add("keystoreManagerPassword", keystoreManagerPassword)
+ .add("restconfTruststore", restconfTruststore)
+ .add("truststorePassword", truststorePassword)
+ .add("restconfWebsocketPort", restconfWebsocketPort)
+ .add("restconfRootPath", restconfRootPath)
+ .add("restPoolMaxSize", restPoolMaxSize)
+ .add("restPoolMinSize", restPoolMinSize)
+ .add("acceptorsSize", acceptorsSize)
+ .add("selectorsSize", selectorsSize)
+ .add("httpsAcceptorsSize", httpsAcceptorsSize)
+ .add("httpsSelectorsSize", httpsSelectorsSize)
+ .add("netconfNettyThreads", netconfNettyThreads)
+ .add("netconfTcp", netconfTcp)
+ .add("netconfTcpBindingAddress", netconfTcpBindingAddress)
+ .add("netconfTcpBindingPort", netconfTcpBindingPort)
+ .add("netconfSsh", netconfSsh)
+ .add("netconfSshBindingAddress", netconfSshBindingAddress)
+ .add("netconfSshBindingPort", netconfSshBindingPort)
+ .add("netconfNotificationStreamName", netconfNotificationStreamName)
+ .add("username", username)
+ .add("password", password)
+ .toString();
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.java
new file mode 100644
index 0000000..e173551
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/BindingDataBrokerProvider.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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class BindingDataBrokerProvider extends ProviderTrait<DataBroker> {
+
+ @Inject
+ private DOMDataBroker domDataBroker;
+ @Inject
+ private BindingToNormalizedNodeCodec mappingService;
+
+ @Override
+ protected BindingDOMDataBrokerAdapter create() {
+ return new BindingDOMDataBrokerAdapter(domDataBroker, mappingService);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java
new file mode 100644
index 0000000..55f9d98
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ConfigAndOperationalPipelineModule.java
@@ -0,0 +1,106 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.PrivateModule;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.ReadableDataManager;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.infra.distro.data.config.WriterRegistryProvider;
+import io.fd.honeycomb.infra.distro.data.oper.ReadableDTDelegProvider;
+import io.fd.honeycomb.infra.distro.data.oper.ReaderRegistryProvider;
+import io.fd.honeycomb.infra.distro.initializer.PersistedFileInitializerProvider;
+import io.fd.honeycomb.rpc.RpcRegistry;
+import io.fd.honeycomb.rpc.RpcRegistryBuilder;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public class ConfigAndOperationalPipelineModule extends PrivateModule {
+
+ public static final String HONEYCOMB_CONFIG_NONPERSIST = "honeycomb-config-nopersist";
+ public static final String HONEYCOMB_CONFIG = "honeycomb-config";
+
+ protected void configure() {
+ // Expose registries for plugin reader/writer factories
+ bind(WriterRegistry.class).toProvider(WriterRegistryProvider.class).in(Singleton.class);
+ expose(WriterRegistry.class);
+ bind(ReaderRegistry.class).toProvider(ReaderRegistryProvider.class).in(Singleton.class);
+ expose(ReaderRegistry.class);
+
+ // Non persisting data tree for config
+ bind(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG_NONPERSIST))
+ .toProvider(DataTreeProvider.ConfigDataTreeProvider.class).in(Singleton.class);
+ expose(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG_NONPERSIST));
+ // Persisting data tree wrapper for config
+ bind(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG))
+ .toProvider(PersistingDataTreeProvider.ConfigPersistingDataTreeProvider.class).in(Singleton.class);
+ expose(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+ // Config Data Tree manager working on top of config data tree + writer registry
+ bind(ModifiableDataManager.class).toProvider(ModifiableDTDelegProvider.class).in(Singleton.class);
+ // Operational Data Tree manager working on top of reader registry
+ bind(ReadableDataManager.class).toProvider(ReadableDTDelegProvider.class).in(Singleton.class);
+ expose(ReadableDataManager.class);
+
+ // DOMDataBroker wrapper on top of data tree managers
+ HoneycombDOMDataBrokerProvider domBrokerProvider = new HoneycombDOMDataBrokerProvider();
+ bind(DOMDataBroker.class).toProvider(domBrokerProvider).in(Singleton.class);
+
+ // BA version of data broker
+ bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONFIG)).toProvider(BindingDataBrokerProvider.class)
+ .in(Singleton.class);
+ expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+ // Create initializer to init persisted config data
+ bind(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONFIG))
+ .toProvider(PersistedFileInitializerProvider.PersistedConfigInitializerProvider.class)
+ .in(Singleton.class);
+ expose(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONFIG));
+
+ configureNotifications();
+ configureRpcs();
+ }
+
+ private void configureNotifications() {
+ // Create notification service
+ bind(DOMNotificationRouter.class).toProvider(DOMNotificationServiceProvider.class).in(Singleton.class);
+ expose(DOMNotificationRouter.class);
+ // Wrap notification service, data broker and schema service in a Broker MD-SAL API
+ bind(Broker.class).toProvider(HoneycombDOMBrokerProvider.class).in(Singleton.class);
+ expose(Broker.class);
+ }
+
+ private void configureRpcs() {
+ // Create rpc service
+ bind(DOMRpcService.class).toProvider(HoneycombDOMRpcServiceProvider.class).in(Singleton.class);
+ expose(DOMRpcService.class);
+
+ bind(RpcRegistryBuilder.class).toProvider(RpcRegistryBuilderProvider.class).in(Singleton.class);
+ expose(RpcRegistryBuilder.class);
+
+ bind(RpcRegistry.class).toProvider(RpcRegistryProvider.class).in(Singleton.class);
+ expose(RpcRegistry.class);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java
new file mode 100644
index 0000000..424393b
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DOMNotificationServiceProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+
+public final class DOMNotificationServiceProvider extends ProviderTrait<DOMNotificationRouter> {
+
+ @Inject
+ private HoneycombConfiguration cfg;
+
+ @Override
+ protected DOMNotificationRouter create() {
+ return DOMNotificationRouter.create(cfg.notificationServiceQueueDepth);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java
new file mode 100644
index 0000000..5b09f21
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataStoreProvider.java
@@ -0,0 +1,43 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+
+public final class DataStoreProvider extends ProviderTrait<InMemoryDOMDataStore> {
+
+ @Inject
+ private SchemaService schemaService;
+ private String name;
+ private LogicalDatastoreType type;
+
+ public DataStoreProvider(final String name,
+ final LogicalDatastoreType type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ @Override
+ protected InMemoryDOMDataStore create() {
+ return InMemoryDOMDataStoreFactory.create(name, type, schemaService, false, null);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java
new file mode 100644
index 0000000..c5fcc05
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/DataTreeProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
+
+public abstract class DataTreeProvider extends ProviderTrait<DataTree> {
+
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ private HoneycombConfiguration config;
+
+ public TipProducingDataTree create() {
+ TipProducingDataTree delegate = InMemoryDataTreeFactory.getInstance().create(getType());
+ delegate.setSchemaContext(schemaService.getGlobalContext());
+ return delegate;
+ }
+
+ public abstract TreeType getType();
+
+ public static class ConfigDataTreeProvider extends DataTreeProvider {
+ public TreeType getType() {
+ return TreeType.CONFIGURATION;
+ }
+
+ }
+
+ public static class ContextDataTreeProvider extends DataTreeProvider {
+ public TreeType getType() {
+ return TreeType.OPERATIONAL;
+ }
+
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java
new file mode 100644
index 0000000..dd34c6c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMBrokerProvider.java
@@ -0,0 +1,44 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.impl.NorthboundFacadeHoneycombDOMBroker;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+
+public final class HoneycombDOMBrokerProvider extends ProviderTrait<Broker> {
+
+ @Inject
+ private DOMDataBroker domDataBroker;
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ private DOMNotificationRouter domNotificationService;
+ @Inject
+ private DOMRpcService domRpcService;
+
+ @Override
+ protected NorthboundFacadeHoneycombDOMBroker create() {
+ return new NorthboundFacadeHoneycombDOMBroker(domDataBroker, schemaService, domNotificationService,
+ domRpcService);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java
new file mode 100644
index 0000000..92bbc51
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMDataBrokerProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.ReadableDataManager;
+import io.fd.honeycomb.data.impl.DataBroker;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class HoneycombDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> {
+
+ @Inject
+ private ModifiableDataManager modDataManager;
+ @Inject(optional = true)
+ private ReadableDataManager readDataManager;
+
+ protected DataBroker create() {
+ return readDataManager != null
+ ? DataBroker.create(modDataManager, readDataManager)
+ : DataBroker.create(modDataManager);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java
new file mode 100644
index 0000000..0459b2f
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombDOMRpcServiceProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.rpc.HoneycombDOMRpcService;
+import io.fd.honeycomb.rpc.RpcRegistry;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+
+public final class HoneycombDOMRpcServiceProvider extends ProviderTrait<DOMRpcService> {
+
+ @Inject
+ private BindingToNormalizedNodeCodec serializer;
+
+ @Inject
+ private RpcRegistry rpcRegistry;
+
+ @Override
+ protected DOMRpcService create() {
+ return new HoneycombDOMRpcService(serializer, rpcRegistry);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java
new file mode 100644
index 0000000..f2e81a9
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/HoneycombNotificationManagerProvider.java
@@ -0,0 +1,68 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.notification.ManagedNotificationProducer;
+import io.fd.honeycomb.notification.NotificationCollector;
+import io.fd.honeycomb.notification.impl.HoneycombNotificationCollector;
+import io.fd.honeycomb.notification.impl.NotificationProducerRegistry;
+import io.fd.honeycomb.notification.impl.NotificationProducerTracker;
+import java.util.HashSet;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
+
+public final class HoneycombNotificationManagerProvider extends ProviderTrait<NotificationCollector> {
+
+ @Inject
+ private DOMNotificationRouter notificationRouter;
+ @Inject(optional = true)
+ private Set<ManagedNotificationProducer> notificationProducers = new HashSet<>();
+ @Inject
+ private BindingToNormalizedNodeCodec codec;
+
+ @Override
+ protected HoneycombNotificationCollector create() {
+ // Create the registry to keep track of what'OPERATIONAL registered
+ NotificationProducerRegistry notificationProducerRegistry =
+ new NotificationProducerRegistry(Lists.newArrayList(notificationProducers));
+
+ // Create BA version of notification service (implementation is free from ODL)
+ BindingDOMNotificationPublishServiceAdapter bindingDOMNotificationPublishServiceAdapter =
+ new BindingDOMNotificationPublishServiceAdapter(codec, notificationRouter);
+
+ // Create Collector on top of BA notification service and registry
+ HoneycombNotificationCollector honeycombNotificationCollector =
+ new HoneycombNotificationCollector(bindingDOMNotificationPublishServiceAdapter,
+ notificationProducerRegistry);
+
+ // Create tracker, responsible for starting and stopping registered notification producers whenever necessary
+ NotificationProducerTracker notificationProducerTracker =
+ new NotificationProducerTracker(notificationProducerRegistry, honeycombNotificationCollector,
+ notificationRouter);
+
+ // DOMNotificationService is already provided by DOMBroker injected into RESTCONF, however RESTCONF
+ // only supports data-change notification, nothing else. So currently (Beryllium-SR2) honeycomb notifications
+ // won't be available over RESTCONF.
+
+ return honeycombNotificationCollector;
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java
new file mode 100644
index 0000000..f5f04d2
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/InmemoryDOMDataBrokerProvider.java
@@ -0,0 +1,61 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.broker.impl.SerializedDOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
+import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
+
+public final class InmemoryDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> {
+
+ public static final String CONFIG = "config";
+ public static final String OPERATIONAL = "operational";
+
+ @Inject
+ @Named(InmemoryDOMDataBrokerProvider.CONFIG)
+ private InMemoryDOMDataStore cfgDataStore;
+ @Inject
+ @Named(InmemoryDOMDataBrokerProvider.OPERATIONAL)
+ private InMemoryDOMDataStore operDataStore;
+
+ @Override
+ protected SerializedDOMDataBroker create() {
+ // This Databroker is dedicated for netconf metadata, not expected to be under heavy load
+ ExecutorService listenableFutureExecutor =
+ SpecialExecutors.newBlockingBoundedCachedThreadPool(1, 100, "commits");
+ ExecutorService commitExecutor = SpecialExecutors.newBoundedSingleThreadExecutor(100, "WriteTxCommit");
+ // TODO HONEYCOMB-164 try to provide more lightweight implementation of DataBroker
+
+ Map<LogicalDatastoreType, DOMStore> map = new LinkedHashMap<>();
+ map.put(LogicalDatastoreType.CONFIGURATION, cfgDataStore);
+ map.put(LogicalDatastoreType.OPERATIONAL, operDataStore);
+
+ return new SerializedDOMDataBroker(map, new DeadlockDetectingListeningExecutorService(commitExecutor,
+ TransactionCommitDeadlockException.DEADLOCK_EXCEPTION_SUPPLIER, listenableFutureExecutor));
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java
new file mode 100644
index 0000000..b49381a
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/ModifiableDTDelegProvider.java
@@ -0,0 +1,51 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.ModifiableDataTreeDelegator;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public final class ModifiableDTDelegProvider extends ProviderTrait<ModifiableDataManager> {
+
+ @Inject
+ private BindingToNormalizedNodeCodec serializer;
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG)
+ private DataTree dataTree;
+ @Inject
+ private WriterRegistry registry;
+ @Inject
+ @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+ private DataBroker contextBroker;
+
+ @Override
+ protected ModifiableDataTreeDelegator create() {
+ return new ModifiableDataTreeDelegator(serializer, dataTree, schemaService.getGlobalContext(),
+ registry, contextBroker);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java
new file mode 100644
index 0000000..e7a654c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/PersistingDataTreeProvider.java
@@ -0,0 +1,99 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.data.impl.PersistingDataTreeAdapter;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import java.nio.file.Paths;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+
+public abstract class PersistingDataTreeProvider extends ProviderTrait<DataTree> {
+
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ protected HoneycombConfiguration config;
+
+ public DataTree create() {
+ return isEnabled()
+ ? new PersistingDataTreeAdapter(getDelegate(), schemaService, Paths.get(getPath()))
+ : getDelegate();
+ }
+
+ public abstract String getPath();
+
+ public abstract TreeType getType();
+
+ public abstract DataTree getDelegate();
+
+ protected abstract boolean isEnabled();
+
+ public static final class ConfigPersistingDataTreeProvider extends PersistingDataTreeProvider {
+
+ @Inject
+ @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG_NONPERSIST)
+ private DataTree delegate;
+
+ public String getPath() {
+ return config.peristConfigPath;
+ }
+
+ public TreeType getType() {
+ return TreeType.CONFIGURATION;
+ }
+
+ public DataTree getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return config.isConfigPersistenceEnabled();
+ }
+ }
+
+ public static final class ContextPersistingDataTreeProvider extends PersistingDataTreeProvider {
+
+ @Inject
+ @Named(ContextPipelineModule.HONEYCOMB_CONTEXT_NOPERSIST)
+ private DataTree delegate;
+
+ public String getPath() {
+ return config.peristContextPath;
+ }
+
+ public TreeType getType() {
+ return TreeType.OPERATIONAL;
+ }
+
+ public DataTree getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return config.isContextPersistenceEnabled();
+ }
+
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java
new file mode 100644
index 0000000..92d9ce9
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryBuilderProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.rpc.RpcRegistryBuilder;
+import io.fd.honeycomb.rpc.RpcService;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class RpcRegistryBuilderProvider extends ProviderTrait<RpcRegistryBuilder> {
+
+ @Inject(optional = true)
+ private Set<RpcService> rpcServices = new HashSet<>();
+
+ @Override
+ protected RpcRegistryBuilder create() {
+ final RpcRegistryBuilder builder = new RpcRegistryBuilder();
+ rpcServices.stream()
+ .forEach(service -> builder.addService(service));
+ return builder;
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java
new file mode 100644
index 0000000..4e09a9d
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/RpcRegistryProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.infra.distro.data;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.rpc.RpcRegistry;
+import io.fd.honeycomb.rpc.RpcRegistryBuilder;
+
+public final class RpcRegistryProvider extends ProviderTrait<RpcRegistry> {
+
+ @Inject
+ private RpcRegistryBuilder builder;
+
+ @Override
+ protected RpcRegistry create() {
+ return builder.build();
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java
new file mode 100644
index 0000000..6546ba2
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/config/WriterRegistryProvider.java
@@ -0,0 +1,41 @@
+/*
+ * 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.infra.distro.data.config;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.util.YangDAG;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class WriterRegistryProvider extends ProviderTrait<WriterRegistry> {
+
+ @Inject(optional = true)
+ private Set<WriterFactory> writerFactories = new HashSet<>();
+
+ @Override
+ protected WriterRegistry create() {
+ final FlatWriterRegistryBuilder builder = new FlatWriterRegistryBuilder(new YangDAG());
+ writerFactories
+ .stream()
+ .forEach(it -> it.init(builder));
+ return builder.build();
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java
new file mode 100644
index 0000000..b0ded35
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ContextPipelineModule.java
@@ -0,0 +1,74 @@
+/*
+ * 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.infra.distro.data.context;
+
+import com.google.inject.PrivateModule;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider;
+import io.fd.honeycomb.infra.distro.data.DataTreeProvider;
+import io.fd.honeycomb.infra.distro.data.PersistingDataTreeProvider;
+import io.fd.honeycomb.infra.distro.initializer.PersistedFileInitializerProvider;
+import io.fd.honeycomb.translate.MappingContext;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public class ContextPipelineModule extends PrivateModule {
+
+ public static final String HONEYCOMB_CONTEXT_NOPERSIST = "honeycomb-context-nopersist";
+ public static final String HONEYCOMB_CONTEXT = "honeycomb-context";
+
+ @Override
+ protected void configure() {
+ // Non persisting data tree for context
+ DataTreeProvider.ContextDataTreeProvider noPersistDataTreeProvider =
+ new DataTreeProvider.ContextDataTreeProvider();
+ bind(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT_NOPERSIST))
+ .toProvider(noPersistDataTreeProvider).in(Singleton.class);
+ expose(DataTree.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT_NOPERSIST));
+ // Persisting data tree wrapper for context
+ PersistingDataTreeProvider.ContextPersistingDataTreeProvider dataTreeProvider =
+ new PersistingDataTreeProvider.ContextPersistingDataTreeProvider();
+ bind(DataTree.class).toProvider(dataTreeProvider).in(Singleton.class);
+
+ // Data Tree manager (without any delegation) on top of context data tree
+ bind(ModifiableDataManager.class).toProvider(ModifiableDTMgrProvider.class).in(Singleton.class);
+
+ // DOMDataBroker interface on top of data tree manager
+ HoneycombContextDOMDataBrokerProvider domBrokerProvider = new HoneycombContextDOMDataBrokerProvider();
+ bind(DOMDataBroker.class).toProvider(domBrokerProvider).in(Singleton.class);
+
+ // BA version of data broker for context
+ bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT)).toProvider(BindingDataBrokerProvider.class)
+ .in(Singleton.class);
+ expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT));
+
+ // Create initializer to init persisted config data
+ bind(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT))
+ .toProvider(PersistedFileInitializerProvider.PersistedContextInitializerProvider.class)
+ .in(Singleton.class);
+ expose(DataTreeInitializer.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT));
+
+ // Mapping context is just a small adapter on top of BA data broker to simplify CRUD of context data
+ bind(MappingContext.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT))
+ .toProvider(RealtimeMappingContextProvider.class).in(Singleton.class);
+ expose(MappingContext.class).annotatedWith(Names.named(HONEYCOMB_CONTEXT));
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java
new file mode 100644
index 0000000..8e17820
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/HoneycombContextDOMDataBrokerProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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.infra.distro.data.context;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.DataBroker;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class HoneycombContextDOMDataBrokerProvider extends ProviderTrait<DOMDataBroker> {
+
+ @Inject
+ private ModifiableDataManager modDataManager;
+
+ public DataBroker create() {
+ return DataBroker.create(modDataManager);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java
new file mode 100644
index 0000000..9da97a8
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/ModifiableDTMgrProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.infra.distro.data.context;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.ModifiableDataTreeManager;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public final class ModifiableDTMgrProvider extends ProviderTrait<ModifiableDataManager> {
+
+ @Inject
+ private DataTree dataTree;
+
+ @Override
+ public ModifiableDataTreeManager create() {
+ return new ModifiableDataTreeManager(dataTree);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.java
new file mode 100644
index 0000000..cc1a8b1
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/context/RealtimeMappingContextProvider.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.infra.distro.data.context;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.util.RealtimeMappingContext;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+public final class RealtimeMappingContextProvider extends ProviderTrait<MappingContext> {
+
+ @Inject
+ @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+ private DataBroker contextDataBroker;
+
+ @Override
+ public RealtimeMappingContext create() {
+ return new RealtimeMappingContext(contextDataBroker);
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.java
new file mode 100644
index 0000000..caac736
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReadableDTDelegProvider.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.infra.distro.data.oper;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.data.ReadableDataManager;
+import io.fd.honeycomb.data.impl.ReadableDataTreeDelegator;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+
+public final class ReadableDTDelegProvider extends ProviderTrait<ReadableDataManager> {
+
+ @Inject
+ private BindingToNormalizedNodeCodec serializer;
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ private ReaderRegistry registry;
+ @Inject
+ @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+ private DataBroker contextBroker;
+
+ @Override
+ protected ReadableDataTreeDelegator create() {
+ return new ReadableDataTreeDelegator(serializer, schemaService.getGlobalContext(),
+ registry, contextBroker);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java
new file mode 100644
index 0000000..8f6bb0e
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/data/oper/ReaderRegistryProvider.java
@@ -0,0 +1,41 @@
+/*
+ * 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.infra.distro.data.oper;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.translate.impl.read.registry.CompositeReaderRegistryBuilder;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import io.fd.honeycomb.translate.util.YangDAG;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class ReaderRegistryProvider extends ProviderTrait<ReaderRegistry> {
+
+ @Inject(optional = true)
+ private Set<ReaderFactory> readerFactories = new HashSet<>();
+
+ @Override
+ protected ReaderRegistry create() {
+ final CompositeReaderRegistryBuilder builder = new CompositeReaderRegistryBuilder(new YangDAG());
+ readerFactories.stream()
+ .forEach(it -> it.init(builder));
+ return builder.build();
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.java
new file mode 100644
index 0000000..e0c38f3
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerPipelineModule.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.infra.distro.initializer;
+
+import com.google.inject.PrivateModule;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.init.InitializerRegistry;
+import io.fd.honeycomb.infra.distro.data.BindingDataBrokerProvider;
+import io.fd.honeycomb.infra.distro.data.HoneycombDOMDataBrokerProvider;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public final class InitializerPipelineModule extends PrivateModule {
+
+ public static final String HONEYCOMB_INITIALIZER = "honeycomb-initializer";
+
+ protected void configure() {
+ // Create data tree manager on top of non-persisting config data tree
+ bind(ModifiableDataManager.class).toProvider(ModifiableDTDelegInitProvider.class).in(Singleton.class);
+ // Wrap as DOMDataBroker
+ bind(DOMDataBroker.class).toProvider(HoneycombDOMDataBrokerProvider.class).in(Singleton.class);
+ // Wrap as BA data broker
+ bind(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER))
+ .toProvider(BindingDataBrokerProvider.class).in(Singleton.class);
+ expose(DataBroker.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER));
+
+ // Create initializer registry so that plugins can provide their initializers
+ bind(InitializerRegistry.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER))
+ .toProvider(InitializerRegistryAdapterProvider.class).in(Singleton.class);
+ expose(InitializerRegistry.class).annotatedWith(Names.named(HONEYCOMB_INITIALIZER));
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java
new file mode 100644
index 0000000..85fb777
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapter.java
@@ -0,0 +1,101 @@
+/*
+ * 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.infra.distro.initializer;
+
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.data.init.InitializerRegistry;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.registry.InitRegistry;
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class InitializerRegistryAdapter implements InitializerRegistry {
+
+ private static final Logger LOG = LoggerFactory.getLogger(InitializerRegistryAdapter.class);
+
+ private final DataTreeInitializer configInitializer;
+ private final DataTreeInitializer contextInitializer;
+ private final InitRegistry initRegistry;
+ private final DataBroker dataBroker;
+ private final MappingContext realtimeMappingContext;
+
+ InitializerRegistryAdapter(final DataTreeInitializer configInitializer,
+ final DataTreeInitializer contextInitializer,
+ final InitRegistry initRegistry,
+ final DataBroker noopConfigDataBroker,
+ final MappingContext realtimeMappingContext) {
+ this.configInitializer = configInitializer;
+ this.contextInitializer = contextInitializer;
+ this.initRegistry = initRegistry;
+ this.dataBroker = noopConfigDataBroker;
+ this.realtimeMappingContext = realtimeMappingContext;
+ }
+
+ @Override
+ public void initialize() throws DataTreeInitializer.InitializeException {
+ LOG.info("Config initialization started");
+
+ try {
+ // Initialize contexts first so that other initializers can find any relevant mapping before initializing
+ // configuration to what is already in VPP
+ contextInitializer.initialize();
+ LOG.info("Persisted context restored successfully");
+ // Initialize all registered initializers
+ initRegistry.initAll(dataBroker, new InitReadContext(realtimeMappingContext));
+ LOG.info("Configuration initialized successfully");
+ // Initialize stored configuration on top
+ configInitializer.initialize();
+ LOG.info("Persisted configuration restored successfully");
+ } catch (Exception e) {
+ LOG.warn("Failed to initialize config", e);
+ }
+
+ LOG.info("Honeycomb initialized");
+ }
+
+ private static final class InitReadContext implements ReadContext {
+
+ private final ModificationCache modificationCache;
+ private final MappingContext realtimeMappingContext;
+
+ InitReadContext(final MappingContext realtimeMappingContext) {
+ modificationCache = new ModificationCache();
+ this.realtimeMappingContext = realtimeMappingContext;
+ }
+
+ @Nonnull
+ @Override
+ public ModificationCache getModificationCache() {
+ return modificationCache;
+ }
+
+ @Nonnull
+ @Override
+ public MappingContext getMappingContext() {
+ return realtimeMappingContext;
+ }
+
+ @Override
+ public void close() {
+ modificationCache.close();
+ }
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java
new file mode 100644
index 0000000..4f5185c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/InitializerRegistryAdapterProvider.java
@@ -0,0 +1,54 @@
+/*
+ * 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.infra.distro.initializer;
+
+import static io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG;
+import static io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule.HONEYCOMB_CONTEXT;
+import static io.fd.honeycomb.infra.distro.initializer.InitializerPipelineModule.HONEYCOMB_INITIALIZER;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.data.init.DataTreeInitializer;
+import io.fd.honeycomb.data.init.InitializerRegistry;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+public final class InitializerRegistryAdapterProvider extends ProviderTrait<InitializerRegistry> {
+
+ @Inject
+ @Named(HONEYCOMB_CONTEXT)
+ private DataTreeInitializer contextInitializer;
+ @Inject
+ @Named(HONEYCOMB_CONFIG)
+ private DataTreeInitializer configInitializer;
+ @Inject
+ private ReaderRegistry initRegistry;
+ @Inject
+ @Named(HONEYCOMB_INITIALIZER)
+ private DataBroker noopConfigDataBroker;
+ @Inject
+ @Named(HONEYCOMB_CONTEXT)
+ private MappingContext realtimeMappingContext;
+
+ @Override
+ protected InitializerRegistryAdapter create() {
+ return new InitializerRegistryAdapter(configInitializer, contextInitializer, initRegistry,
+ noopConfigDataBroker, realtimeMappingContext);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java
new file mode 100644
index 0000000..3579ff1
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/ModifiableDTDelegInitProvider.java
@@ -0,0 +1,50 @@
+/*
+ * 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.infra.distro.initializer;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.data.ModifiableDataManager;
+import io.fd.honeycomb.data.impl.ModifiableDataTreeDelegator;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.data.ConfigAndOperationalPipelineModule;
+import io.fd.honeycomb.infra.distro.data.context.ContextPipelineModule;
+import io.fd.honeycomb.translate.util.write.NoopWriterRegistry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+
+public final class ModifiableDTDelegInitProvider extends ProviderTrait<ModifiableDataManager> {
+
+ @Inject
+ private BindingToNormalizedNodeCodec serializer;
+ @Inject
+ @Named(ConfigAndOperationalPipelineModule.HONEYCOMB_CONFIG_NONPERSIST)
+ private DataTree dataTree;
+ @Inject
+ @Named(ContextPipelineModule.HONEYCOMB_CONTEXT)
+ private DataBroker contextBroker;
+ @Inject
+ private SchemaService schemaService;
+
+ @Override
+ public ModifiableDataTreeDelegator create() {
+ return new ModifiableDataTreeDelegator(serializer, dataTree, schemaService.getGlobalContext(),
+ new NoopWriterRegistry(), contextBroker);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.java
new file mode 100644
index 0000000..58d63cf
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/initializer/PersistedFileInitializerProvider.java
@@ -0,0 +1,78 @@
+/*
+ * 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.infra.distro.initializer;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.data.init.RestoringInitializer;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import java.nio.file.Paths;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+
+public abstract class PersistedFileInitializerProvider extends ProviderTrait<RestoringInitializer> {
+
+ @Inject
+ private SchemaService schemaService;
+ @Inject
+ protected HoneycombConfiguration cfgAttributes;
+ @Inject
+ private DOMDataBroker domDataBroker;
+
+ @Override
+ public RestoringInitializer create() {
+ return new RestoringInitializer(schemaService, Paths.get(getPersistPath()), domDataBroker,
+ RestoringInitializer.RestorationType.valueOf(getRestorationType()), getDataStoreType());
+ }
+
+ public abstract String getPersistPath();
+
+ public abstract LogicalDatastoreType getDataStoreType();
+
+ public abstract String getRestorationType();
+
+ public static class PersistedContextInitializerProvider extends PersistedFileInitializerProvider {
+ public String getPersistPath() {
+ return cfgAttributes.peristContextPath;
+ }
+
+ public LogicalDatastoreType getDataStoreType() {
+ return LogicalDatastoreType.OPERATIONAL;
+ }
+
+ public String getRestorationType() {
+ return cfgAttributes.persistedContextRestorationType;
+ }
+
+ }
+
+ public static class PersistedConfigInitializerProvider extends PersistedFileInitializerProvider {
+ public String getPersistPath() {
+ return cfgAttributes.peristConfigPath;
+ }
+
+ public LogicalDatastoreType getDataStoreType() {
+ return LogicalDatastoreType.CONFIGURATION;
+ }
+
+ public String getRestorationType() {
+ return cfgAttributes.persistedConfigRestorationType;
+ }
+
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/HoneycombNotification2NetconfProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/HoneycombNotification2NetconfProvider.java
new file mode 100644
index 0000000..f60366c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+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 HoneycombConfiguration 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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfBindingBrokerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfBindingBrokerProvider.java
new file mode 100644
index 0000000..3d06b8d
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.impl.FakeBindingAwareBroker;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMdsalMapperProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMdsalMapperProvider.java
new file mode 100644
index 0000000..9ede54f
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.java
new file mode 100644
index 0000000..f3fddf3
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfModule.java
@@ -0,0 +1,131 @@
+/*
+ * 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.infra.distro.netconf;
+
+import static io.fd.honeycomb.infra.distro.data.InmemoryDOMDataBrokerProvider.CONFIG;
+import static io.fd.honeycomb.infra.distro.data.InmemoryDOMDataBrokerProvider.OPERATIONAL;
+
+import com.google.inject.PrivateModule;
+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.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;
+
+public class NetconfModule extends PrivateModule {
+
+ 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";
+
+ @Override
+ protected void configure() {
+ // 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).in(Singleton.class);
+ 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).in(Singleton.class);
+ 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).in(Singleton.class);
+ 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)
+ .in(Singleton.class);
+ expose(NetconfTcpServerProvider.NetconfTcpServer.class);
+ bind(NetconfSshServerProvider.NetconfSshServer.class).toProvider(NetconfSshServerProvider.class)
+ .in(Singleton.class);
+ return expose(NetconfSshServerProvider.NetconfSshServer.class);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringMapperProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringMapperProvider.java
new file mode 100644
index 0000000..f617ded
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringReaderFactoryProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringReaderFactoryProvider.java
new file mode 100644
index 0000000..3a4c136
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringServiceProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfMonitoringServiceProvider.java
new file mode 100644
index 0000000..9858003
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationMapperProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationMapperProvider.java
new file mode 100644
index 0000000..2554d02
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationsReaderFactoryProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfNotificationsReaderFactoryProvider.java
new file mode 100644
index 0000000..b699439
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.java
new file mode 100644
index 0000000..cb45f5d
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfReadersModule.java
@@ -0,0 +1,34 @@
+/*
+ * 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.infra.distro.netconf;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+
+public class NetconfReadersModule extends AbstractModule {
+
+ protected void configure() {
+ // 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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfServerDispatcherProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfServerDispatcherProvider.java
new file mode 100644
index 0000000..00c2d16
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.infra.distro.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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.java
new file mode 100644
index 0000000..ba36a26
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfSshServerProvider.java
@@ -0,0 +1,152 @@
+/*
+ * 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.infra.distro.netconf;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.InitializationException;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+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 HoneycombConfiguration cfgAttributes;
+ @Inject
+ private NioEventLoopGroup nettyThreadgroup;
+
+ private ScheduledExecutorService pool =
+ Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat("netconf-ssh-%d").build());
+
+ @Override
+ protected NetconfSshServer create() {
+ 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(cfgAttributes));
+ 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 HoneycombConfiguration cfgAttributes;
+
+ SimplelAuthProvider(final HoneycombConfiguration 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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.java
new file mode 100644
index 0000000..66b82ee
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NetconfTcpServerProvider.java
@@ -0,0 +1,86 @@
+/*
+ * 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.infra.distro.netconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.InitializationException;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+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 HoneycombConfiguration cfgAttributes;
+
+ @Override
+ protected NetconfTcpServer create() {
+ 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/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyThreadGroupProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/netconf/NettyThreadGroupProvider.java
new file mode 100644
index 0000000..e14952b
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/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.infra.distro.netconf;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import io.netty.channel.nio.NioEventLoopGroup;
+
+public final class NettyThreadGroupProvider extends ProviderTrait<NioEventLoopGroup> {
+
+ @Inject
+ private HoneycombConfiguration cfgAttributes;
+
+ @Override
+ protected NioEventLoopGroup create() {
+ return new NioEventLoopGroup(cfgAttributes.netconfNettyThreads,
+ new ThreadFactoryBuilder().setNameFormat("netconf-netty-%d").build());
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpConnectorProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpConnectorProvider.java
new file mode 100644
index 0000000..f298df1
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpConnectorProvider.java
@@ -0,0 +1,41 @@
+/*
+ * 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.infra.distro.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+
+final class HttpConnectorProvider extends ProviderTrait<ServerConnector> {
+
+ @Inject
+ private HoneycombConfiguration cfg;
+ @Inject
+ private Server server;
+
+ @Override
+ protected ServerConnector create() {
+ ServerConnector httpConnector =
+ new ServerConnector(server, cfg.acceptorsSize.get(), cfg.selectorsSize.get());
+ httpConnector.setHost(cfg.restconfBindingAddress.get());
+ httpConnector.setPort(cfg.restconfPort.get());
+ server.addConnector(httpConnector);
+ return httpConnector;
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpsConnectorProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpsConnectorProvider.java
new file mode 100644
index 0000000..68c0fb5
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/HttpsConnectorProvider.java
@@ -0,0 +1,75 @@
+/*
+ * 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.infra.distro.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import java.net.URL;
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+final class HttpsConnectorProvider extends ProviderTrait<ServerConnector> {
+
+ @Inject
+ private HoneycombConfiguration cfg;
+ @Inject
+ private Server server;
+
+ @Override
+ protected ServerConnector create() {
+ // SSL Context Factory
+ // Based on:
+ // https://github.com/eclipse/jetty.project/blob/jetty-9.3.x/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
+ // https://wiki.eclipse.org/Jetty/Howto/Configure_SSL#Loading_Keys_and_Certificates_via_PKCS12
+ // Keystore created with:
+ // openssl genrsa -des3 -out honeycomb.key
+ // openssl req -new -x509 -key honeycomb.key -out honeycomb.crt
+ // openssl pkcs12 -inkey honeycomb.key -in honeycomb.crt -export -out honeycomb.pkcs12
+ // keytool -importkeystore -srckeystore honeycomb.pkcs12 -srcstoretype PKCS12 -destkeystore honeycomb-keystore
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ URL keystoreURL = getClass().getResource(cfg.restconfKeystore.get());
+ sslContextFactory.setKeyStorePath(keystoreURL.getPath());
+ sslContextFactory.setKeyStorePassword(cfg.keystorePassword.get());
+ sslContextFactory.setKeyManagerPassword((cfg.keystoreManagerPassword.get()));
+ URL truststoreURL = getClass().getResource(cfg.restconfTruststore.get());
+ sslContextFactory.setTrustStorePath(truststoreURL.getPath());
+ sslContextFactory.setTrustStorePassword((cfg.truststorePassword.get()));
+ // TODO HONEYCOMB-167 make this more configurable
+ sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA", "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "SSL_DHE_DSS_WITH_DES_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+
+ // SSL Connector
+ ServerConnector sslConnector =
+ new ServerConnector(server, cfg.httpsAcceptorsSize.get(), cfg.httpsSelectorsSize.get(),
+ // The ssl connection factory delegates the real processing to http connection factory
+ new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
+ // That's why http connection factory is also required here
+ // Order is IMPORTANT here
+ new HttpConnectionFactory()
+ );
+ sslConnector.setHost(cfg.restconfHttpsBindingAddress.get());
+ sslConnector.setPort(cfg.restconfHttpsPort.get());
+ server.addConnector(sslConnector);
+ return sslConnector;
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/JettyServerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/JettyServerProvider.java
new file mode 100644
index 0000000..bc5fe8b
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/JettyServerProvider.java
@@ -0,0 +1,90 @@
+/*
+ * 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.infra.distro.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import java.net.URL;
+import java.util.Collections;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.HashLoginService;
+import org.eclipse.jetty.security.authentication.BasicAuthenticator;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.gzip.GzipHandler;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.util.security.Password;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+final class JettyServerProvider extends ProviderTrait<Server> {
+
+ private static final String REALM = "HCRealm";
+ // Mime types to be compressed when requested
+ private static final String[] GZIP_MIME_TYPES = {"application/xml",
+ "xml",
+ "application/yang.data+xml",
+ "application/json",
+ "application/yang.data+json"};
+
+ @Inject
+ private HoneycombConfiguration cfg;
+
+ @Override
+ protected Server create() {
+ Server server = new Server(new QueuedThreadPool(cfg.restPoolMaxSize.get(), cfg.restPoolMinSize.get()));
+
+ // Load Realm for basic auth
+ HashLoginService service = new HashLoginService(REALM);
+ // Reusing the name as role
+ service.putUser(cfg.username, new Password(cfg.password), new String[]{cfg.username});
+ server.addBean(service);
+
+ final URL resource = getClass().getResource("/");
+ WebAppContext webapp = new WebAppContext(resource.getPath(), cfg.restconfRootPath.get());
+
+ server.setHandler(getGzip(service, webapp));
+ return server;
+ }
+
+ private GzipHandler getGzip(final HashLoginService service, final WebAppContext webapp) {
+ final GzipHandler gzipHandler = new GzipHandler();
+ gzipHandler.setIncludedMimeTypes(GZIP_MIME_TYPES);
+ gzipHandler.setHandler(getBaseAuth(service, webapp));
+ return gzipHandler;
+ }
+
+ private ConstraintSecurityHandler getBaseAuth(HashLoginService service, WebAppContext webapp) {
+ Constraint constraint = new Constraint();
+ constraint.setName("auth");
+ constraint.setAuthenticate(true);
+ constraint.setRoles(new String[]{cfg.username});
+
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setPathSpec("/*");
+ mapping.setConstraint(constraint);
+
+ ConstraintSecurityHandler security = new ConstraintSecurityHandler();
+ security.setConstraintMappings(Collections.singletonList(mapping));
+ security.setAuthenticator(new BasicAuthenticator());
+ security.setLoginService(service);
+
+ security.setHandler(webapp);
+ return security;
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.java
new file mode 100644
index 0000000..7799d7f
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfModule.java
@@ -0,0 +1,39 @@
+/*
+ * 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.infra.distro.restconf;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.opendaylight.netconf.sal.rest.api.RestConnector;
+
+public class RestconfModule extends AbstractModule {
+
+ public static final String RESTCONF_HTTP = "restconf-http";
+ public static final String RESTCONF_HTTPS = "restconf-https";
+
+ protected void configure() {
+ bind(Server.class).toProvider(JettyServerProvider.class).in(Singleton.class);
+ bind(ServerConnector.class).annotatedWith(Names.named(RESTCONF_HTTP)).toProvider(HttpConnectorProvider.class)
+ .in(Singleton.class);
+ bind(ServerConnector.class).annotatedWith(Names.named(RESTCONF_HTTPS)).toProvider(HttpsConnectorProvider.class)
+ .in(Singleton.class);
+ bind(RestConnector.class).toProvider(RestconfProvider.class).in(Singleton.class);
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.java
new file mode 100644
index 0000000..6664c7d
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/restconf/RestconfProvider.java
@@ -0,0 +1,41 @@
+/*
+ * 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.infra.distro.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import io.fd.honeycomb.infra.distro.cfgattrs.HoneycombConfiguration;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.netconf.sal.rest.api.RestConnector;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfProviderImpl;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+
+final class RestconfProvider extends ProviderTrait<RestConnector> {
+
+ @Inject
+ private HoneycombConfiguration cfg;
+ @Inject
+ private Broker domBroker;
+
+ @Override
+ protected RestconfProviderImpl create() {
+ RestconfProviderImpl instance = new RestconfProviderImpl();
+ instance.setWebsocketPort(new PortNumber(cfg.restconfWebsocketPort.get()));
+ domBroker.registerProvider(instance);
+ return instance;
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java
new file mode 100644
index 0000000..e2d0fbf
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ModuleInfoBackedCtxProvider.java
@@ -0,0 +1,51 @@
+/*
+ * 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.infra.distro.schema;
+
+import static io.fd.honeycomb.infra.distro.schema.YangModulesProvider.YangModules;
+
+import com.google.common.base.MoreObjects;
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import java.util.stream.Collectors;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ModuleInfoBackedCtxProvider extends ProviderTrait<ModuleInfoBackedContext> {
+ private static final Logger LOG = LoggerFactory.getLogger(ModuleInfoBackedCtxProvider.class);
+
+ // optional in sense that list of modules inside can be empty if none was found
+ @Inject
+ private YangModules moduleInfos;
+
+ @Override
+ protected ModuleInfoBackedContext create() {
+ ModuleInfoBackedContext create = ModuleInfoBackedContext.create();
+ create.addModuleInfos(moduleInfos.getYangBindings().stream()
+ .map(YangModelBindingProvider::getModuleInfo)
+ .collect(Collectors.toList()));
+ LOG.debug("ModuleInfoBackedContext created from {}", moduleInfos);
+ return create;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("writerFactories", moduleInfos).toString();
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java
new file mode 100644
index 0000000..c851dab
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/ResourceLoader.java
@@ -0,0 +1,135 @@
+/*
+ * 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.infra.distro.schema;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.common.io.Resources;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import org.apache.commons.io.IOUtils;
+
+interface ResourceLoader {
+
+ default Set<String> loadResourceContentsOnPath(final String path) {
+ final URL folderUrl = getClass().getClassLoader().getResource(path);
+ checkNotNull(folderUrl, "Resources %s not found", path);
+
+ if (ResourceLoaderIml.urlToUri(folderUrl).getScheme().equals("jar")) {
+ return ResourceLoaderIml.readFromJar(path, folderUrl);
+ } else {
+ return ResourceLoaderIml.readFromFolder(folderUrl);
+ }
+
+ }
+
+ final class ResourceLoaderIml {
+
+ private static Set<String> readFromFolder(final URL folderUrl) {
+ final File folder = new File(folderUrl.getPath());
+ final File[] files = checkNotNull(folder.listFiles(), "No files present on path %s", folderUrl);
+ return Arrays.stream(files)
+ .map(ResourceLoaderIml::fileToUrl)
+ .map(ResourceLoaderIml::urlToContentString)
+ .flatMap(content -> Arrays.stream(content.split(System.lineSeparator())))
+ .filter(ResourceLoaderIml::filterNonEmpty)
+ .collect(Collectors.toSet());
+ }
+
+ private static Set<String> readFromJar(final String path, final URL url) {
+ final String uriString = urlToUri(url).toString();
+ final String fileReference = extractJarFilePath(uriString);
+ try (JarFile jar = new JarFile(new File(fileReference))) {
+ return Collections.list(jar.entries())
+ .stream()
+ .filter(jarEntry -> jarEntry.getName().contains(path))
+ .map(jarEntry -> getJarEntryStream(jar, jarEntry))
+ .map(ResourceLoaderIml::readJarEntryStream)
+ .flatMap(content -> Arrays.stream(content.split(System.lineSeparator())))
+ .filter(ResourceLoaderIml::filterNonEmpty)
+ .collect(Collectors.toSet());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static String extractJarFilePath(final String uriString) {
+ return uriString.substring(0, uriString.indexOf("!")).replace("jar:file:", "");
+ }
+
+ private static boolean filterNonEmpty(final String line) {
+ return !Strings.isNullOrEmpty(line.trim());
+ }
+
+ private static String readJarEntryStream(final InputStream inputStream) {
+ try {
+ final String value = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ IOUtils.closeQuietly(inputStream);
+ return value;
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static InputStream getJarEntryStream(final JarFile jar, final JarEntry jarEntry) {
+ try {
+ return jar.getInputStream(jarEntry);
+ } catch (IOException e) {
+ throw new IllegalStateException(format("Unable to get stream for entry %s | jar %s", jar, jarEntry));
+ }
+ }
+
+ private static URI urlToUri(final URL url) {
+ try {
+ return url.toURI();
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException(format("Unable to convert URL %s to URI", url));
+ }
+ }
+
+ private static String urlToContentString(final URL url) {
+ try {
+ return Resources.toString(url, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Unable to read resource from: " + url, e);
+ }
+ }
+
+ private static URL fileToUrl(final File file) {
+ try {
+ return file.toURI().toURL();
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java
new file mode 100644
index 0000000..0799a06
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaModule.java
@@ -0,0 +1,33 @@
+/*
+ * 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.infra.distro.schema;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+
+public class SchemaModule extends AbstractModule {
+
+ protected void configure() {
+ bind(ModuleInfoBackedContext.class).toProvider(ModuleInfoBackedCtxProvider.class).in(Singleton.class);
+ bind(SchemaService.class).toProvider(SchemaServiceProvider.class).in(Singleton.class);
+ bind(BindingToNormalizedNodeCodec.class).toProvider(SerializerProvider.class).in(Singleton.class);
+ }
+
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java
new file mode 100644
index 0000000..eb3552c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SchemaServiceProvider.java
@@ -0,0 +1,81 @@
+/*
+ * 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.infra.distro.schema;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+
+public final class SchemaServiceProvider extends ProviderTrait<SchemaService> {
+
+ @Inject
+ private ModuleInfoBackedContext mibCtx;
+
+ public StaticSchemaService create() {
+ return new StaticSchemaService(mibCtx.getSchemaContext());
+ }
+
+ /**
+ * Static schema context provider service.
+ */
+ private static final class StaticSchemaService implements SchemaService {
+ private final SchemaContext schemaContext;
+
+ StaticSchemaService(SchemaContext schemaContext) {
+ this.schemaContext = schemaContext;
+ }
+
+ @Override
+ public void addModule(final Module module) {
+ throw new UnsupportedOperationException("Static service");
+ }
+
+ @Override
+ public void removeModule(final Module module) {
+ throw new UnsupportedOperationException("Static service");
+ }
+
+ @Override
+ public SchemaContext getSessionContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public SchemaContext getGlobalContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+ final SchemaContextListener listener) {
+ listener.onGlobalContextUpdated(schemaContext);
+ return new ListenerRegistration<SchemaContextListener>() {
+ public void close() {}
+
+ public SchemaContextListener getInstance() {
+ return listener;
+ }
+
+ };
+ }
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java
new file mode 100644
index 0000000..2a1963c
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/SerializerProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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.infra.distro.schema;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.infra.distro.ProviderTrait;
+import javassist.ClassPool;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+
+public class SerializerProvider extends ProviderTrait<BindingToNormalizedNodeCodec> {
+
+ @Inject
+ private ModuleInfoBackedContext mibCtx;
+
+ @Override
+ protected BindingToNormalizedNodeCodec create() {
+ final DataObjectSerializerGenerator serializerGenerator =
+ StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()));
+ BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(serializerGenerator);
+ BindingRuntimeContext ctx = BindingRuntimeContext.create(mibCtx, mibCtx.getSchemaContext());
+ codecRegistry.onBindingRuntimeContextUpdated(ctx);
+ BindingToNormalizedNodeCodec codec = new BindingToNormalizedNodeCodec(mibCtx, codecRegistry);
+ codec.onGlobalContextUpdated(mibCtx.getSchemaContext());
+ return codec;
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java
new file mode 100644
index 0000000..d705226
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangBindingProviderModule.java
@@ -0,0 +1,30 @@
+/*
+ * 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.infra.distro.schema;
+
+import com.google.inject.AbstractModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class YangBindingProviderModule extends AbstractModule {
+ private static final Logger LOG = LoggerFactory.getLogger(YangBindingProviderModule.class);
+
+ protected void configure() {
+ LOG.info("Configuring YangBindingProviderModule");
+ bind(YangModulesProvider.YangModules.class).toProvider(YangModulesProvider.class).asEagerSingleton();
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java
new file mode 100644
index 0000000..a483cfd
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModuleMappingIndex.java
@@ -0,0 +1,69 @@
+/*
+ * 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.infra.distro.schema;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Multimap;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+
+/**
+ * Index from guice module to yang module providers
+ */
+class YangModuleMappingIndex implements ResourceLoader {
+
+ private static final String G_MODULE_TOKEN = "GUICE_MODULE:";
+ private static final String KEY_VALUE_SEPARATOR = "|";
+ private static final String Y_MODULE_TOKEN = "YANG_MODULES:";
+ private static final String Y_MODULE_SEPARATOR = ",";
+
+ /**
+ * key - module class name
+ * value - yang module provider
+ */
+ private final Multimap<String, String> index;
+
+ YangModuleMappingIndex(final String indexPath) {
+ this.index = LinkedListMultimap.create();
+ loadResourceContentsOnPath(indexPath)
+ .forEach(line -> {
+ final String moduleName = parseModuleName(line);
+ parseYangModules(line).forEach(yModuleProvider -> index.put(moduleName, yModuleProvider));
+ });
+ }
+
+ Set<String> getByModuleName(@Nonnull final String moduleName) {
+ return ImmutableSet.copyOf(index.get(moduleName));
+ }
+
+ int applicationModulesCount() {
+ return index.keySet().size();
+ }
+
+ private static String parseModuleName(final String rawLine) {
+ return rawLine.substring(rawLine.indexOf(G_MODULE_TOKEN) + G_MODULE_TOKEN.length(),
+ rawLine.indexOf(KEY_VALUE_SEPARATOR));
+ }
+
+ private static Stream<String> parseYangModules(final String rawLine) {
+ return Arrays.stream(rawLine.substring(rawLine.indexOf(Y_MODULE_TOKEN) + Y_MODULE_TOKEN.length())
+ .split(Y_MODULE_SEPARATOR));
+ }
+}
diff --git a/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java
new file mode 100644
index 0000000..f6d8ea0
--- /dev/null
+++ b/infra/minimal-distribution-core/src/main/java/io/fd/honeycomb/infra/distro/schema/YangModulesProvider.java
@@ -0,0 +1,97 @@
+/*
+ * 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.infra.distro.schema;
+
+
+import static java.lang.String.format;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Resources;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import io.fd.honeycomb.infra.distro.activation.ActivationConfig;
+import io.fd.honeycomb.infra.distro.activation.ActiveModules;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+
+/**
+ * Loads active yang modules
+ * Relying on generate yang-module-index
+ */
+public class YangModulesProvider implements Provider<YangModulesProvider.YangModules> {
+
+ @Inject
+ private ActiveModules activeModules;
+
+ @Inject
+ private ActivationConfig config;
+
+ @Override
+ public YangModules get() {
+ // no need to bind this, pretty big map and its needed just here
+ final YangModuleMappingIndex index = new YangModuleMappingIndex(config.getYangModulesIndexPath());
+
+ return new YangModules(activeModules.getActiveModulesClasses().stream()
+ .map(Class::getName)
+ .map(index::getByModuleName)
+ .flatMap(Collection::stream)
+ .map(YangModulesProvider::loadClass)
+ .map(aClass -> (Class<? extends YangModelBindingProvider>) aClass)
+ .collect(Collectors.toSet()));
+ }
+
+ static class YangModules {
+ private final Set<Class<? extends YangModelBindingProvider>> yangBindings;
+
+ YangModules(final Set<Class<? extends YangModelBindingProvider>> yangBindings) {
+ this.yangBindings = yangBindings;
+ }
+
+ Set<YangModelBindingProvider> getYangBindings() {
+ return yangBindings.stream()
+ .map(providerClass -> {
+ try {
+ return providerClass.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new IllegalStateException(format("Unable to create instance of %s", providerClass),
+ e);
+ }
+ }).collect(Collectors.toSet());
+ }
+ }
+
+ private static Class<?> loadClass(@Nonnull final String className) {
+ try {
+ return Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Unable to load class: " + className, e);
+ }
+ }
+
+ static String urlToString(@Nonnull final URL url) {
+ try {
+ return Resources.toString(url, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Unable to read resource from: " + url, e);
+ }
+ }
+}