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.sal.binding.api.BindingAwareBroker;
30 import org.opendaylight.controller.sal.core.api.Broker;
31 import org.opendaylight.netconf.api.NetconfMessage;
32 import org.opendaylight.netconf.client.NetconfClientDispatcher;
33 import org.opendaylight.netconf.client.NetconfClientSessionListener;
34 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
35 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
36 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
37 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
38 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
39 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
40 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
41 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
42 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
43 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
44 import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
45 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
46 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
47 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
48 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
49 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
50 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
51 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
52 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
53 import org.opendaylight.netconf.topology.api.NetconfTopology;
54 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
55 import org.opendaylight.protocol.framework.ReconnectStrategy;
56 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
57 import org.opendaylight.protocol.framework.TimedReconnectStrategy;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
65 import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
66 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
67 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
68 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
69 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
70 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
71 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
72 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
73 import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
74 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
75 import org.opendaylight.yangtools.yang.parser.util.TextToASTTransformer;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
79 public abstract class AbstractNetconfTopology implements NetconfTopology {
81 private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
83 protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
84 protected static final int DEFAULT_KEEPALIVE_DELAY = 0;
85 protected static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
86 protected static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
87 private static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
88 private static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
89 private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
90 private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
92 // constants related to Schema Cache(s)
94 * Filesystem based caches are stored relative to the cache directory.
96 private static final String CACHE_DIRECTORY = "cache";
99 * The default cache directory relative to <code>CACHE_DIRECTORY</code>
101 private static final String DEFAULT_CACHE_DIRECTORY = "schema";
104 * The qualified schema cache directory <code>cache/schema</code>
106 private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY = CACHE_DIRECTORY + File.separator+ DEFAULT_CACHE_DIRECTORY;
109 * The name for the default schema repository
111 private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
114 * The default schema repository in the case that one is not specified.
116 private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
117 new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
120 * The default <code>FilesystemSchemaSourceCache</code>, which stores cached files in <code>cache/schema</code>.
122 private static final FilesystemSchemaSourceCache<YangTextSchemaSource> DEFAULT_CACHE =
123 new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
124 new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
127 * The default factory for creating <code>SchemaContext</code> instances.
129 private static final SchemaContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
130 DEFAULT_SCHEMA_REPOSITORY.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
133 * Keeps track of initialized Schema resources. A Map is maintained in which the key represents the name
134 * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>. The
135 * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
136 * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
137 * Netconf mount. Access to <code>schemaResourcesDTOs</code> should be surrounded by appropriate
138 * synchronization locks.
140 private static volatile Map<String, NetconfDevice.SchemaResourcesDTO> schemaResourcesDTOs = new HashMap<>();
142 // Initializes default constant instances for the case when the default schema repository
143 // directory cache/schema is used.
145 schemaResourcesDTOs.put(DEFAULT_CACHE_DIRECTORY,
146 new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY,
147 DEFAULT_SCHEMA_CONTEXT_FACTORY,
148 new NetconfStateSchemasResolverImpl()));
149 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_CACHE);
150 DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
151 TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
154 protected final String topologyId;
155 private final NetconfClientDispatcher clientDispatcher;
156 protected final BindingAwareBroker bindingAwareBroker;
157 protected final Broker domBroker;
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;
164 protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY;
165 protected SchemaRepository schemaRepository = DEFAULT_SCHEMA_REPOSITORY;
166 protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY;
168 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
170 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
171 final BindingAwareBroker bindingAwareBroker, final Broker domBroker,
172 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
173 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
174 final DataBroker dataBroker) {
175 this.topologyId = topologyId;
176 this.clientDispatcher = clientDispatcher;
177 this.bindingAwareBroker = bindingAwareBroker;
178 this.domBroker = domBroker;
179 this.eventExecutor = eventExecutor;
180 this.keepaliveExecutor = keepaliveExecutor;
181 this.processingExecutor = processingExecutor;
182 this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository();
183 this.dataBroker = dataBroker;
186 public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) {
187 this.schemaRegistry = schemaRegistry;
190 public void setSchemaContextFactory(final SchemaContextFactory schemaContextFactory) {
191 this.schemaContextFactory = schemaContextFactory;
195 public ListenableFuture<NetconfDeviceCapabilities> connectNode(NodeId nodeId, Node configNode) {
196 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, configNode);
197 return setupConnection(nodeId, configNode);
201 public ListenableFuture<Void> disconnectNode(NodeId nodeId) {
202 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
203 if (!activeConnectors.containsKey(nodeId)) {
204 return Futures.immediateFailedFuture(new IllegalStateException("Unable to disconnect device that is not connected"));
207 // retrieve connection, and disconnect it
208 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
209 connectorDTO.getCommunicator().close();
210 connectorDTO.getFacade().close();
211 return Futures.immediateFuture(null);
214 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
215 final Node configNode) {
216 final NetconfNode netconfNode = configNode.getAugmentation(NetconfNode.class);
218 Preconditions.checkNotNull(netconfNode.getHost());
219 Preconditions.checkNotNull(netconfNode.getPort());
220 Preconditions.checkNotNull(netconfNode.isTcpOnly());
222 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode);
223 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
224 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
225 final NetconfReconnectingClientConfiguration clientConfig = getClientConfig(netconfClientSessionListener, netconfNode);
226 final ListenableFuture<NetconfDeviceCapabilities> future = deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
228 activeConnectors.put(nodeId, deviceCommunicatorDTO);
230 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
232 public void onSuccess(NetconfDeviceCapabilities result) {
233 LOG.debug("Connector for : " + nodeId.getValue() + " started succesfully");
237 public void onFailure(Throwable t) {
238 LOG.error("Connector for : " + nodeId.getValue() + " failed");
239 // remove this node from active connectors?
246 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId,
247 final NetconfNode node) {
248 //setup default values since default value is not supported in mdsal
249 final Long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis();
250 final Long keepaliveDelay = node.getKeepaliveDelay() == null ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay();
251 final Boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
253 IpAddress ipAddress = node.getHost().getIpAddress();
254 InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null ?
255 ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
256 node.getPort().getValue());
257 RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
259 RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
260 createSalFacade(remoteDeviceId, domBroker, bindingAwareBroker);
262 if (keepaliveDelay > 0) {
263 LOG.warn("Adding keepalive facade, for device {}", nodeId);
264 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, keepaliveExecutor.getExecutor(), keepaliveDelay, defaultRequestTimeoutMillis);
267 // pre register yang library sources as fallback schemas to schema registry
268 List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
269 if (node.getYangLibrary() != null) {
270 final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
271 final String yangLibUsername = node.getYangLibrary().getUsername();
272 final String yangLigPassword = node.getYangLibrary().getPassword();
274 LibraryModulesSchemas libraryModulesSchemas;
275 if(yangLibURL != null) {
276 if(yangLibUsername != null && yangLigPassword != null) {
277 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
279 libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
282 for (Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry : libraryModulesSchemas.getAvailableModels().entrySet()) {
283 registeredYangLibSources.
284 add(schemaRegistry.registerSchemaSource(
285 new YangLibrarySchemaYangSourceProvider(remoteDeviceId, libraryModulesSchemas.getAvailableModels()),
286 PotentialSchemaSource
287 .create(sourceIdentifierURLEntry.getKey(), YangTextSchemaSource.class,
288 PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
293 final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
294 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
295 if (node.isSchemaless()) {
296 device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
298 device = new NetconfDeviceBuilder()
299 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
300 .setSchemaResourcesDTO(schemaResourcesDTO)
301 .setGlobalProcessingExecutor(processingExecutor.getExecutor())
302 .setId(remoteDeviceId)
303 .setSalFacade(salFacade)
307 final Optional<NetconfSessionPreferences> userCapabilities = getUserCapabilities(node);
308 final int rpcMessageLimit =
309 node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT : node.getConcurrentRpcLimit();
311 if (rpcMessageLimit < 1) {
312 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
315 return new NetconfConnectorDTO(
316 userCapabilities.isPresent() ?
317 new NetconfDeviceCommunicator(
318 remoteDeviceId, device, new UserPreferences(userCapabilities.get(), node.getYangModuleCapabilities().isOverride()), rpcMessageLimit):
319 new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit), salFacade);
322 protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
323 // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
324 NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
325 final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
326 // Only checks to ensure the String is not empty or null; further checks related to directory accessibility and file permissions
327 // are handled during the FilesystemSchemaSourceCache initialization.
328 if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
329 // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry and
330 // SchemaContextFactory remain the default values.
331 if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
332 // Multiple modules may be created at once; synchronize to avoid issues with data consistency among threads.
333 synchronized(schemaResourcesDTOs) {
334 // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if they already exist
335 schemaResourcesDTO = schemaResourcesDTOs.get(moduleSchemaCacheDirectory);
336 if (schemaResourcesDTO == null) {
337 schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
338 schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
339 TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(), schemaResourcesDTO.getSchemaRegistry())
341 schemaResourcesDTOs.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
344 LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}",
345 nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
348 LOG.warn("schema-cache-directory for {} is null or empty; using the default {}",
349 nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY);
352 if (schemaResourcesDTO == null) {
353 schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository, schemaContextFactory,
354 new NetconfStateSchemasResolverImpl());
357 return schemaResourcesDTO;
361 * Creates the backing Schema classes for a particular directory.
363 * @param moduleSchemaCacheDirectory The string directory relative to "cache"
364 * @return A DTO containing the Schema classes for the Netconf mount.
366 private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
367 final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
368 final SchemaContextFactory schemaContextFactory
369 = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT);
370 setSchemaRegistry(repository);
371 setSchemaContextFactory(schemaContextFactory);
372 final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
373 createDeviceFilesystemCache(moduleSchemaCacheDirectory);
374 repository.registerSchemaSourceListener(deviceCache);
375 return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
376 new NetconfStateSchemasResolverImpl());
380 * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
382 * @param schemaCacheDirectory The custom cache directory relative to "cache"
383 * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
385 private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(final String schemaCacheDirectory) {
386 final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
387 return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class, new File(relativeSchemaCacheDirectory));
390 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener, NetconfNode node) {
392 //setup default values since default value is not supported in mdsal
393 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis();
394 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts();
395 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis();
396 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
398 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue());
400 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
401 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
402 final ReconnectStrategy strategy = sf.createReconnectStrategy();
404 final AuthenticationHandler authHandler;
405 final Credentials credentials = node.getCredentials();
406 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) {
407 authHandler = new LoginPassword(
408 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) credentials).getUsername(),
409 ((org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPassword) credentials).getPassword());
411 throw new IllegalStateException("Only login/password authentification is supported");
414 return NetconfReconnectingClientConfigurationBuilder.create()
415 .withAddress(socketAddress)
416 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
417 .withReconnectStrategy(strategy)
418 .withAuthHandler(authHandler)
419 .withProtocol(node.isTcpOnly() ?
420 NetconfClientConfiguration.NetconfClientProtocol.TCP :
421 NetconfClientConfiguration.NetconfClientProtocol.SSH)
422 .withConnectStrategyFactory(sf)
423 .withSessionListener(listener)
427 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id, final Broker domBroker, final BindingAwareBroker bindingBroker);
429 private InetSocketAddress getSocketAddress(final Host host, int port) {
430 if(host.getDomainName() != null) {
431 return new InetSocketAddress(host.getDomainName().getValue(), port);
433 final IpAddress ipAddress = host.getIpAddress();
434 final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue();
435 return new InetSocketAddress(ip, port);
439 private Optional<NetconfSessionPreferences> getUserCapabilities(final NetconfNode node) {
440 if(node.getYangModuleCapabilities() == null) {
441 return Optional.absent();
444 final List<String> capabilities = node.getYangModuleCapabilities().getCapability();
445 if(capabilities == null || capabilities.isEmpty()) {
446 return Optional.absent();
449 final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined);
450 Preconditions.checkState(parsedOverrideCapabilities.getNonModuleCaps().isEmpty(), "Capabilities to override can " +
451 "only contain module based capabilities, non-module capabilities will be retrieved from the device," +
452 " configured non-module capabilities: " + parsedOverrideCapabilities.getNonModuleCaps());
454 return Optional.of(parsedOverrideCapabilities);
457 private static final class TimedReconnectStrategyFactory implements ReconnectStrategyFactory {
458 private final Long connectionAttempts;
459 private final EventExecutor executor;
460 private final double sleepFactor;
461 private final int minSleep;
463 TimedReconnectStrategyFactory(final EventExecutor executor, final Long maxConnectionAttempts, final int minSleep, final BigDecimal sleepFactor) {
464 if (maxConnectionAttempts != null && maxConnectionAttempts > 0) {
465 connectionAttempts = maxConnectionAttempts;
467 connectionAttempts = null;
470 this.sleepFactor = sleepFactor.doubleValue();
471 this.executor = executor;
472 this.minSleep = minSleep;
476 public ReconnectStrategy createReconnectStrategy() {
477 final Long maxSleep = null;
478 final Long deadline = null;
480 return new TimedReconnectStrategy(executor, minSleep,
481 minSleep, sleepFactor, maxSleep, connectionAttempts, deadline);
485 protected static class NetconfConnectorDTO implements AutoCloseable {
487 private final NetconfDeviceCommunicator communicator;
488 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
490 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator, final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
491 this.communicator = communicator;
492 this.facade = facade;
495 public NetconfDeviceCommunicator getCommunicator() {
499 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
503 public NetconfClientSessionListener getSessionListener() {
508 public void close() {
509 communicator.close();