BUG-693 Config module for netconf client dispatcher.
[controller.git] / opendaylight / md-sal / sal-netconf-connector / src / main / java / org / opendaylight / controller / config / yang / md / sal / connector / netconf / NetconfConnectorModule.java
1 /*
2  * Copyright (c) 2014 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.config.yang.md.sal.connector.netconf;
9
10 import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkCondition;
11 import static org.opendaylight.controller.config.api.JmxAttributeValidationException.checkNotNull;
12
13 import io.netty.util.HashedWheelTimer;
14 import io.netty.util.concurrent.GlobalEventExecutor;
15
16 import java.io.File;
17 import java.io.InputStream;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22
23 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
24 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
25 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
26 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
27 import org.opendaylight.controller.netconf.util.handler.ssh.authentication.LoginPassword;
28 import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
29 import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
30 import org.opendaylight.protocol.framework.ReconnectStrategy;
31 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
32 import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
33 import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
34 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
35 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders;
36 import org.osgi.framework.BundleContext;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.google.common.net.InetAddresses;
41
42 /**
43  *
44  */
45 public final class NetconfConnectorModule extends org.opendaylight.controller.config.yang.md.sal.connector.netconf.AbstractNetconfConnectorModule
46 {
47     private static final Logger logger = LoggerFactory.getLogger(NetconfConnectorModule.class);
48
49     private static ExecutorService GLOBAL_PROCESSING_EXECUTOR = null;
50     private static AbstractCachingSchemaSourceProvider<String, InputStream> GLOBAL_NETCONF_SOURCE_PROVIDER = null;
51     private BundleContext bundleContext;
52
53     public NetconfConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
54         super(identifier, dependencyResolver);
55     }
56
57     public NetconfConnectorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, NetconfConnectorModule oldModule, java.lang.AutoCloseable oldInstance) {
58         super(identifier, dependencyResolver, oldModule, oldInstance);
59     }
60
61     @Override
62     protected void customValidation() {
63         checkNotNull(getAddress(), addressJmxAttribute);
64         //checkState(getAddress().getIpv4Address() != null || getAddress().getIpv6Address() != null,"Address must be set.");
65         checkNotNull(getPort(), portJmxAttribute);
66         checkNotNull(getDomRegistry(), portJmxAttribute);
67         checkNotNull(getDomRegistry(), domRegistryJmxAttribute);
68
69         checkNotNull(getConnectionTimeoutMillis(), connectionTimeoutMillisJmxAttribute);
70         checkCondition(getConnectionTimeoutMillis() > 0, "must be > 0", connectionTimeoutMillisJmxAttribute);
71
72         checkNotNull(getBetweenAttemptsTimeoutMillis(), betweenAttemptsTimeoutMillisJmxAttribute);
73         checkCondition(getBetweenAttemptsTimeoutMillis() > 0, "must be > 0", betweenAttemptsTimeoutMillisJmxAttribute);
74
75         // FIXME BUG-944 remove backwards compatibility
76         if(getClientDispatcher() == null) {
77             checkCondition(getBossThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", bossThreadGroupJmxAttribute);
78             checkCondition(getWorkerThreadGroup() != null, "Client dispatcher was not set, thread groups have to be set instead", workerThreadGroupJmxAttribute);
79         }
80
81         // Check username + password in case of ssh
82         if(getTcpOnly() == false) {
83             checkNotNull(getUsername(), usernameJmxAttribute);
84             checkNotNull(getPassword(), passwordJmxAttribute);
85         }
86
87     }
88
89     @Override
90     public java.lang.AutoCloseable createInstance() {
91
92         getDomRegistryDependency();
93         NetconfDevice device = new NetconfDevice(getIdentifier().getInstanceName());
94
95         device.setClientConfig(getClientConfig(device));
96
97         device.setProcessingExecutor(getGlobalProcessingExecutor());
98
99         device.setEventExecutor(getEventExecutorDependency());
100         device.setDispatcher(getClientDispatcher() == null ? createDispatcher() : getClientDispatcherDependency());
101         device.setSchemaSourceProvider(getGlobalNetconfSchemaProvider(bundleContext));
102
103         getDomRegistryDependency().registerProvider(device, bundleContext);
104         device.start();
105         return device;
106     }
107
108     private ExecutorService getGlobalProcessingExecutor() {
109         return GLOBAL_PROCESSING_EXECUTOR == null ? Executors.newCachedThreadPool() : GLOBAL_PROCESSING_EXECUTOR;
110     }
111
112     private synchronized AbstractCachingSchemaSourceProvider<String, InputStream> getGlobalNetconfSchemaProvider(BundleContext bundleContext) {
113         if(GLOBAL_NETCONF_SOURCE_PROVIDER == null) {
114             String storageFile = "cache/schema";
115             //            File directory = bundleContext.getDataFile(storageFile);
116             File directory = new File(storageFile);
117             SchemaSourceProvider<String> defaultProvider = SchemaSourceProviders.noopProvider();
118             GLOBAL_NETCONF_SOURCE_PROVIDER = FilesystemSchemaCachingProvider.createFromStringSourceProvider(defaultProvider, directory);
119         }
120         return GLOBAL_NETCONF_SOURCE_PROVIDER;
121     }
122
123     // FIXME BUG-944 remove backwards compatibility
124     /**
125      * @deprecated Use getClientDispatcherDependency method instead to retrieve injected dispatcher.
126      * This one creates new instance of NetconfClientDispatcher and will be removed in near future.
127      */
128     @Deprecated
129     private NetconfClientDispatcher createDispatcher() {
130         return new NetconfClientDispatcherImpl(getBossThreadGroupDependency(), getWorkerThreadGroupDependency(), new HashedWheelTimer());
131     }
132
133     public void setBundleContext(BundleContext bundleContext) {
134         this.bundleContext = bundleContext;
135     }
136
137     public NetconfClientConfiguration getClientConfig(final NetconfDevice device) {
138         InetSocketAddress socketAddress = getSocketAddress();
139         ReconnectStrategy strategy = getReconnectStrategy();
140         long clientConnectionTimeoutMillis = getConnectionTimeoutMillis();
141
142         return NetconfClientConfigurationBuilder.create()
143         .withAddress(socketAddress)
144         .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
145         .withReconnectStrategy(strategy)
146         .withSessionListener(new NetconfDeviceListener(device))
147         .withAuthHandler(new LoginPassword(getUsername(),getPassword()))
148         .withProtocol(getTcpOnly() ?
149                 NetconfClientConfiguration.NetconfClientProtocol.TCP :
150                 NetconfClientConfiguration.NetconfClientProtocol.SSH)
151         .build();
152     }
153
154     private ReconnectStrategy getReconnectStrategy() {
155         Long connectionAttempts;
156         if (getMaxConnectionAttempts() != null && getMaxConnectionAttempts() > 0) {
157             connectionAttempts = getMaxConnectionAttempts();
158         } else {
159             logger.trace("Setting {} on {} to infinity", maxConnectionAttemptsJmxAttribute, this);
160             connectionAttempts = null;
161         }
162         double sleepFactor = 1.0;
163         int minSleep = 1000;
164         Long maxSleep = null;
165         Long deadline = null;
166
167         return new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, getBetweenAttemptsTimeoutMillis(),
168                 minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
169     }
170
171     private InetSocketAddress getSocketAddress() {
172         /*
173          * Uncomment after Switch to IP Address
174         if(getAddress().getIpv4Address() != null) {
175             addressValue = getAddress().getIpv4Address().getValue();
176         } else {
177             addressValue = getAddress().getIpv6Address().getValue();
178         }
179          */
180         InetAddress inetAddress = InetAddresses.forString(getAddress());
181         return new InetSocketAddress(inetAddress, getPort().intValue());
182     }
183 }