summaryrefslogtreecommitdiffstats
path: root/infra/northbound
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2017-07-13 20:21:01 +0200
committerMarek Gradzki <mgradzki@cisco.com>2017-07-14 12:20:49 +0000
commitb65cd89989ead7082089bf6f333e56b03f619606 (patch)
treec80952fdaead46627ca861d1b3edb68dc4b87f47 /infra/northbound
parent32771868ab8f9d2fdad236c049ec1c3fc3c76ba0 (diff)
HONEYCOMB-360 - Restconf Northbound Intefaces provider separation
- Restconf configuration included under restconf.json Change-Id: I45f503d3ef383bd6e3d356308d3212c7314b7a28 Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
Diffstat (limited to 'infra/northbound')
-rw-r--r--infra/northbound/pom.xml1
-rw-r--r--infra/northbound/restconf/asciidoc/Readme.adoc14
-rw-r--r--infra/northbound/restconf/pom.xml105
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java49
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.java86
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java94
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java74
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java113
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java29
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java59
-rw-r--r--infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java40
-rw-r--r--infra/northbound/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json21
12 files changed, 685 insertions, 0 deletions
diff --git a/infra/northbound/pom.xml b/infra/northbound/pom.xml
index 68554ea7f..e234d4c28 100644
--- a/infra/northbound/pom.xml
+++ b/infra/northbound/pom.xml
@@ -33,6 +33,7 @@
<modules>
<module>common</module>
<module>bgp</module>
+ <module>restconf</module>
</modules>
</project> \ No newline at end of file
diff --git a/infra/northbound/restconf/asciidoc/Readme.adoc b/infra/northbound/restconf/asciidoc/Readme.adoc
new file mode 100644
index 000000000..957949ab3
--- /dev/null
+++ b/infra/northbound/restconf/asciidoc/Readme.adoc
@@ -0,0 +1,14 @@
+= restconf
+
+Provides modules and configuration for RESTCONF northbound interface.
+
+* To start RESTCONF HTTP use
+ ** "restconf-http-enabled": "true"
+* To start RESTCONF HTTPS use
+ ** "restconf-https-enabled": "true"
+* To disable RESTCONF start use
+ ** "restconf-http-enabled": "false"
+ ** "restconf-https-enabled": "false"
+* To disable RESTCONF fully
+ ** comment/remove io.fd.honeycomb.northbound.restconf.RestconfModule
+from distribution module configuration \ No newline at end of file
diff --git a/infra/northbound/restconf/pom.xml b/infra/northbound/restconf/pom.xml
new file mode 100644
index 000000000..3f7427208
--- /dev/null
+++ b/infra/northbound/restconf/pom.xml
@@ -0,0 +1,105 @@
+<?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.10-SNAPSHOT</version>
+ <relativePath>../../../common/impl-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>io.fd.honeycomb.northbound</groupId>
+ <artifactId>restconf</artifactId>
+ <version>1.17.10-SNAPSHOT</version>
+
+ <properties>
+ <jersey.version>1.19.1</jersey.version>
+ <servlet.version>3.1.0</servlet.version>
+ <jetty.version>9.3.11.v20160721</jetty.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>io.fd.honeycomb</groupId>
+ <artifactId>binding-init</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Northbound common -->
+ <dependency>
+ <groupId>io.fd.honeycomb.northbound</groupId>
+ <artifactId>common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- ODL-Restconf -->
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>sal-rest-connector</artifactId>
+ </dependency>
+
+ <!-- Jersey + Jetty for RESTCONF -->
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty.version}</version>
+ </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>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java
new file mode 100644
index 000000000..04a767c32
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpConnectorProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class HttpConnectorProvider extends ProviderTrait<ServerConnector> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HttpConnectorProvider.class);
+
+ @Inject
+ private RestconfConfiguration cfg;
+ @Inject
+ private Server server;
+
+ @Override
+ protected ServerConnector create() {
+ if (!cfg.isRestconfHttpEnabled()) {
+ LOG.debug("RESTCONF HTTP disabled, skipping initialization");
+ return null;
+ }
+
+ LOG.info("Starting RESTCONF HTTP");
+ 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/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.java
new file mode 100644
index 000000000..5a27bcb8e
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/HttpsConnectorProvider.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.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+
+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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class HttpsConnectorProvider extends ProviderTrait<ServerConnector> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HttpsConnectorProvider.class);
+
+ @Inject
+ private RestconfConfiguration cfg;
+ @Inject
+ private Server server;
+
+ @Override
+ protected ServerConnector create() {
+ if (!cfg.isRestconfHttpsEnabled()) {
+ LOG.debug("RESTCONF HTTPS disabled, skipping initialization");
+ return null;
+ }
+ LOG.info("Starting RESTCONF HTTPS");
+ // 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/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java
new file mode 100644
index 000000000..a87459560
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerProvider.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+import io.fd.honeycomb.northbound.CredentialsConfiguration;
+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 RestconfConfiguration cfg;
+
+ @Inject
+ private CredentialsConfiguration credentialsCfg;
+
+ @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(credentialsCfg.username, new Password(credentialsCfg.password),
+ new String[]{credentialsCfg.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[]{credentialsCfg.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/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java
new file mode 100644
index 000000000..1bd50bb22
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/JettyServerStarter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+import static io.fd.honeycomb.northbound.restconf.RestconfModule.RESTCONF_HTTP;
+import static io.fd.honeycomb.northbound.restconf.RestconfModule.RESTCONF_HTTPS;
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+
+import javax.annotation.Nullable;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.opendaylight.netconf.sal.rest.api.RestConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class JettyServerStarter extends ProviderTrait<JettyServerStarter.ServerInit> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(JettyServerStarter.class);
+
+ @Inject
+ private Server server;
+
+ // injecting all connectors to make sure that server is started after they are added
+ @Inject
+ private RestConnector connector;
+
+ // if HTTP is disabled, null will be injected
+ @Nullable
+ @Inject(optional = true)
+ @Named(RESTCONF_HTTP)
+ private ServerConnector httpConnectorInit;
+
+ // if HTTPS is disabled, null will be injected
+ @Nullable
+ @Inject(optional = true)
+ @Named(RESTCONF_HTTPS)
+ private ServerConnector httpsConnectorInit;
+
+ @Override
+ protected ServerInit create() {
+ try {
+ LOG.info("Starting RESTCONF Jetty server");
+ server.start();
+ LOG.info("RESTCONF Jetty server successfully started");
+ } catch (Exception e) {
+ LOG.error("Unable to start RESTCONF Jetty server", e);
+ throw new IllegalStateException("Unable to start RESTCONF Jetty server", e);
+ }
+
+ return new ServerInit() {
+ };
+ }
+
+ interface ServerInit {
+ }
+}
diff --git a/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java
new file mode 100644
index 000000000..a02429b26
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfiguration.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+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;
+
+//TODO - HONEYCOMB-377 - do not include module to active modules if disabled
+@BindConfig(value = "restconf", syntax = Syntax.JSON)
+public class RestconfConfiguration {
+
+ public boolean isRestconfHttpEnabled() {
+ return Boolean.valueOf(restconfHttp);
+ }
+
+ public boolean isRestconfHttpsEnabled() {
+ return Boolean.valueOf(restconfHttps);
+ }
+
+ public boolean isRestconfEnabled() {
+ return isRestconfHttpEnabled() || isRestconfHttpsEnabled();
+ }
+
+ @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);
+
+ @Override
+ public String toString() {
+ return "RestconfConfiguration{" +
+ "restconfHttp='" + restconfHttp + '\'' +
+ ", restconfBindingAddress=" + restconfBindingAddress +
+ ", restconfPort=" + restconfPort +
+ ", restconfHttps='" + restconfHttps + '\'' +
+ ", restconfHttpsBindingAddress=" + restconfHttpsBindingAddress +
+ ", restconfHttpsPort=" + restconfHttpsPort +
+ ", restconfKeystore=" + restconfKeystore +
+ ", keystorePassword=" + keystorePassword +
+ ", keystoreManagerPassword=" + keystoreManagerPassword +
+ ", restconfTruststore=" + restconfTruststore +
+ ", truststorePassword=" + truststorePassword +
+ ", restconfWebsocketPort=" + restconfWebsocketPort +
+ ", restconfRootPath=" + restconfRootPath +
+ ", restPoolMaxSize=" + restPoolMaxSize +
+ ", restPoolMinSize=" + restPoolMinSize +
+ ", acceptorsSize=" + acceptorsSize +
+ ", selectorsSize=" + selectorsSize +
+ ", httpsAcceptorsSize=" + httpsAcceptorsSize +
+ ", httpsSelectorsSize=" + httpsSelectorsSize +
+ '}';
+ }
+}
diff --git a/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java
new file mode 100644
index 000000000..1e18a3700
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfConfigurationModule.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+import com.google.inject.AbstractModule;
+import net.jmob.guice.conf.core.ConfigurationModule;
+
+public class RestconfConfigurationModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ install(ConfigurationModule.create());
+ requestInjection(RestconfConfiguration.class);
+ }
+}
diff --git a/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java
new file mode 100644
index 000000000..9f9ecf7a2
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfModule.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+import com.google.inject.Singleton;
+import com.google.inject.name.Names;
+import io.fd.honeycomb.northbound.NorthboundAbstractModule;
+import io.fd.honeycomb.northbound.restconf.JettyServerStarter.ServerInit;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.opendaylight.netconf.sal.rest.api.RestConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RestconfModule extends NorthboundAbstractModule<RestconfConfiguration> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RestconfModule.class);
+
+ public static final String RESTCONF_HTTP = "restconf-http";
+ public static final String RESTCONF_HTTPS = "restconf-https";
+
+ public RestconfModule() {
+ super(new RestconfConfigurationModule(), RestconfConfiguration.class);
+ }
+
+ @Override
+ protected void configure() {
+ if (!getConfiguration().isRestconfEnabled()) {
+ LOG.info("Restconf is disabled, skipping configuration");
+ return;
+ }
+
+ LOG.info("Starting RESTCONF Northbound");
+ install(new RestconfConfigurationModule());
+ 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);
+ bind(ServerInit.class).toProvider(JettyServerStarter.class).asEagerSingleton();
+ }
+}
diff --git a/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java
new file mode 100644
index 000000000..d519a931d
--- /dev/null
+++ b/infra/northbound/restconf/src/main/java/io/fd/honeycomb/northbound/restconf/RestconfProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.northbound.restconf;
+
+import com.google.inject.Inject;
+import io.fd.honeycomb.binding.init.ProviderTrait;
+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 RestconfConfiguration 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/northbound/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json b/infra/northbound/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json
new file mode 100644
index 000000000..d04e4ed3d
--- /dev/null
+++ b/infra/northbound/restconf/src/main/resources/honeycomb-minimal-resources/config/restconf.json
@@ -0,0 +1,21 @@
+{
+ "restconf-http-enabled": "true",
+ "restconf-root-path": "/restconf",
+ "restconf-binding-address": "127.0.0.1",
+ "restconf-port": 8183,
+ "restconf-https-enabled": "true",
+ "restconf-https-binding-address": "0.0.0.0",
+ "restconf-https-port": 8445,
+ "restconf-keystore": "/honeycomb-keystore",
+ "restconf-keystore-password": "OBF:1v9s1unr1unn1vv51zlk1t331vg91x1b1vgl1t331zly1vu51uob1uo71v8u",
+ "restconf-keystore-manager-password": "OBF:1v9s1unr1unn1vv51zlk1t331vg91x1b1vgl1t331zly1vu51uob1uo71v8u",
+ "restconf-truststore": "/honeycomb-keystore",
+ "restconf-truststore-password": "OBF:1v9s1unr1unn1vv51zlk1t331vg91x1b1vgl1t331zly1vu51uob1uo71v8u",
+ "restconf-websocket-port": 7779,
+ "restconf-pool-max-size": 10,
+ "restconf-pool-min-size": 1,
+ "restconf-acceptors-size": 1,
+ "restconf-selectors-size": 1,
+ "restconf-https-acceptors-size": 1,
+ "restconf-https-selectors-size": 1
+}