f212edc2d3f3a4f44aae85d53c1fa06d993d2afa
[netconf.git] / opendaylight / netconf / netconf-ssh / src / main / java / org / opendaylight / controller / config / yang / netconf / northbound / ssh / NetconfNorthboundSshModule.java
1 package org.opendaylight.controller.config.yang.netconf.northbound.ssh;
2
3 import io.netty.channel.ChannelFuture;
4 import io.netty.channel.local.LocalAddress;
5 import io.netty.util.concurrent.GenericFutureListener;
6 import java.io.IOException;
7 import java.net.InetAddress;
8 import java.net.InetSocketAddress;
9 import java.net.UnknownHostException;
10 import java.util.concurrent.Executors;
11 import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
12 import org.opendaylight.netconf.api.NetconfServerDispatcher;
13 import org.opendaylight.netconf.ssh.SshProxyServer;
14 import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 public class NetconfNorthboundSshModule extends org.opendaylight.controller.config.yang.netconf.northbound.ssh.AbstractNetconfNorthboundSshModule {
19
20     private static final Logger LOG = LoggerFactory.getLogger(NetconfNorthboundSshModule.class);
21
22     public NetconfNorthboundSshModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
23         super(identifier, dependencyResolver);
24     }
25
26     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) {
27         super(identifier, dependencyResolver, oldModule, oldInstance);
28     }
29
30     @Override
31     public void customValidation() {
32         // add custom validation form module attributes here.
33     }
34
35     @Override
36     public java.lang.AutoCloseable createInstance() {
37         final NetconfServerDispatcher dispatch = getDispatcherDependency();
38
39         final LocalAddress localAddress = new LocalAddress(getPort().toString());
40         final ChannelFuture localServer = dispatch.createLocalServer(localAddress);
41
42         final SshProxyServer sshProxyServer = new SshProxyServer(Executors.newScheduledThreadPool(1), getWorkerThreadGroupDependency(), getEventExecutorDependency());
43
44         final InetSocketAddress bindingAddress = getInetAddress();
45         final SshProxyServerConfigurationBuilder sshProxyServerConfigurationBuilder = new SshProxyServerConfigurationBuilder();
46         sshProxyServerConfigurationBuilder.setBindingAddress(bindingAddress);
47         sshProxyServerConfigurationBuilder.setLocalAddress(localAddress);
48         sshProxyServerConfigurationBuilder.setAuthenticator(getAuthProviderDependency());
49         sshProxyServerConfigurationBuilder.setIdleTimeout(Integer.MAX_VALUE);
50         sshProxyServerConfigurationBuilder.setKeyPairProvider(new PEMGeneratorHostKeyProvider());
51
52         localServer.addListener(new GenericFutureListener<ChannelFuture>() {
53
54             @Override
55             public void operationComplete(final ChannelFuture future) {
56                 if(future.isDone() && !future.isCancelled()) {
57                     try {
58                         sshProxyServer.bind(sshProxyServerConfigurationBuilder.createSshProxyServerConfiguration());
59                         LOG.info("Netconf SSH endpoint started successfully at {}", bindingAddress);
60                     } catch (final IOException e) {
61                         throw new RuntimeException("Unable to start SSH netconf server", e);
62                     }
63                 } else {
64                     LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause());
65                     throw new RuntimeException("Unable to start SSH netconf server", future.cause());
66                 }
67             }
68         });
69
70         return new NetconfServerCloseable(localServer, sshProxyServer);
71     }
72
73     private InetSocketAddress getInetAddress() {
74         try {
75             final InetAddress inetAd = InetAddress.getByName(getBindingAddress().getIpv4Address() == null ? getBindingAddress().getIpv6Address().getValue() : getBindingAddress().getIpv4Address().getValue());
76             return new InetSocketAddress(inetAd, getPort().getValue());
77         } catch (final UnknownHostException e) {
78             throw new IllegalArgumentException("Unable to bind netconf endpoint to address " + getBindingAddress(), e);
79         }
80     }
81
82     private static final class NetconfServerCloseable implements AutoCloseable {
83         private final ChannelFuture localServer;
84         private final SshProxyServer sshProxyServer;
85
86         public NetconfServerCloseable(final ChannelFuture localServer, final SshProxyServer sshProxyServer) {
87             this.localServer = localServer;
88             this.sshProxyServer = sshProxyServer;
89         }
90
91         @Override
92         public void close() throws Exception {
93             sshProxyServer.close();
94
95             if(localServer.isDone()) {
96                 localServer.channel().close();
97             } else {
98                 localServer.cancel(true);
99             }
100         }
101     }
102 }