Merge "Fixed inappropriate uses of log level INFO"
[controller.git] / opendaylight / netconf / netconf-ssh / src / main / java / org / opendaylight / controller / netconf / osgi / NetconfSSHActivator.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.netconf.osgi;
9
10 import com.google.common.base.Optional;
11 import java.io.FileInputStream;
12 import java.net.InetSocketAddress;
13 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
14 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
15 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
16 import org.opendaylight.controller.usermanager.IUserManager;
17 import org.osgi.framework.BundleActivator;
18 import org.osgi.framework.BundleContext;
19 import org.osgi.framework.ServiceReference;
20 import org.osgi.util.tracker.ServiceTracker;
21 import org.osgi.util.tracker.ServiceTrackerCustomizer;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 /**
26  * Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
27  * starts SSH Server in its own thread. This thread is closed when activator calls stop() method. Server opens socket
28  * and listen for client connections. Each client connection creation is handled in separate
29  * {@link org.opendaylight.controller.netconf.ssh.threads.SocketThread} thread.
30  * This thread creates two additional threads {@link org.opendaylight.controller.netconf.ssh.threads.IOThread}
31  * forwarding data from/to client.IOThread closes servers session and server connection when it gets -1 on input stream.
32  * {@link org.opendaylight.controller.netconf.ssh.threads.IOThread}'s run method waits for -1 on input stream to finish.
33  * All threads are daemons.
34  **/
35 public class NetconfSSHActivator implements BundleActivator{
36
37     private NetconfSSHServer server;
38     private static final Logger logger =  LoggerFactory.getLogger(NetconfSSHActivator.class);
39     private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
40     private IUserManager iUserManager;
41     private BundleContext context = null;
42
43     ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
44         @Override
45         public IUserManager addingService(ServiceReference<IUserManager> reference) {
46             logger.trace("Service {} added, let there be SSH bridge.", reference);
47             iUserManager =  context.getService(reference);
48             try {
49                 onUserManagerFound(iUserManager);
50             } catch (Exception e) {
51                 logger.trace("Can't start SSH server due to {}",e);
52             }
53             return iUserManager;
54         }
55         @Override
56         public void modifiedService(ServiceReference<IUserManager> reference, IUserManager service) {
57             logger.trace("Replacing modified service {} in netconf SSH.", reference);
58             server.addUserManagerService(service);
59         }
60         @Override
61         public void removedService(ServiceReference<IUserManager> reference, IUserManager service) {
62             logger.trace("Removing service {} from netconf SSH. " +
63                     "SSH won't authenticate users until IUserManeger service will be started.", reference);
64             removeUserManagerService();
65         }
66     };
67
68
69     @Override
70     public void start(BundleContext context) throws Exception {
71         this.context = context;
72         listenForManagerService();
73     }
74
75     @Override
76     public void stop(BundleContext context) throws Exception {
77         if (server != null){
78             server.stop();
79             logger.trace("Netconf SSH bridge is down ...");
80         }
81     }
82     private void startSSHServer() throws Exception {
83         logger.trace("Starting netconf SSH  bridge.");
84         Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
85         InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
86                 EXCEPTION_MESSAGE, true);
87
88         if (sshSocketAddressOptional.isPresent()){
89             String path = NetconfConfigUtil.getPrivateKeyPath(context);
90             path = path.replace("\\", "/");
91             if (path.equals("")){
92                 throw new Exception("Missing netconf.ssh.pk.path key in configuration file.");
93             }
94
95             try (FileInputStream fis = new FileInputStream(path)){
96                 AuthProvider authProvider = new AuthProvider(iUserManager,fis);
97                 this.server = NetconfSSHServer.start(sshSocketAddressOptional.get().getPort(),tcpSocketAddress,authProvider);
98             }
99
100             Thread serverThread = new  Thread(server,"netconf SSH server thread");
101             serverThread.setDaemon(true);
102             serverThread.start();
103             logger.trace("Netconf SSH  bridge up and running.");
104         } else {
105             logger.trace("No valid connection configuration for SSH bridge found.");
106             throw new Exception("No valid connection configuration for SSH bridge found.");
107         }
108     }
109     private void onUserManagerFound(IUserManager userManager) throws Exception{
110         if (server!=null && server.isUp()){
111            server.addUserManagerService(userManager);
112         } else {
113            startSSHServer();
114         }
115     }
116     private void removeUserManagerService(){
117         this.server.removeUserManagerService();
118     }
119     private void listenForManagerService(){
120         ServiceTracker<IUserManager, IUserManager> listenerTracker = new ServiceTracker<>(context, IUserManager.class,customizer);
121         listenerTracker.open();
122     }
123 }