2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.config.yang.netconf.northbound.ssh;
11 import io.netty.channel.ChannelFuture;
12 import io.netty.channel.local.LocalAddress;
13 import io.netty.util.concurrent.GenericFutureListener;
14 import java.io.IOException;
15 import java.net.InetAddress;
16 import java.net.InetSocketAddress;
17 import java.net.UnknownHostException;
18 import java.util.concurrent.Executors;
19 import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
20 import org.opendaylight.netconf.api.NetconfServerDispatcher;
21 import org.opendaylight.netconf.ssh.SshProxyServer;
22 import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
26 public class NetconfNorthboundSshModule extends org.opendaylight.controller.config.yang.netconf.northbound.ssh.AbstractNetconfNorthboundSshModule {
28 private static final Logger LOG = LoggerFactory.getLogger(NetconfNorthboundSshModule.class);
30 public NetconfNorthboundSshModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
31 super(identifier, dependencyResolver);
34 public NetconfNorthboundSshModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.netconf.northbound.ssh.NetconfNorthboundSshModule oldModule, final java.lang.AutoCloseable oldInstance) {
35 super(identifier, dependencyResolver, oldModule, oldInstance);
39 public void customValidation() {
40 // add custom validation form module attributes here.
44 public java.lang.AutoCloseable createInstance() {
45 final NetconfServerDispatcher dispatch = getDispatcherDependency();
47 final LocalAddress localAddress = new LocalAddress(getPort().toString());
48 final ChannelFuture localServer = dispatch.createLocalServer(localAddress);
50 final SshProxyServer sshProxyServer = new SshProxyServer(Executors.newScheduledThreadPool(1), getWorkerThreadGroupDependency(), getEventExecutorDependency());
52 final InetSocketAddress bindingAddress = getInetAddress();
53 final SshProxyServerConfigurationBuilder sshProxyServerConfigurationBuilder = new SshProxyServerConfigurationBuilder();
54 sshProxyServerConfigurationBuilder.setBindingAddress(bindingAddress);
55 sshProxyServerConfigurationBuilder.setLocalAddress(localAddress);
56 sshProxyServerConfigurationBuilder.setAuthenticator(getAuthProviderDependency());
57 sshProxyServerConfigurationBuilder.setIdleTimeout(Integer.MAX_VALUE);
58 sshProxyServerConfigurationBuilder.setKeyPairProvider(new PEMGeneratorHostKeyProvider());
60 localServer.addListener(new GenericFutureListener<ChannelFuture>() {
63 public void operationComplete(final ChannelFuture future) {
64 if(future.isDone() && !future.isCancelled()) {
66 sshProxyServer.bind(sshProxyServerConfigurationBuilder.createSshProxyServerConfiguration());
67 LOG.info("Netconf SSH endpoint started successfully at {}", bindingAddress);
68 } catch (final IOException e) {
69 throw new RuntimeException("Unable to start SSH netconf server", e);
72 LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause());
73 throw new RuntimeException("Unable to start SSH netconf server", future.cause());
78 return new NetconfServerCloseable(localServer, sshProxyServer);
81 private InetSocketAddress getInetAddress() {
83 final InetAddress inetAd = InetAddress.getByName(getBindingAddress().getIpv4Address() == null ? getBindingAddress().getIpv6Address().getValue() : getBindingAddress().getIpv4Address().getValue());
84 return new InetSocketAddress(inetAd, getPort().getValue());
85 } catch (final UnknownHostException e) {
86 throw new IllegalArgumentException("Unable to bind netconf endpoint to address " + getBindingAddress(), e);
90 private static final class NetconfServerCloseable implements AutoCloseable {
91 private final ChannelFuture localServer;
92 private final SshProxyServer sshProxyServer;
94 public NetconfServerCloseable(final ChannelFuture localServer, final SshProxyServer sshProxyServer) {
95 this.localServer = localServer;
96 this.sshProxyServer = sshProxyServer;
100 public void close() throws Exception {
101 sshProxyServer.close();
103 if(localServer.isDone()) {
104 localServer.channel().close();
106 localServer.cancel(true);