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.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
27 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
28 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
29 import org.opendaylight.controller.config.threadpool.ThreadPool;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
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.PublicKeyAuth;
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 =
108 CACHE_DIRECTORY + File.separator + DEFAULT_CACHE_DIRECTORY;
111 * The name for the default schema repository.
113 private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
116 * The default schema repository in the case that one is not specified.
118 private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
119 new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
122 * The default <code>FilesystemSchemaSourceCache</code>, which stores cached files in <code>cache/schema</code>.
124 private static final FilesystemSchemaSourceCache<YangTextSchemaSource> DEFAULT_CACHE =
125 new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
126 new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
129 * The default factory for creating <code>SchemaContext</code> instances.
131 private static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
132 DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
135 * Keeps track of initialized Schema resources. A Map is maintained in which the key represents the name
136 * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>. The
137 * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
138 * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
139 * Netconf mount. Access to <code>SCHEMA_RESOURCES_DTO_MAP</code> should be surrounded by appropriate
140 * synchronization locks.
142 private static final Map<String, NetconfDevice.SchemaResourcesDTO> SCHEMA_RESOURCES_DTO_MAP = new HashMap<>();
144 // Initializes default constant instances for the case when the default schema repository
145 // directory cache/schema is used.
147 SCHEMA_RESOURCES_DTO_MAP.put(DEFAULT_CACHE_DIRECTORY,
148 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY,
149 DEFAULT_SCHEMA_CONTEXT_FACTORY,
150 new NetconfStateSchemasResolverImpl()));
151 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
152 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
153 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
156 protected final String topologyId;
157 private final NetconfClientDispatcher clientDispatcher;
158 private final EventExecutor eventExecutor;
159 protected final ScheduledThreadPool keepaliveExecutor;
160 protected final ThreadPool processingExecutor;
161 protected final SharedSchemaRepository sharedSchemaRepository;
162 protected final DataBroker dataBroker;
163 protected final DOMMountPointService mountPointService;
164 protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY;
165 protected SchemaRepository schemaRepository = DEFAULT_SCHEMA_REPOSITORY;
166 protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY;
167 protected String privateKeyPath;
168 protected String privateKeyPassphrase;
169 protected final AAAEncryptionService encryptionService;
170 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
172 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
173 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
174 final ThreadPool processingExecutor,
175 final SchemaRepositoryProvider schemaRepositoryProvider,
176 final DataBroker dataBroker, final DOMMountPointService mountPointService,
177 final AAAEncryptionService encryptionService) {
178 this.topologyId = topologyId;
179 this.clientDispatcher = clientDispatcher;
180 this.eventExecutor = eventExecutor;
181 this.keepaliveExecutor = keepaliveExecutor;
182 this.processingExecutor = processingExecutor;
183 this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository();
184 this.dataBroker = dataBroker;
185 this.mountPointService = mountPointService;
186 this.encryptionService = encryptionService;
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(final NodeId nodeId, final Node configNode) {
199 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, configNode);
200 return setupConnection(nodeId, configNode);
204 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
205 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
206 if (!activeConnectors.containsKey(nodeId)) {
207 return Futures.immediateFailedFuture(
208 new IllegalStateException("Unable to disconnect device that is not connected"));
211 // retrieve connection, and disconnect it
212 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
213 connectorDTO.getCommunicator().close();
214 connectorDTO.getFacade().close();
215 return Futures.immediateFuture(null);
218 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
219 final Node configNode) {
220 final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
222 Preconditions.checkNotNull(netconfNode.getHost());
223 Preconditions.checkNotNull(netconfNode.getPort());
224 Preconditions.checkNotNull(netconfNode.isTcpOnly());
226 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode);
227 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
228 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
229 final NetconfReconnectingClientConfiguration clientConfig =
230 getClientConfig(netconfClientSessionListener, netconfNode);
231 final ListenableFuture<NetconfDeviceCapabilities> future =
232 deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
234 activeConnectors.put(nodeId, deviceCommunicatorDTO);
236 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
238 public void onSuccess(final NetconfDeviceCapabilities result) {
239 LOG.debug("Connector for : " + nodeId.getValue() + " started succesfully");
243 public void onFailure(final Throwable throwable) {
244 LOG.error("Connector for : " + nodeId.getValue() + " failed");
245 // remove this node from active connectors?
252 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId,
253 final NetconfNode node) {
254 //setup default values since default value is not supported in mdsal
255 final Long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
256 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
257 final Long keepaliveDelay = node.getKeepaliveDelay() == null
258 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
259 final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
260 ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
262 final IpAddress ipAddress = node.getHost().getIpAddress();
263 final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
264 ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
265 node.getPort().getValue());
266 final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
268 RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
269 createSalFacade(remoteDeviceId);
271 if (keepaliveDelay > 0) {
272 LOG.warn("Adding keepalive facade, for device {}", nodeId);
273 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(),
274 keepaliveDelay, defaultRequestTimeoutMillis);
277 // pre register yang library sources as fallback schemas to schema registry
278 final List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
279 if (node.getYangLibrary() != null) {
280 final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
281 final String yangLibUsername = node.getYangLibrary().getUsername();
282 final String yangLigPassword = node.getYangLibrary().getPassword();
284 final LibraryModulesSchemas libraryModulesSchemas;
285 if (yangLibURL != null) {
286 if (yangLibUsername != null && yangLigPassword != null) {
287 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
289 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
292 for (final Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry
293 : libraryModulesSchemas.getAvailableModels().entrySet()) {
294 registeredYangLibSources
295 .add(schemaRegistry.registerSchemaSource(
296 new YangLibrarySchemaYangSourceProvider(remoteDeviceId,
297 libraryModulesSchemas.getAvailableModels()),
298 PotentialSchemaSource.create(sourceIdentifierURLEntry.getKey(),
299 YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
304 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
305 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
306 if (node.isSchemaless()) {
307 device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
309 device = new NetconfDeviceBuilder()
310 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
311 .setSchemaResourcesDTO(schemaResourcesDTO)
312 .setGlobalProcessingExecutor(processingExecutor.getExecutor())
313 .setId(remoteDeviceId)
314 .setSalFacade(salFacade)
318 final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
319 final int rpcMessageLimit =
320 node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
322 if (rpcMessageLimit < 1) {
323 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
326 return new NetconfConnectorDTO(userCapabilities.isPresent()
327 ? new NetconfDeviceCommunicator(remoteDeviceId, device, userCapabilities.get(), rpcMessageLimit)
328 : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit), salFacade);
331 protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
332 // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
333 NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
334 final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
335 // Only checks to ensure the String is not empty or null; further checks related to directory
336 // accessibility and file permissionsare handled during the FilesystemSchemaSourceCache initialization.
337 if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
338 // If a custom schema cache directory is specified, create the backing DTO; otherwise,
339 // the SchemaRegistry and SchemaContextFactory remain the default values.
340 if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
341 // Multiple modules may be created at once;
342 // synchronize to avoid issues with data consistency among threads.
343 synchronized (SCHEMA_RESOURCES_DTO_MAP) {
344 // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables
345 // if they already exist
346 schemaResourcesDTO = SCHEMA_RESOURCES_DTO_MAP.get(moduleSchemaCacheDirectory);
347 if (schemaResourcesDTO == null) {
348 schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
349 schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
350 TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(),
351 schemaResourcesDTO.getSchemaRegistry())
353 SCHEMA_RESOURCES_DTO_MAP.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
356 LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}",
357 nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
360 LOG.warn("schema-cache-directory for {} is null or empty; using the default {}",
361 nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY);
364 if (schemaResourcesDTO == null) {
365 schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository,
366 schemaContextFactory, new NetconfStateSchemasResolverImpl());
369 return schemaResourcesDTO;
373 * Creates the backing Schema classes for a particular directory.
375 * @param moduleSchemaCacheDirectory The string directory relative to "cache"
376 * @return A DTO containing the Schema classes for the Netconf mount.
378 private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
379 final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
380 final SchemaContextFactory schemaContextFactory
381 = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
382 setSchemaRegistry(repository);
383 setSchemaContextFactory(schemaContextFactory);
384 final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
385 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
386 repository.registerSchemaSourceListener(deviceCache);
387 return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
388 new NetconfStateSchemasResolverImpl());
392 * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
394 * @param schemaCacheDirectory The custom cache directory relative to "cache"
395 * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
397 private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(
398 final String schemaCacheDirectory) {
399 final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
400 return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class,
401 new File(relativeSchemaCacheDirectory));
405 * Sets the private key path from location specified in configuration file using blueprint.
407 public void setPrivateKeyPath(String privateKeyPath) {
408 this.privateKeyPath = privateKeyPath;
412 * Sets the private key passphrase from location specified in configuration file using blueprint.
414 public void setPrivateKeyPassphrase(String privateKeyPassphrase) {
415 this.privateKeyPassphrase = privateKeyPassphrase;
418 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
419 final NetconfNode node) {
421 //setup default values since default value is not supported in mdsal
422 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
423 ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis();
424 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
425 ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts();
426 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
427 ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis();
428 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
430 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue());
432 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
433 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
434 final ReconnectStrategy strategy = sf.createReconnectStrategy();
436 final AuthenticationHandler authHandler;
437 final Credentials credentials = node.getCredentials();
438 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
439 .netconf.node.credentials.credentials.LoginPassword) {
440 authHandler = new PublicKeyAuth(
441 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
442 .netconf.node.credentials.credentials.LoginPassword) credentials).getUsername(),
443 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
444 .netconf.node.credentials.credentials.LoginPassword) credentials).getPassword(),
445 privateKeyPath, privateKeyPassphrase, encryptionService);
447 throw new IllegalStateException("Only login/password authentification is supported");
450 return NetconfReconnectingClientConfigurationBuilder.create()
451 .withAddress(socketAddress)
452 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
453 .withReconnectStrategy(strategy)
454 .withAuthHandler(authHandler)
455 .withProtocol(node.isTcpOnly() ? NetconfClientConfiguration.NetconfClientProtocol.TCP :
456 NetconfClientConfiguration.NetconfClientProtocol.SSH)
457 .withConnectStrategyFactory(sf)
458 .withSessionListener(listener)
462 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id);
464 private InetSocketAddress getSocketAddress(final Host host, final int port) {
465 if (host.getDomainName() != null) {
466 return new InetSocketAddress(host.getDomainName().getValue(), port);
468 final IpAddress ipAddress = host.getIpAddress();
469 final String ip = ipAddress.getIpv4Address() != null
470 ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
471 return new InetSocketAddress(ip, port);
475 private Optional<UserPreferences> getUserCapabilities(final NetconfNode node) {
476 // if none of yang-module-capabilities or non-module-capabilities is specified
477 // just return absent
478 if (node.getYangModuleCapabilities() == null && node.getNonModuleCapabilities() == null) {
479 return Optional.absent();
482 final List<String> capabilities = new ArrayList<>();
484 boolean overrideYangModuleCaps = false;
485 if (node.getYangModuleCapabilities() != null) {
486 capabilities.addAll(node.getYangModuleCapabilities().getCapability());
487 overrideYangModuleCaps = node.getYangModuleCapabilities().isOverride();
490 //non-module capabilities should not exist in yang module capabilities
491 final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(capabilities);
492 Preconditions.checkState(netconfSessionPreferences.getNonModuleCaps().isEmpty(),
493 "List yang-module-capabilities/capability should contain only module based capabilities. "
494 + "Non-module capabilities used: " + netconfSessionPreferences.getNonModuleCaps());
496 boolean overrideNonModuleCaps = false;
497 if (node.getNonModuleCapabilities() != null) {
498 capabilities.addAll(node.getNonModuleCapabilities().getCapability());
499 overrideNonModuleCaps = node.getNonModuleCapabilities().isOverride();
502 return Optional.of(new UserPreferences(NetconfSessionPreferences
503 .fromStrings(capabilities, CapabilityOrigin.UserDefined), overrideYangModuleCaps, overrideNonModuleCaps));
506 private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory {
507 private final Long connectionAttempts;
508 private final EventExecutor executor;
509 private final double sleepFactor;
510 private final int minSleep;
512 TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts,
513 final int minSleep, final BigDecimal sleepFactor) {
514 if (maxConnectionAttempts != null && maxConnectionAttempts > 0) {
515 connectionAttempts = maxConnectionAttempts;
517 connectionAttempts = null;
520 this.sleepFactor = sleepFactor.doubleValue();
521 this.executor = executor;
522 this.minSleep = minSleep;
526 public ReconnectStrategy createReconnectStrategy() {
527 final Long maxSleep = null;
528 final Long deadline = null;
530 return new TimedReconnectStrategy(executor, minSleep,
531 minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
535 protected static class NetconfConnectorDTO implements AutoCloseable {
537 private final NetconfDeviceCommunicator communicator;
538 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
540 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator,
541 final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
542 this.communicator = communicator;
543 this.facade = facade;
546 public NetconfDeviceCommunicator getCommunicator() {
550 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
554 public NetconfClientSessionListener getSessionListener() {
559 public void close() {
560 communicator.close();