2 * Copyright (c) 2015 Cisco Systems, Inc. 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
9 package org.opendaylight.netconf.topology;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.base.Strings;
14 import com.google.common.collect.Lists;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import io.netty.util.concurrent.EventExecutor;
20 import java.math.BigDecimal;
21 import java.net.InetSocketAddress;
23 import java.util.HashMap;
24 import java.util.List;
26 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
27 import org.opendaylight.controller.config.threadpool.ThreadPool;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
30 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
31 import org.opendaylight.controller.sal.core.api.Broker;
32 import org.opendaylight.netconf.api.NetconfMessage;
33 import org.opendaylight.netconf.client.NetconfClientDispatcher;
34 import org.opendaylight.netconf.client.NetconfClientSessionListener;
35 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
36 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
37 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
38 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
39 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
40 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
41 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
42 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
43 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
44 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
45 import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
46 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
47 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
48 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
49 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
50 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
51 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
52 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
53 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
54 import org.opendaylight.netconf.topology.api.NetconfTopology;
55 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
56 import org.opendaylight.protocol.framework.ReconnectStrategy;
57 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
58 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
66 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
67 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
68 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
69 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
70 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
71 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
72 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
73 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
74 import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
75 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
76 import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
80 public abstract class AbstractNetconfTopology implements NetconfTopology {
82 private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
84 protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
85 protected static final int DEFAULT_KEEPALIVE_DELAY = 0;
86 protected static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
87 protected static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
88 private static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
89 private static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
90 private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
91 private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
93 // constants related to Schema Cache(s)
95 * Filesystem based caches are stored relative to the cache directory.
97 private static final String CACHE_DIRECTORY = "cache";
100 * The default cache directory relative to <code>CACHE_DIRECTORY</code>
102 private static final String DEFAULT_CACHE_DIRECTORY = "schema";
105 * The qualified schema cache directory <code>cache/schema</code>
107 private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY = CACHE_DIRECTORY + File.separator+ DEFAULT_CACHE_DIRECTORY;
110 * The name for the default schema repository
112 private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
115 * The default schema repository in the case that one is not specified.
117 private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
118 new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
121 * The default <code>FilesystemSchemaSourceCache</code>, which stores cached files in <code>cache/schema</code>.
123 private static final FilesystemSchemaSourceCache<YangTextSchemaSource> DEFAULT_CACHE =
124 new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
125 new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
128 * The default factory for creating <code>SchemaContext</code> instances.
130 private static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
131 DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
134 * Keeps track of initialized Schema resources. A Map is maintained in which the key represents the name
135 * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>. The
136 * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
137 * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
138 * Netconf mount. Access to <code>schemaResourcesDTOs</code> should be surrounded by appropriate
139 * synchronization locks.
141 private static volatile Map<String, NetconfDevice.SchemaResourcesDTO> schemaResourcesDTOs = new HashMap<>();
143 // Initializes default constant instances for the case when the default schema repository
144 // directory cache/schema is used.
146 schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY,
147 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY,
148 DEFAULT_SCHEMA_CONTEXT_FACTORY,
149 new NetconfStateSchemasResolverImpl()));
150 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
151 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
152 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
155 protected final String topologyId;
156 private final NetconfClientDispatcher clientDispatcher;
157 protected final BindingAwareBroker bindingAwareBroker;
158 protected final Broker domBroker;
159 private final EventExecutor eventExecutor;
160 protected final ScheduledThreadPool keepaliveExecutor;
161 protected final ThreadPool processingExecutor;
162 protected final SharedSchemaRepository sharedSchemaRepository;
163 protected final DataBroker dataBroker;
164 protected final DOMMountPointService mountPointService;
166 protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY;
167 protected SchemaRepository schemaRepository = DEFAULT_SCHEMA_REPOSITORY;
168 protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY;
170 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
172 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
173 final BindingAwareBroker bindingAwareBroker, final Broker domBroker,
174 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
175 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
176 final DataBroker dataBroker, final DOMMountPointService mountPointService) {
177 this.topologyId = topologyId;
178 this.clientDispatcher = clientDispatcher;
179 this.bindingAwareBroker = bindingAwareBroker;
180 this.domBroker = domBroker;
181 this.eventExecutor = eventExecutor;
182 this.keepaliveExecutor = keepaliveExecutor;
183 this.processingExecutor = processingExecutor;
184 this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository();
185 this.dataBroker = dataBroker;
186 this.mountPointService = mountPointService;
189 public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) {
190 this.schemaRegistry = schemaRegistry;
193 public void setSchemaContextFactory(final SchemaContextFactory schemaContextFactory) {
194 this.schemaContextFactory = schemaContextFactory;
198 public ListenableFuture<NetconfDeviceCapabilities> connectNode(NodeId nodeId, Node configNode) {
199 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, configNode);
200 return setupConnection(nodeId, configNode);
204 public ListenableFuture<Void> disconnectNode(NodeId nodeId) {
205 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
206 if (!activeConnectors.containsKey(nodeId)) {
207 return Futures.immediateFailedFuture(new IllegalStateException("Unable to disconnect device that is not connected"));
210 // retrieve connection, and disconnect it
211 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
212 connectorDTO.getCommunicator().close();
213 connectorDTO.getFacade().close();
214 return Futures.immediateFuture(null);
217 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
218 final Node configNode) {
219 final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
221 Preconditions.checkNotNull(netconfNode.getHost());
222 Preconditions.checkNotNull(netconfNode.getPort());
223 Preconditions.checkNotNull(netconfNode.isTcpOnly());
225 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode);
226 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
227 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
228 final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(netconfClientSessionListener, netconfNode);
229 final ListenableFuture<NetconfDeviceCapabilities> future = deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
231 activeConnectors.put(nodeId, deviceCommunicatorDTO);
233 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
235 public void onSuccess(NetconfDeviceCapabilities result) {
236 LOG.debug("Connector for : " + nodeId.getValue() + " started succesfully");
240 public void onFailure(Throwable t) {
241 LOG.error("Connector for : " + nodeId.getValue() + " failed");
242 // remove this node from active connectors?
249 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId,
250 final NetconfNode node) {
251 //setup default values since default value is not supported in mdsal
252 final Long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
253 final Long keepaliveDelay = node.getKeepaliveDelay() == null ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
254 final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
256 IpAddress ipAddress = node.getHost().getIpAddress();
257 InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null ?
258 ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
259 node.getPort().getValue());
260 RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
262 RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
263 createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker);
265 if (keepaliveDelay > 0) {
266 LOG.warn("Adding keepalive facade, for device {}", nodeId);
267 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay, defaultRequestTimeoutMillis);
270 // pre register yang library sources as fallback schemas to schema registry
271 List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
272 if (node.getYangLibrary() != null) {
273 final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
274 final String yangLibUsername = node.getYangLibrary().getUsername();
275 final String yangLigPassword = node.getYangLibrary().getPassword();
277 LibraryModulesSchemas libraryModulesSchemas;
278 if(yangLibURL != null) {
279 if(yangLibUsername != null && yangLigPassword != null) {
280 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
282 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
285 for (Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry : libraryModulesSchemas.getAvailableModels().entrySet()) {
286 registeredYangLibSources.
287 add(schemaRegistry.registerSchemaSource(
288 new YangLibrarySchemaYangSourceProvider(remoteDeviceId, libraryModulesSchemas.getAvailableModels()),
289 PotentialSchemaSource
290 .create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
291 PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
296 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
297 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
298 if (node.isSchemaless()) {
299 device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
301 device = new NetconfDeviceBuilder()
302 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
303 .setSchemaResourcesDTO(schemaResourcesDTO)
304 .setGlobalProcessingExecutor(processingExecutor.getExecutor())
305 .setId(remoteDeviceId)
306 .setSalFacade(salFacade)
310 final Optional<NetconfSessionPreferences> userCapabilities = getUserCapabilities(node);
311 final int rpcMessageLimit =
312 node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
314 if (rpcMessageLimit < 1) {
315 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
318 return new NetconfConnectorDTO(
319 userCapabilities.isPresent() ?
320 new NetconfDeviceCommunicator(
321 remoteDeviceId, device, new UserPreferences(userCapabilities.get(), node.getYangModuleCapabilities().isOverride()), rpcMessageLimit):
322 new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit), salFacade);
325 protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
326 // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
327 NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
328 final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
329 // Only checks to ensure the String is not empty or null; further checks related to directory accessibility and file permissions
330 // are handled during the FilesystemSchemaSourceCache initialization.
331 if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
332 // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry and
333 // SchemaContextFactory remain the default values.
334 if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
335 // Multiple modules may be created at once; synchronize to avoid issues with data consistency among threads.
336 synchronized(schemaResourcesDTOs) {
337 // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if they already exist
338 schemaResourcesDTO = schemaResourcesDTOs.get(moduleSchemaCacheDirectory);
339 if (schemaResourcesDTO == null) {
340 schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
341 schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
342 TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(), schemaResourcesDTO.getSchemaRegistry())
344 schemaResourcesDTOs.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
347 LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}",
348 nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
351 LOG.warn("schema-cache-directory for {} is null or empty; using the default {}",
352 nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY);
355 if (schemaResourcesDTO == null) {
356 schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaContextFactory,
357 new NetconfStateSchemasResolverImpl());
360 return schemaResourcesDTO;
364 * Creates the backing Schema classes for a particular directory.
366 * @param moduleSchemaCacheDirectory The string directory relative to "cache"
367 * @return A DTO containing the Schema classes for the Netconf mount.
369 private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
370 final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
371 final SchemaContextFactory schemaContextFactory
372 = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
373 setSchemaRegistry(repository);
374 setSchemaContextFactory(schemaContextFactory);
375 final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
376 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
377 repository.registerSchemaSourceListener(deviceCache);
378 return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
379 new NetconfStateSchemasResolverImpl());
383 * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
385 * @param schemaCacheDirectory The custom cache directory relative to "cache"
386 * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
388 private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(final String schemaCacheDirectory) {
389 final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
390 return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class, new File(relativeSchemaCacheDirectory));
393 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener, NetconfNode node) {
395 //setup default values since default value is not supported in mdsal
396 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis();
397 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts();
398 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis();
399 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
401 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue());
403 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
404 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
405 final ReconnectStrategy strategy = sf.createReconnectStrategy();
407 final AuthenticationHandler authHandler;
408 final Credentials credentials = node.getCredentials();
409 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) {
410 authHandler = new LoginPassword(
411 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) credentials).getUsername(),
412 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) credentials).getPassword());
414 throw new IllegalStateException("Only login/password authentification is supported");
417 return NetconfReconnectingClientConfigurationBuilder.create()
418 .withAddress(socketAddress)
419 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
420 .withReconnectStrategy(strategy)
421 .withAuthHandler(authHandler)
422 .withProtocol(node.isTcpOnly() ?
423 NetconfClientConfiguration.NetconfClientProtocol.TCP :
424 NetconfClientConfiguration.NetconfClientProtocol.SSH)
425 .withConnectStrategyFactory(sf)
426 .withSessionListener(listener)
430 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker);
432 private InetSocketAddress getSocketAddress(final Host host, int port) {
433 if(host.getDomainName() != null) {
434 return new InetSocketAddress(host.getDomainName().getValue(), port);
436 final IpAddress ipAddress = host.getIpAddress();
437 final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
438 return new InetSocketAddress(ip, port);
442 private Optional<NetconfSessionPreferences> getUserCapabilities(final NetconfNode node) {
443 if(node.getYangModuleCapabilities() == null) {
444 return Optional.absent();
447 final List<String> capabilities = node.getYangModuleCapabilities().getCapability();
448 if(capabilities == null || capabilities.isEmpty()) {
449 return Optional.absent();
452 final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined);
453 Preconditions.checkState(parsedOverrideCapabilities.getNonModuleCaps().isEmpty(), "Capabilities to override can " +
454 "only contain module based capabilities, non-module capabilities will be retrieved from the device," +
455 " configured non-module capabilities: " + parsedOverrideCapabilities.getNonModuleCaps());
457 return Optional.of(parsedOverrideCapabilities);
460 private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory {
461 private final Long connectionAttempts;
462 private final EventExecutor executor;
463 private final double sleepFactor;
464 private final int minSleep;
466 TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts, final int minSleep, final BigDecimal sleepFactor) {
467 if (maxConnectionAttempts != null && maxConnectionAttempts > 0) {
468 connectionAttempts = maxConnectionAttempts;
470 connectionAttempts = null;
473 this.sleepFactor = sleepFactor.doubleValue();
474 this.executor = executor;
475 this.minSleep = minSleep;
479 public ReconnectStrategy createReconnectStrategy() {
480 final Long maxSleep = null;
481 final Long deadline = null;
483 return new TimedReconnectStrategy(executor, minSleep,
484 minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
488 protected static class NetconfConnectorDTO implements AutoCloseable {
490 private final NetconfDeviceCommunicator communicator;
491 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
493 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator, final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
494 this.communicator = communicator;
495 this.facade = facade;
498 public NetconfDeviceCommunicator getCommunicator() {
502 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
506 public NetconfClientSessionListener getSessionListener() {
511 public void close() {
512 communicator.close();