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
8 package org.opendaylight.netconf.topology.spi;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.base.Preconditions;
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.ListeningExecutorService;
19 import com.google.common.util.concurrent.MoreExecutors;
20 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 java.util.Optional;
29 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
30 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
31 import org.opendaylight.controller.config.threadpool.ThreadPool;
32 import org.opendaylight.mdsal.binding.api.DataBroker;
33 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
34 import org.opendaylight.netconf.api.NetconfMessage;
35 import org.opendaylight.netconf.client.NetconfClientDispatcher;
36 import org.opendaylight.netconf.client.NetconfClientSessionListener;
37 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
38 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
39 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
40 import org.opendaylight.netconf.nettyutil.ReconnectStrategyFactory;
41 import org.opendaylight.netconf.nettyutil.TimedReconnectStrategyFactory;
42 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
43 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswordHandler;
44 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
45 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
46 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
47 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
48 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
49 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
50 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
51 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
52 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
53 import org.opendaylight.netconf.sal.connect.netconf.auth.DatastoreBackedPublicKeyAuth;
54 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
55 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
56 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
57 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
58 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
59 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfKeystoreAdapter;
60 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
61 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
62 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
63 import org.opendaylight.netconf.sal.connect.util.SslHandlerFactoryImpl;
64 import org.opendaylight.netconf.topology.api.NetconfTopology;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
67 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev190614.NetconfNodeAugmentedOptional;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.KeyAuth;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPw;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPwUnencrypted;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.key.auth.KeyBased;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.LoginPassword;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencrypted;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.schema.storage.YangLibrary;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
83 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
84 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
85 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
86 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
87 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
88 import org.slf4j.Logger;
89 import org.slf4j.LoggerFactory;
91 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 boolean DEFAULT_IS_TCP_ONLY = false;
99 private static final int DEFAULT_MAX_CONNECTION_ATTEMPTS = 0;
100 private static final int DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS = 2000;
101 private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
102 private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
105 private final NetconfClientDispatcher clientDispatcher;
106 private final EventExecutor eventExecutor;
107 private final DeviceActionFactory deviceActionFactory;
108 private final NetconfKeystoreAdapter keystoreAdapter;
109 private final SchemaResourceManager schemaManager;
110 private final BaseNetconfSchemas baseSchemas;
112 protected final ScheduledThreadPool keepaliveExecutor;
113 protected final ListeningExecutorService processingExecutor;
114 protected final DataBroker dataBroker;
115 protected final DOMMountPointService mountPointService;
116 protected final String topologyId;
117 protected String privateKeyPath;
118 protected String privateKeyPassphrase;
119 protected final AAAEncryptionService encryptionService;
120 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
123 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
124 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
125 final ThreadPool processingExecutor, final SchemaResourceManager schemaManager,
126 final DataBroker dataBroker, final DOMMountPointService mountPointService,
127 final AAAEncryptionService encryptionService,
128 final DeviceActionFactory deviceActionFactory,
129 final BaseNetconfSchemas baseSchemas) {
130 this.topologyId = topologyId;
131 this.clientDispatcher = clientDispatcher;
132 this.eventExecutor = eventExecutor;
133 this.keepaliveExecutor = keepaliveExecutor;
134 this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor.getExecutor());
135 this.schemaManager = requireNonNull(schemaManager);
136 this.deviceActionFactory = deviceActionFactory;
137 this.dataBroker = dataBroker;
138 this.mountPointService = mountPointService;
139 this.encryptionService = encryptionService;
140 this.baseSchemas = requireNonNull(baseSchemas);
142 this.keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
146 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
147 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, hideCredentials(configNode));
148 return setupConnection(nodeId, configNode);
152 * Hiding of private credentials from node configuration (credentials data is replaced by asterisks).
154 * @param nodeConfiguration Node configuration container.
155 * @return String representation of node configuration with credentials replaced by asterisks.
158 public static String hideCredentials(final Node nodeConfiguration) {
159 final NetconfNode netconfNodeAugmentation = nodeConfiguration.augmentation(NetconfNode.class);
160 final String nodeCredentials = netconfNodeAugmentation.getCredentials().toString();
161 final String nodeConfigurationString = nodeConfiguration.toString();
162 return nodeConfigurationString.replace(nodeCredentials, "***");
166 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
167 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
168 if (!activeConnectors.containsKey(nodeId)) {
169 return Futures.immediateFailedFuture(
170 new IllegalStateException("Unable to disconnect device that is not connected"));
173 // retrieve connection, and disconnect it
174 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
175 connectorDTO.getCommunicator().close();
176 connectorDTO.getFacade().close();
177 return Futures.immediateFuture(null);
180 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
181 final Node configNode) {
182 final NetconfNode netconfNode = configNode.augmentation(NetconfNode.class);
183 final NetconfNodeAugmentedOptional nodeOptional = configNode.augmentation(NetconfNodeAugmentedOptional.class);
185 requireNonNull(netconfNode.getHost());
186 requireNonNull(netconfNode.getPort());
188 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode, nodeOptional);
189 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
190 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
191 final NetconfReconnectingClientConfiguration clientConfig =
192 getClientConfig(netconfClientSessionListener, netconfNode);
193 final ListenableFuture<NetconfDeviceCapabilities> future =
194 deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
196 activeConnectors.put(nodeId, deviceCommunicatorDTO);
198 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
200 public void onSuccess(final NetconfDeviceCapabilities result) {
201 LOG.debug("Connector for {} started succesfully", nodeId.getValue());
205 public void onFailure(final Throwable throwable) {
206 LOG.error("Connector for {} failed", nodeId.getValue(), throwable);
207 // remove this node from active connectors?
209 }, MoreExecutors.directExecutor());
214 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node) {
215 return createDeviceCommunicator(nodeId, node, null);
218 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node,
219 final NetconfNodeAugmentedOptional nodeOptional) {
220 //setup default values since default value is not supported in mdsal
221 final long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
222 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis().toJava();
223 final long keepaliveDelay = node.getKeepaliveDelay() == null
224 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay().toJava();
226 final IpAddress ipAddress = node.getHost().getIpAddress();
227 final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
228 ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
229 node.getPort().getValue().toJava());
230 final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
232 RemoteDeviceHandler<NetconfSessionPreferences> salFacade = createSalFacade(remoteDeviceId);
234 if (keepaliveDelay > 0) {
235 LOG.warn("Adding keepalive facade, for device {}", nodeId);
236 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, this.keepaliveExecutor.getExecutor(),
237 keepaliveDelay, defaultRequestTimeoutMillis);
240 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
241 if (node.isSchemaless()) {
242 device = new SchemalessNetconfDevice(baseSchemas, remoteDeviceId, salFacade);
244 device = createNetconfDevice(remoteDeviceId, salFacade, nodeId, node, nodeOptional);
247 final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
248 final int rpcMessageLimit = node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT
249 : node.getConcurrentRpcLimit().toJava();
251 if (rpcMessageLimit < 1) {
252 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
255 NetconfDeviceCommunicator netconfDeviceCommunicator =
256 userCapabilities.isPresent() ? new NetconfDeviceCommunicator(remoteDeviceId, device,
257 userCapabilities.get(), rpcMessageLimit)
258 : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit);
260 if (salFacade instanceof KeepaliveSalFacade) {
261 ((KeepaliveSalFacade)salFacade).setListener(netconfDeviceCommunicator);
263 return new NetconfConnectorDTO(netconfDeviceCommunicator, salFacade);
266 private NetconfDevice createNetconfDevice(final RemoteDeviceId remoteDeviceId,
267 final RemoteDeviceHandler<NetconfSessionPreferences> salFacade, final NodeId nodeId, final NetconfNode node,
268 final NetconfNodeAugmentedOptional nodeOptional) {
269 final boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
270 ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
272 final SchemaResourcesDTO resources = schemaManager.getSchemaResources(node, nodeId.getValue());
274 final NetconfDevice device = new NetconfDeviceBuilder()
275 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
276 .setSchemaResourcesDTO(resources)
277 .setGlobalProcessingExecutor(this.processingExecutor)
278 .setId(remoteDeviceId)
279 .setSalFacade(salFacade)
281 .setEventExecutor(eventExecutor)
282 .setNodeOptional(nodeOptional)
283 .setDeviceActionFactory(deviceActionFactory)
284 .setBaseSchemas(baseSchemas)
287 final YangLibrary yangLibrary = node.getYangLibrary();
288 if (yangLibrary != null) {
289 final Uri uri = yangLibrary.getYangLibraryUrl();
291 // FIXME: NETCONF-675: these registrations need to be torn down with the device. This does not look
292 // quite right, though, as we can end up adding a lot of registrations on a
294 // This leak is also detected by SpotBugs as soon as this initialization is switched
295 // to proper "new ArrayList<>" and hence we really need to attach these somewhere
297 // It seems we should be subclassing NetconfConnectorDTO for this purpose as a
298 // first step and then perhaps do some refcounting or similar based on the
299 // schemaRegistry instance.
300 final List<SchemaSourceRegistration<?>> registeredYangLibSources = Lists.newArrayList();
301 final String yangLibURL = uri.getValue();
302 final SchemaSourceRegistry schemaRegistry = resources.getSchemaRegistry();
304 // pre register yang library sources as fallback schemas to schema registry
305 final LibraryModulesSchemas schemas;
306 final String yangLibUsername = yangLibrary.getUsername();
307 final String yangLigPassword = yangLibrary.getPassword();
308 if (yangLibUsername != null && yangLigPassword != null) {
309 schemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
311 schemas = LibraryModulesSchemas.create(yangLibURL);
314 for (final Map.Entry<SourceIdentifier, URL> entry : schemas.getAvailableModels().entrySet()) {
315 registeredYangLibSources.add(schemaRegistry.registerSchemaSource(
316 new YangLibrarySchemaYangSourceProvider(remoteDeviceId, schemas.getAvailableModels()),
317 PotentialSchemaSource.create(entry.getKey(), YangTextSchemaSource.class,
318 PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
327 * Sets the private key path from location specified in configuration file using blueprint.
329 public void setPrivateKeyPath(final String privateKeyPath) {
330 this.privateKeyPath = privateKeyPath;
334 * Sets the private key passphrase from location specified in configuration file using blueprint.
336 public void setPrivateKeyPassphrase(final String privateKeyPassphrase) {
337 this.privateKeyPassphrase = privateKeyPassphrase;
340 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
341 final NetconfNode node) {
343 //setup default values since default value is not supported in mdsal
344 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
345 ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis().toJava();
346 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
347 ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts().toJava();
348 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
349 ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis().toJava();
350 final boolean useTcp = node.isTcpOnly() == null ? DEFAULT_IS_TCP_ONLY : node.isTcpOnly();
351 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
353 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue().toJava());
355 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
356 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
358 final NetconfReconnectingClientConfigurationBuilder reconnectingClientConfigurationBuilder;
359 final Protocol protocol = node.getProtocol();
361 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
362 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TCP)
363 .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
364 } else if (protocol == null || protocol.getName() == Name.SSH) {
365 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
366 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH)
367 .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
368 } else if (protocol.getName() == Name.TLS) {
369 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
370 .withSslHandlerFactory(new SslHandlerFactoryImpl(keystoreAdapter, protocol.getSpecification()))
371 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TLS);
373 throw new IllegalStateException("Unsupported protocol type: " + protocol.getName());
376 if (node.getOdlHelloMessageCapabilities() != null) {
377 reconnectingClientConfigurationBuilder
378 .withOdlHelloCapabilities(node.getOdlHelloMessageCapabilities().getCapability());
381 return reconnectingClientConfigurationBuilder
382 .withAddress(socketAddress)
383 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
384 .withReconnectStrategy(sf.createReconnectStrategy())
385 .withConnectStrategyFactory(sf)
386 .withSessionListener(listener)
390 private AuthenticationHandler getHandlerFromCredentials(final Credentials credentials) {
391 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
392 .rev150114.netconf.node.credentials.credentials.LoginPassword) {
393 final org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
394 .rev150114.netconf.node.credentials.credentials.LoginPassword loginPassword
395 = (org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
396 .rev150114.netconf.node.credentials.credentials.LoginPassword) credentials;
397 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
399 if (credentials instanceof LoginPwUnencrypted) {
400 final LoginPasswordUnencrypted loginPassword =
401 ((LoginPwUnencrypted) credentials).getLoginPasswordUnencrypted();
402 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
404 if (credentials instanceof LoginPw) {
405 final LoginPassword loginPassword = ((LoginPw) credentials).getLoginPassword();
406 return new LoginPasswordHandler(loginPassword.getUsername(),
407 encryptionService.decrypt(loginPassword.getPassword()));
409 if (credentials instanceof KeyAuth) {
410 final KeyBased keyPair = ((KeyAuth) credentials).getKeyBased();
411 return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(),
412 keystoreAdapter, encryptionService);
414 throw new IllegalStateException("Unsupported credential type: " + credentials.getClass());
417 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id);
419 private static InetSocketAddress getSocketAddress(final Host host, final int port) {
420 if (host.getDomainName() != null) {
421 return new InetSocketAddress(host.getDomainName().getValue(), port);
424 final IpAddress ipAddress = host.getIpAddress();
425 final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue()
426 : ipAddress.getIpv6Address().getValue();
427 return new InetSocketAddress(ip, port);
430 private static Optional<UserPreferences> getUserCapabilities(final NetconfNode node) {
431 // if none of yang-module-capabilities or non-module-capabilities is specified
432 // just return absent
433 if (node.getYangModuleCapabilities() == null && node.getNonModuleCapabilities() == null) {
434 return Optional.empty();
437 final List<String> capabilities = new ArrayList<>();
439 boolean overrideYangModuleCaps = false;
440 if (node.getYangModuleCapabilities() != null) {
441 capabilities.addAll(node.getYangModuleCapabilities().getCapability());
442 overrideYangModuleCaps = node.getYangModuleCapabilities().isOverride();
445 //non-module capabilities should not exist in yang module capabilities
446 final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(capabilities);
447 Preconditions.checkState(netconfSessionPreferences.getNonModuleCaps().isEmpty(),
448 "List yang-module-capabilities/capability should contain only module based capabilities. "
449 + "Non-module capabilities used: " + netconfSessionPreferences.getNonModuleCaps());
451 boolean overrideNonModuleCaps = false;
452 if (node.getNonModuleCapabilities() != null) {
453 capabilities.addAll(node.getNonModuleCapabilities().getCapability());
454 overrideNonModuleCaps = node.getNonModuleCapabilities().isOverride();
457 return Optional.of(new UserPreferences(NetconfSessionPreferences
458 .fromStrings(capabilities, CapabilityOrigin.UserDefined), overrideYangModuleCaps, overrideNonModuleCaps));
461 protected static class NetconfConnectorDTO implements AutoCloseable {
463 private final NetconfDeviceCommunicator communicator;
464 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
466 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator,
467 final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
468 this.communicator = communicator;
469 this.facade = facade;
472 public NetconfDeviceCommunicator getCommunicator() {
476 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
480 public NetconfClientSessionListener getSessionListener() {
485 public void close() {
486 communicator.close();