2 * Copyright (c) 2016 Inocybe Technologies 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
8 package org.opendaylight.netconf.northbound;
10 import io.netty.channel.ChannelFuture;
11 import io.netty.channel.EventLoopGroup;
12 import io.netty.channel.local.LocalAddress;
13 import io.netty.util.concurrent.EventExecutor;
14 import java.io.IOException;
15 import java.net.InetSocketAddress;
16 import java.util.concurrent.Executors;
17 import org.opendaylight.netconf.auth.AuthProvider;
18 import org.opendaylight.netconf.northbound.ssh.SshProxyServer;
19 import org.opendaylight.netconf.northbound.ssh.SshProxyServerConfigurationBuilder;
20 import org.opendaylight.netconf.server.api.NetconfServerDispatcher;
21 import org.opendaylight.netconf.shaded.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
23 import org.osgi.service.component.annotations.Activate;
24 import org.osgi.service.component.annotations.Component;
25 import org.osgi.service.component.annotations.Deactivate;
26 import org.osgi.service.component.annotations.Reference;
27 import org.osgi.service.metatype.annotations.AttributeDefinition;
28 import org.osgi.service.metatype.annotations.Designate;
29 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * NETCONF server for MD-SAL (listening by default on port 2830).
36 @Component(service = { }, configurationPid = "org.opendaylight.netconf.ssh")
37 @Designate(ocd = NetconfNorthboundSshServer.Configuration.class)
38 public final class NetconfNorthboundSshServer implements AutoCloseable {
39 @ObjectClassDefinition
40 public @interface Configuration {
42 String bindingAddress() default "0.0.0.0";
43 @AttributeDefinition(min = "1", max = "65535")
44 int portNumber() default 2830;
47 private static final Logger LOG = LoggerFactory.getLogger(NetconfNorthboundSshServer.class);
49 private final ChannelFuture localServer;
50 private final SshProxyServer sshProxyServer;
53 public NetconfNorthboundSshServer(
54 @Reference final NetconfServerDispatcher netconfServerDispatcher,
55 @Reference(target = "(type=global-worker-group)") final EventLoopGroup workerGroup,
56 @Reference(target = "(type=global-event-executor)") final EventExecutor eventExecutor,
57 @Reference(target = "(type=netconf-auth-provider)") final AuthProvider authProvider,
58 final Configuration configuration) {
59 this(netconfServerDispatcher, workerGroup, eventExecutor, authProvider, configuration.bindingAddress(),
60 configuration.portNumber());
63 public NetconfNorthboundSshServer(final NetconfServerDispatcher netconfServerDispatcher,
64 final EventLoopGroup workerGroup, final EventExecutor eventExecutor, final AuthProvider authProvider,
65 final String bindingAddress, final int portNumber) {
66 final LocalAddress localAddress = new LocalAddress(String.valueOf(portNumber));
67 final var sshProxyServerConfiguration = new SshProxyServerConfigurationBuilder()
68 .setBindingAddress(getInetAddress(bindingAddress, portNumber))
69 .setLocalAddress(localAddress)
70 .setAuthenticator(authProvider)
71 .setIdleTimeout(Integer.MAX_VALUE)
72 .setKeyPairProvider(new SimpleGeneratorHostKeyProvider())
73 .createSshProxyServerConfiguration();
75 localServer = netconfServerDispatcher.createLocalServer(localAddress);
76 sshProxyServer = new SshProxyServer(Executors.newScheduledThreadPool(1), workerGroup, eventExecutor);
78 localServer.addListener(future -> {
79 if (future.isDone() && !future.isCancelled()) {
81 sshProxyServer.bind(sshProxyServerConfiguration);
82 } catch (final IOException e) {
83 throw new IllegalStateException("Unable to start SSH netconf server", e);
85 LOG.info("Netconf SSH endpoint started successfully at {}", bindingAddress);
87 LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause());
88 throw new IllegalStateException("Unable to start SSH netconf server", future.cause());
95 public void close() throws IOException {
96 sshProxyServer.close();
98 if (localServer.isDone()) {
99 localServer.channel().close();
101 localServer.cancel(true);
105 private static InetSocketAddress getInetAddress(final String bindingAddress, final int portNumber) {
106 final var ipAddress = IetfInetUtil.ipAddressFor(bindingAddress);
107 return new InetSocketAddress(IetfInetUtil.inetAddressFor(ipAddress), portNumber);