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.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.AuthEncryptor;
54 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
55 import org.opendaylight.netconf.topology.api.NetconfTopology;
56 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
57 import org.opendaylight.protocol.framework.ReconnectStrategy;
58 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
59 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
67 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
68 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
69 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
70 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
71 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
72 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
73 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
74 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
75 import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
76 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
77 import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
81 public abstract class AbstractNetconfTopology implements NetconfTopology {
83 private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
85 protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
86 protected static final int DEFAULT_KEEPALIVE_DELAY = 0;
87 protected static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
88 protected static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
89 private static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
90 private static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
91 private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
92 private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
94 // constants related to Schema Cache(s)
96 * Filesystem based caches are stored relative to the cache directory.
98 private static final String CACHE_DIRECTORY = "cache";
101 * The default cache directory relative to <code>CACHE_DIRECTORY</code>
103 private static final String DEFAULT_CACHE_DIRECTORY = "schema";
106 * The qualified schema cache directory <code>cache/schema</code>
108 private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY = 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>schemaResourcesDTOs</code> should be surrounded by appropriate
140 * synchronization locks.
142 private static final Map<String, NetconfDevice.SchemaResourcesDTO> schemaResourcesDTOs = new HashMap<>();
144 // Initializes default constant instances for the case when the default schema repository
145 // directory cache/schema is used.
147 schemaResourcesDTOs.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;
165 protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY;
166 protected SchemaRepository schemaRepository = DEFAULT_SCHEMA_REPOSITORY;
167 protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY;
169 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
171 protected final AAAEncryptionService encryptionService;
173 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
174 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
175 final ThreadPool processingExecutor,
176 final SchemaRepositoryProvider schemaRepositoryProvider,
177 final DataBroker dataBroker, final DOMMountPointService mountPointService,
178 final AAAEncryptionService encryptionService) {
179 this.topologyId = topologyId;
180 this.clientDispatcher = clientDispatcher;
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;
187 this.encryptionService = encryptionService;
190 public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) {
191 this.schemaRegistry = schemaRegistry;
194 public void setSchemaContextFactory(final SchemaContextFactory schemaContextFactory) {
195 this.schemaContextFactory = schemaContextFactory;
199 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
200 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, configNode);
201 return setupConnection(nodeId, configNode);
205 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
206 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
207 if (!activeConnectors.containsKey(nodeId)) {
208 return Futures.immediateFailedFuture(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 AuthEncryptor.encryptIfNeeded(nodeId, netconfNode, encryptionService, topologyId, dataBroker);
224 Preconditions.checkNotNull(netconfNode.getHost());
225 Preconditions.checkNotNull(netconfNode.getPort());
226 Preconditions.checkNotNull(netconfNode.isTcpOnly());
228 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode);
229 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
230 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
231 final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(netconfClientSessionListener, netconfNode);
232 final ListenableFuture<NetconfDeviceCapabilities> future = 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 t) {
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 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
256 final Long keepaliveDelay = node.getKeepaliveDelay() == null ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
257 final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
259 final IpAddress ipAddress = node.getHost().getIpAddress();
260 final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null ?
261 ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
262 node.getPort().getValue());
263 final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
265 RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
266 createSalFacade(remoteDeviceId);
268 if (keepaliveDelay > 0) {
269 LOG.warn("Adding keepalive facade, for device {}", nodeId);
270 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay, defaultRequestTimeoutMillis);
273 // pre register yang library sources as fallback schemas to schema registry
274 final List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
275 if (node.getYangLibrary() != null) {
276 final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
277 final String yangLibUsername = node.getYangLibrary().getUsername();
278 final String yangLigPassword = node.getYangLibrary().getPassword();
280 final LibraryModulesSchemas libraryModulesSchemas;
281 if(yangLibURL != null) {
282 if(yangLibUsername != null && yangLigPassword != null) {
283 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
285 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
288 for (final Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry : libraryModulesSchemas.getAvailableModels().entrySet()) {
289 registeredYangLibSources.
290 add(schemaRegistry.registerSchemaSource(
291 new YangLibrarySchemaYangSourceProvider(remoteDeviceId, libraryModulesSchemas.getAvailableModels()),
292 PotentialSchemaSource
293 .create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
294 PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
299 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
300 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
301 if (node.isSchemaless()) {
302 device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
304 device = new NetconfDeviceBuilder()
305 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
306 .setSchemaResourcesDTO(schemaResourcesDTO)
307 .setGlobalProcessingExecutor(processingExecutor.getExecutor())
308 .setId(remoteDeviceId)
309 .setSalFacade(salFacade)
313 final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
314 final int rpcMessageLimit =
315 node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
317 if (rpcMessageLimit < 1) {
318 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
321 return new NetconfConnectorDTO(userCapabilities.isPresent()
322 ? new NetconfDeviceCommunicator(remoteDeviceId, device, userCapabilities.get(), rpcMessageLimit)
323 : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit), salFacade);
326 protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
327 // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
328 NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
329 final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
330 // Only checks to ensure the String is not empty or null; further checks related to directory accessibility and file permissions
331 // are handled during the FilesystemSchemaSourceCache initialization.
332 if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
333 // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry and
334 // SchemaContextFactory remain the default values.
335 if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
336 // Multiple modules may be created at once; synchronize to avoid issues with data consistency among threads.
337 synchronized(schemaResourcesDTOs) {
338 // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if they already exist
339 schemaResourcesDTO = schemaResourcesDTOs.get(moduleSchemaCacheDirectory);
340 if (schemaResourcesDTO == null) {
341 schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
342 schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
343 TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(), schemaResourcesDTO.getSchemaRegistry())
345 schemaResourcesDTOs.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
348 LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}",
349 nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
352 LOG.warn("schema-cache-directory for {} is null or empty; using the default {}",
353 nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY);
356 if (schemaResourcesDTO == null) {
357 schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaContextFactory,
358 new NetconfStateSchemasResolverImpl());
361 return schemaResourcesDTO;
365 * Creates the backing Schema classes for a particular directory.
367 * @param moduleSchemaCacheDirectory The string directory relative to "cache"
368 * @return A DTO containing the Schema classes for the Netconf mount.
370 private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
371 final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
372 final SchemaContextFactory schemaContextFactory
373 = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
374 setSchemaRegistry(repository);
375 setSchemaContextFactory(schemaContextFactory);
376 final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
377 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
378 repository.registerSchemaSourceListener(deviceCache);
379 return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
380 new NetconfStateSchemasResolverImpl());
384 * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
386 * @param schemaCacheDirectory The custom cache directory relative to "cache"
387 * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
389 private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(final String schemaCacheDirectory) {
390 final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
391 return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class, new File(relativeSchemaCacheDirectory));
394 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener, final NetconfNode node) {
396 //setup default values since default value is not supported in mdsal
397 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis();
398 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts();
399 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis();
400 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
402 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue());
404 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
405 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
406 final ReconnectStrategy strategy = sf.createReconnectStrategy();
408 final AuthenticationHandler authHandler;
409 final Credentials credentials = node.getCredentials();
410 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) {
411 authHandler = new LoginPassword(
412 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
413 .netconf.node.credentials.credentials.LoginPassword) credentials).getUsername(),
414 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114
415 .netconf.node.credentials.credentials.LoginPassword) credentials).getPassword(),
418 throw new IllegalStateException("Only login/password authentification is supported");
421 return NetconfReconnectingClientConfigurationBuilder.create()
422 .withAddress(socketAddress)
423 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
424 .withReconnectStrategy(strategy)
425 .withAuthHandler(authHandler)
426 .withProtocol(node.isTcpOnly() ?
427 NetconfClientConfiguration.NetconfClientProtocol.TCP :
428 NetconfClientConfiguration.NetconfClientProtocol.SSH)
429 .withConnectStrategyFactory(sf)
430 .withSessionListener(listener)
434 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id);
436 private InetSocketAddress getSocketAddress(final Host host, final int port) {
437 if(host.getDomainName() != null) {
438 return new InetSocketAddress(host.getDomainName().getValue(), port);
440 final IpAddress ipAddress = host.getIpAddress();
441 final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
442 return new InetSocketAddress(ip, port);
446 private Optional<UserPreferences> getUserCapabilities(final NetconfNode node) {
447 // if none of yang-module-capabilities or non-module-capabilities is specified
448 // just return absent
449 if (node.getYangModuleCapabilities() == null && node.getNonModuleCapabilities() == null) {
450 return Optional.absent();
453 final List<String> capabilities = new ArrayList<>();
455 boolean overrideYangModuleCaps = false;
456 if (node.getYangModuleCapabilities() != null) {
457 capabilities.addAll(node.getYangModuleCapabilities().getCapability());
458 overrideYangModuleCaps = node.getYangModuleCapabilities().isOverride();
461 //non-module capabilities should not exist in yang module capabilities
462 final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(capabilities);
463 Preconditions.checkState(netconfSessionPreferences.getNonModuleCaps().isEmpty(), "List yang-module-capabilities/capability " +
464 "should contain only module based capabilities. Non-module capabilities used: " +
465 netconfSessionPreferences.getNonModuleCaps());
467 boolean overrideNonModuleCaps = false;
468 if (node.getNonModuleCapabilities() != null) {
469 capabilities.addAll(node.getNonModuleCapabilities().getCapability());
470 overrideNonModuleCaps = node.getNonModuleCapabilities().isOverride();
473 return Optional.of(new UserPreferences(NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined),
474 overrideYangModuleCaps, overrideNonModuleCaps));
477 private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory {
478 private final Long connectionAttempts;
479 private final EventExecutor executor;
480 private final double sleepFactor;
481 private final int minSleep;
483 TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts, final int minSleep, final BigDecimal sleepFactor) {
484 if (maxConnectionAttempts != null && maxConnectionAttempts > 0) {
485 connectionAttempts = maxConnectionAttempts;
487 connectionAttempts = null;
490 this.sleepFactor = sleepFactor.doubleValue();
491 this.executor = executor;
492 this.minSleep = minSleep;
496 public ReconnectStrategy createReconnectStrategy() {
497 final Long maxSleep = null;
498 final Long deadline = null;
500 return new TimedReconnectStrategy(executor, minSleep,
501 minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
505 protected static class NetconfConnectorDTO implements AutoCloseable {
507 private final NetconfDeviceCommunicator communicator;
508 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
510 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator, final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
511 this.communicator = communicator;
512 this.facade = facade;
515 public NetconfDeviceCommunicator getCommunicator() {
519 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
523 public NetconfClientSessionListener getSessionListener() {
528 public void close() {
529 communicator.close();