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