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 com.google.common.util.concurrent.MoreExecutors;
19 import io.netty.util.concurrent.EventExecutor;
21 import java.math.BigDecimal;
22 import java.net.InetSocketAddress;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
28 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
29 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
30 import org.opendaylight.controller.config.threadpool.ThreadPool;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
33 import org.opendaylight.netconf.api.NetconfMessage;
34 import org.opendaylight.netconf.client.NetconfClientDispatcher;
35 import org.opendaylight.netconf.client.NetconfClientSessionListener;
36 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
37 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
38 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
39 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
40 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswordHandler;
41 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
42 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
43 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
44 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
45 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
46 import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
47 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
48 import org.opendaylight.netconf.sal.connect.netconf.auth.DatastoreBackedPublicKeyAuth;
49 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
50 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
51 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
52 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
53 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
54 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfKeystoreAdapter;
55 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
56 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
57 import org.opendaylight.netconf.topology.api.NetconfTopology;
58 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
59 import org.opendaylight.protocol.framework.ReconnectStrategy;
60 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
61 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.KeyAuth;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordDeprecated;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPw;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPwUnencrypted;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.key.auth.KeyBased;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.LoginPassword;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencrypted;
74 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
75 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
76 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
77 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
78 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
79 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
80 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
81 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
82 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
83 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
84 import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
85 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
86 import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
87 import org.slf4j.Logger;
88 import org.slf4j.LoggerFactory;
90 public abstract class AbstractNetconfTopology implements NetconfTopology {
92 private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
94 protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
95 protected static final int DEFAULT_KEEPALIVE_DELAY = 0;
96 protected static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
97 protected static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
98 private static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
99 private static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
100 private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
101 private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
103 // constants related to Schema Cache(s)
105 * Filesystem based caches are stored relative to the cache directory.
107 private static final String CACHE_DIRECTORY = "cache";
110 * The default cache directory relative to <code>CACHE_DIRECTORY</code>.
112 private static final String DEFAULT_CACHE_DIRECTORY = "schema";
115 * The qualified schema cache directory <code>cache/schema</code>.
117 private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY =
118 CACHE_DIRECTORY + File.separator + DEFAULT_CACHE_DIRECTORY;
121 * The name for the default schema repository.
123 private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
126 * The default schema repository in the case that one is not specified.
128 private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
129 new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
132 * The default <code>FilesystemSchemaSourceCache</code>, which stores cached files in <code>cache/schema</code>.
134 private static final FilesystemSchemaSourceCache<YangTextSchemaSource> DEFAULT_CACHE =
135 new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
136 new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
139 * The default factory for creating <code>SchemaContext</code> instances.
141 private static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
142 DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
145 * Keeps track of initialized Schema resources. A Map is maintained in which the key represents the name
146 * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>. The
147 * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
148 * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
149 * Netconf mount. Access to <code>SCHEMA_RESOURCES_DTO_MAP</code> should be surrounded by appropriate
150 * synchronization locks.
152 private static final Map<String, NetconfDevice.SchemaResourcesDTO> SCHEMA_RESOURCES_DTO_MAP = new HashMap<>();
154 // Initializes default constant instances for the case when the default schema repository
155 // directory cache/schema is used.
157 SCHEMA_RESOURCES_DTO_MAP.put(DEFAULT_CACHE_DIRECTORY,
158 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY,
159 DEFAULT_SCHEMA_CONTEXT_FACTORY,
160 new NetconfStateSchemasResolverImpl()));
161 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
162 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
163 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
166 protected final String topologyId;
167 private final NetconfClientDispatcher clientDispatcher;
168 private final EventExecutor eventExecutor;
169 protected final ScheduledThreadPool keepaliveExecutor;
170 protected final ThreadPool processingExecutor;
171 protected final SharedSchemaRepository sharedSchemaRepository;
172 protected final DataBroker dataBroker;
173 protected final DOMMountPointService mountPointService;
174 private final NetconfKeystoreAdapter keystoreAdapter;
175 protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY;
176 protected SchemaRepository schemaRepository = DEFAULT_SCHEMA_REPOSITORY;
177 protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY;
178 protected String privateKeyPath;
179 protected String privateKeyPassphrase;
180 protected final AAAEncryptionService encryptionService;
181 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
183 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
184 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
185 final ThreadPool processingExecutor,
186 final SchemaRepositoryProvider schemaRepositoryProvider,
187 final DataBroker dataBroker, final DOMMountPointService mountPointService,
188 final AAAEncryptionService encryptionService) {
189 this.topologyId = topologyId;
190 this.clientDispatcher = clientDispatcher;
191 this.eventExecutor = eventExecutor;
192 this.keepaliveExecutor = keepaliveExecutor;
193 this.processingExecutor = processingExecutor;
194 this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository();
195 this.dataBroker = dataBroker;
196 this.mountPointService = mountPointService;
197 this.encryptionService = encryptionService;
199 this.keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
202 public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) {
203 this.schemaRegistry = schemaRegistry;
206 public void setSchemaContextFactory(final SchemaContextFactory schemaContextFactory) {
207 this.schemaContextFactory = schemaContextFactory;
211 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
212 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, configNode);
213 return setupConnection(nodeId, configNode);
217 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
218 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
219 if (!activeConnectors.containsKey(nodeId)) {
220 return Futures.immediateFailedFuture(
221 new IllegalStateException("Unable to disconnect device that is not connected"));
224 // retrieve connection, and disconnect it
225 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
226 connectorDTO.getCommunicator().close();
227 connectorDTO.getFacade().close();
228 return Futures.immediateFuture(null);
231 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
232 final Node configNode) {
233 final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
235 Preconditions.checkNotNull(netconfNode.getHost());
236 Preconditions.checkNotNull(netconfNode.getPort());
237 Preconditions.checkNotNull(netconfNode.isTcpOnly());
239 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode);
240 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
241 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
242 final NetconfReconnectingClientConfiguration clientConfig =
243 getClientConfig(netconfClientSessionListener, netconfNode);
244 final ListenableFuture<NetconfDeviceCapabilities> future =
245 deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
247 activeConnectors.put(nodeId, deviceCommunicatorDTO);
249 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
251 public void onSuccess(final NetconfDeviceCapabilities result) {
252 LOG.debug("Connector for : " + nodeId.getValue() + " started succesfully");
256 public void onFailure(final Throwable throwable) {
257 LOG.error("Connector for : " + nodeId.getValue() + " failed");
258 // remove this node from active connectors?
260 }, MoreExecutors.directExecutor());
265 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId,
266 final NetconfNode node) {
267 //setup default values since default value is not supported in mdsal
268 final Long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
269 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
270 final Long keepaliveDelay = node.getKeepaliveDelay() == null
271 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
272 final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
273 ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
275 final IpAddress ipAddress = node.getHost().getIpAddress();
276 final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
277 ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
278 node.getPort().getValue());
279 final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
281 RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
282 createSalFacade(remoteDeviceId);
284 if (keepaliveDelay > 0) {
285 LOG.warn("Adding keepalive facade, for device {}", nodeId);
286 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(),
287 keepaliveDelay, defaultRequestTimeoutMillis);
290 // pre register yang library sources as fallback schemas to schema registry
291 final List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
292 if (node.getYangLibrary() != null) {
293 final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
294 final String yangLibUsername = node.getYangLibrary().getUsername();
295 final String yangLigPassword = node.getYangLibrary().getPassword();
297 final LibraryModulesSchemas libraryModulesSchemas;
298 if (yangLibURL != null) {
299 if (yangLibUsername != null && yangLigPassword != null) {
300 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
302 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
305 for (final Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry
306 : libraryModulesSchemas.getAvailableModels().entrySet()) {
307 registeredYangLibSources
308 .add(schemaRegistry.registerSchemaSource(
309 new YangLibrarySchemaYangSourceProvider(remoteDeviceId,
310 libraryModulesSchemas.getAvailableModels()),
311 PotentialSchemaSource.create(sourceIdentifierURLEntry.getKey(),
312 YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
317 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
318 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
319 if (node.isSchemaless()) {
320 device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
322 device = new NetconfDeviceBuilder()
323 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
324 .setSchemaResourcesDTO(schemaResourcesDTO)
325 .setGlobalProcessingExecutor(processingExecutor.getExecutor())
326 .setId(remoteDeviceId)
327 .setSalFacade(salFacade)
331 final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
332 final int rpcMessageLimit =
333 node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
335 if (rpcMessageLimit < 1) {
336 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
339 return new NetconfConnectorDTO(userCapabilities.isPresent()
340 ? new NetconfDeviceCommunicator(remoteDeviceId, device, userCapabilities.get(), rpcMessageLimit)
341 : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit), salFacade);
344 protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
345 // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
346 NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
347 final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
348 // Only checks to ensure the String is not empty or null; further checks related to directory
349 // accessibility and file permissionsare handled during the FilesystemSchemaSourceCache initialization.
350 if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
351 // If a custom schema cache directory is specified, create the backing DTO; otherwise,
352 // the SchemaRegistry and SchemaContextFactory remain the default values.
353 if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
354 // Multiple modules may be created at once;
355 // synchronize to avoid issues with data consistency among threads.
356 synchronized (SCHEMA_RESOURCES_DTO_MAP) {
357 // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables
358 // if they already exist
359 schemaResourcesDTO = SCHEMA_RESOURCES_DTO_MAP.get(moduleSchemaCacheDirectory);
360 if (schemaResourcesDTO == null) {
361 schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
362 schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
363 TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(),
364 schemaResourcesDTO.getSchemaRegistry())
366 SCHEMA_RESOURCES_DTO_MAP.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
369 LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}",
370 nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
373 LOG.warn("schema-cache-directory for {} is null or empty; using the default {}",
374 nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY);
377 if (schemaResourcesDTO == null) {
378 schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository,
379 schemaContextFactory, new NetconfStateSchemasResolverImpl());
382 return schemaResourcesDTO;
386 * Creates the backing Schema classes for a particular directory.
388 * @param moduleSchemaCacheDirectory The string directory relative to "cache"
389 * @return A DTO containing the Schema classes for the Netconf mount.
391 private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
392 final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
393 final SchemaContextFactory schemaContextFactory
394 = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
395 setSchemaRegistry(repository);
396 setSchemaContextFactory(schemaContextFactory);
397 final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
398 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
399 repository.registerSchemaSourceListener(deviceCache);
400 return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
401 new NetconfStateSchemasResolverImpl());
405 * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
407 * @param schemaCacheDirectory The custom cache directory relative to "cache"
408 * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
410 private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(
411 final String schemaCacheDirectory) {
412 final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
413 return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class,
414 new File(relativeSchemaCacheDirectory));
418 * Sets the private key path from location specified in configuration file using blueprint.
420 public void setPrivateKeyPath(String privateKeyPath) {
421 this.privateKeyPath = privateKeyPath;
425 * Sets the private key passphrase from location specified in configuration file using blueprint.
427 public void setPrivateKeyPassphrase(String privateKeyPassphrase) {
428 this.privateKeyPassphrase = privateKeyPassphrase;
431 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
432 final NetconfNode node) {
434 //setup default values since default value is not supported in mdsal
435 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
436 ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis();
437 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
438 ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts();
439 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
440 ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis();
441 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
443 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue());
445 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
446 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
447 final ReconnectStrategy strategy = sf.createReconnectStrategy();
449 final AuthenticationHandler authHandler = getHandlerFromCredentials(node.getCredentials());
451 return NetconfReconnectingClientConfigurationBuilder.create()
452 .withAddress(socketAddress)
453 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
454 .withReconnectStrategy(strategy)
455 .withAuthHandler(authHandler)
456 .withProtocol(node.isTcpOnly() ? NetconfClientConfiguration.NetconfClientProtocol.TCP :
457 NetconfClientConfiguration.NetconfClientProtocol.SSH)
458 .withConnectStrategyFactory(sf)
459 .withSessionListener(listener)
463 private AuthenticationHandler getHandlerFromCredentials(final Credentials credentials) {
464 if (credentials instanceof LoginPasswordDeprecated) {
465 final LoginPasswordDeprecated loginPassword = (LoginPasswordDeprecated) credentials;
466 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
468 if (credentials instanceof LoginPwUnencrypted) {
469 final LoginPasswordUnencrypted loginPassword =
470 ((LoginPwUnencrypted) credentials).getLoginPasswordUnencrypted();
471 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
473 if (credentials instanceof LoginPw) {
474 final LoginPassword loginPassword = ((LoginPw) credentials).getLoginPassword();
475 return new LoginPasswordHandler(loginPassword.getUsername(),
476 encryptionService.decrypt(loginPassword.getPassword()));
478 if (credentials instanceof KeyAuth) {
479 final KeyBased keyPair = ((KeyAuth) credentials).getKeyBased();
480 return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(),
481 keystoreAdapter, encryptionService);
483 throw new IllegalStateException("Unsupported credential type: " + credentials.getClass());
486 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id);
488 private InetSocketAddress getSocketAddress(final Host host, final int port) {
489 if (host.getDomainName() != null) {
490 return new InetSocketAddress(host.getDomainName().getValue(), port);
492 final IpAddress ipAddress = host.getIpAddress();
493 final String ip = ipAddress.getIpv4Address() != null
494 ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
495 return new InetSocketAddress(ip, port);
499 private Optional<UserPreferences> getUserCapabilities(final NetconfNode node) {
500 // if none of yang-module-capabilities or non-module-capabilities is specified
501 // just return absent
502 if (node.getYangModuleCapabilities() == null && node.getNonModuleCapabilities() == null) {
503 return Optional.absent();
506 final List<String> capabilities = new ArrayList<>();
508 boolean overrideYangModuleCaps = false;
509 if (node.getYangModuleCapabilities() != null) {
510 capabilities.addAll(node.getYangModuleCapabilities().getCapability());
511 overrideYangModuleCaps = node.getYangModuleCapabilities().isOverride();
514 //non-module capabilities should not exist in yang module capabilities
515 final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(capabilities);
516 Preconditions.checkState(netconfSessionPreferences.getNonModuleCaps().isEmpty(),
517 "List yang-module-capabilities/capability should contain only module based capabilities. "
518 + "Non-module capabilities used: " + netconfSessionPreferences.getNonModuleCaps());
520 boolean overrideNonModuleCaps = false;
521 if (node.getNonModuleCapabilities() != null) {
522 capabilities.addAll(node.getNonModuleCapabilities().getCapability());
523 overrideNonModuleCaps = node.getNonModuleCapabilities().isOverride();
526 return Optional.of(new UserPreferences(NetconfSessionPreferences
527 .fromStrings(capabilities, CapabilityOrigin.UserDefined), overrideYangModuleCaps, overrideNonModuleCaps));
530 private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory {
531 private final Long connectionAttempts;
532 private final EventExecutor executor;
533 private final double sleepFactor;
534 private final int minSleep;
536 TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts,
537 final int minSleep, final BigDecimal sleepFactor) {
538 if (maxConnectionAttempts != null && maxConnectionAttempts > 0) {
539 connectionAttempts = maxConnectionAttempts;
541 connectionAttempts = null;
544 this.sleepFactor = sleepFactor.doubleValue();
545 this.executor = executor;
546 this.minSleep = minSleep;
550 public ReconnectStrategy createReconnectStrategy() {
551 final Long maxSleep = null;
552 final Long deadline = null;
554 return new TimedReconnectStrategy(executor, minSleep,
555 minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
559 protected static class NetconfConnectorDTO implements AutoCloseable {
561 private final NetconfDeviceCommunicator communicator;
562 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
564 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator,
565 final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
566 this.communicator = communicator;
567 this.facade = facade;
570 public NetconfDeviceCommunicator getCommunicator() {
574 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
578 public NetconfClientSessionListener getSessionListener() {
583 public void close() {
584 communicator.close();