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.util.RemoteDeviceId;
62 import org.opendaylight.netconf.sal.connect.util.SslHandlerFactoryImpl;
63 import org.opendaylight.netconf.topology.api.NetconfTopology;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev190614.NetconfNodeAugmentedOptional;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.KeyAuth;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPw;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPwUnencrypted;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.key.auth.KeyBased;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.LoginPassword;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencrypted;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.schema.storage.YangLibrary;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
82 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
83 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
84 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
85 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
86 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
87 import org.slf4j.Logger;
88 import org.slf4j.LoggerFactory;
90 public abstract class AbstractNetconfTopology implements NetconfTopology {
91 private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
93 protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
94 protected static final int DEFAULT_KEEPALIVE_DELAY = 0;
95 protected static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
96 protected static final int DEFAULT_CONCURRENT_RPC_LIMIT = 0;
97 private static final boolean DEFAULT_IS_TCP_ONLY = false;
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);
104 private final NetconfClientDispatcher clientDispatcher;
105 private final EventExecutor eventExecutor;
106 private final DeviceActionFactory deviceActionFactory;
107 private final NetconfKeystoreAdapter keystoreAdapter;
108 private final SchemaResourceManager schemaManager;
110 protected final ScheduledThreadPool keepaliveExecutor;
111 protected final ListeningExecutorService processingExecutor;
112 protected final DataBroker dataBroker;
113 protected final DOMMountPointService mountPointService;
114 protected final String topologyId;
115 protected String privateKeyPath;
116 protected String privateKeyPassphrase;
117 protected final AAAEncryptionService encryptionService;
118 protected final HashMap<NodeId, NetconfConnectorDTO> activeConnectors = new HashMap<>();
120 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
121 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
122 final ThreadPool processingExecutor, final SchemaResourceManager schemaManager,
123 final DataBroker dataBroker, final DOMMountPointService mountPointService,
124 final AAAEncryptionService encryptionService,
125 final DeviceActionFactory deviceActionFactory) {
126 this.topologyId = topologyId;
127 this.clientDispatcher = clientDispatcher;
128 this.eventExecutor = eventExecutor;
129 this.keepaliveExecutor = keepaliveExecutor;
130 this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor.getExecutor());
131 this.schemaManager = requireNonNull(schemaManager);
132 this.deviceActionFactory = deviceActionFactory;
133 this.dataBroker = dataBroker;
134 this.mountPointService = mountPointService;
135 this.encryptionService = encryptionService;
137 this.keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
141 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
142 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, hideCredentials(configNode));
143 return setupConnection(nodeId, configNode);
147 * Hiding of private credentials from node configuration (credentials data is replaced by asterisks).
149 * @param nodeConfiguration Node configuration container.
150 * @return String representation of node configuration with credentials replaced by asterisks.
153 public static String hideCredentials(final Node nodeConfiguration) {
154 final NetconfNode netconfNodeAugmentation = nodeConfiguration.augmentation(NetconfNode.class);
155 final String nodeCredentials = netconfNodeAugmentation.getCredentials().toString();
156 final String nodeConfigurationString = nodeConfiguration.toString();
157 return nodeConfigurationString.replace(nodeCredentials, "***");
161 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
162 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
163 if (!activeConnectors.containsKey(nodeId)) {
164 return Futures.immediateFailedFuture(
165 new IllegalStateException("Unable to disconnect device that is not connected"));
168 // retrieve connection, and disconnect it
169 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
170 connectorDTO.getCommunicator().close();
171 connectorDTO.getFacade().close();
172 return Futures.immediateFuture(null);
175 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
176 final Node configNode) {
177 final NetconfNode netconfNode = configNode.augmentation(NetconfNode.class);
178 final NetconfNodeAugmentedOptional nodeOptional = configNode.augmentation(NetconfNodeAugmentedOptional.class);
180 requireNonNull(netconfNode.getHost());
181 requireNonNull(netconfNode.getPort());
183 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode, nodeOptional);
184 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
185 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
186 final NetconfReconnectingClientConfiguration clientConfig =
187 getClientConfig(netconfClientSessionListener, netconfNode);
188 final ListenableFuture<NetconfDeviceCapabilities> future =
189 deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
191 activeConnectors.put(nodeId, deviceCommunicatorDTO);
193 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
195 public void onSuccess(final NetconfDeviceCapabilities result) {
196 LOG.debug("Connector for {} started succesfully", nodeId.getValue());
200 public void onFailure(final Throwable throwable) {
201 LOG.error("Connector for {} failed", nodeId.getValue(), throwable);
202 // remove this node from active connectors?
204 }, MoreExecutors.directExecutor());
209 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node) {
210 return createDeviceCommunicator(nodeId, node, null);
213 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node,
214 final NetconfNodeAugmentedOptional nodeOptional) {
215 //setup default values since default value is not supported in mdsal
216 final long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
217 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis().toJava();
218 final long keepaliveDelay = node.getKeepaliveDelay() == null
219 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay().toJava();
221 final IpAddress ipAddress = node.getHost().getIpAddress();
222 final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
223 ? ipAddress.getIpv4Address().getValue() : ipAddress.getIpv6Address().getValue(),
224 node.getPort().getValue().toJava());
225 final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
227 RemoteDeviceHandler<NetconfSessionPreferences> salFacade = createSalFacade(remoteDeviceId);
229 if (keepaliveDelay > 0) {
230 LOG.warn("Adding keepalive facade, for device {}", nodeId);
231 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, this.keepaliveExecutor.getExecutor(),
232 keepaliveDelay, defaultRequestTimeoutMillis);
235 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
236 if (node.isSchemaless()) {
237 device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
239 device = createNetconfDevice(remoteDeviceId, salFacade, nodeId, node, nodeOptional);
242 final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
243 final int rpcMessageLimit = node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT
244 : node.getConcurrentRpcLimit().toJava();
246 if (rpcMessageLimit < 1) {
247 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
250 NetconfDeviceCommunicator netconfDeviceCommunicator =
251 userCapabilities.isPresent() ? new NetconfDeviceCommunicator(remoteDeviceId, device,
252 userCapabilities.get(), rpcMessageLimit)
253 : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit);
255 if (salFacade instanceof KeepaliveSalFacade) {
256 ((KeepaliveSalFacade)salFacade).setListener(netconfDeviceCommunicator);
258 return new NetconfConnectorDTO(netconfDeviceCommunicator, salFacade);
261 private NetconfDevice createNetconfDevice(final RemoteDeviceId remoteDeviceId,
262 final RemoteDeviceHandler<NetconfSessionPreferences> salFacade, final NodeId nodeId, final NetconfNode node,
263 final NetconfNodeAugmentedOptional nodeOptional) {
264 final boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
265 ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
267 final SchemaResourcesDTO resources = schemaManager.getSchemaResources(node, nodeId.getValue());
269 final NetconfDevice device = new NetconfDeviceBuilder()
270 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
271 .setSchemaResourcesDTO(resources)
272 .setGlobalProcessingExecutor(this.processingExecutor)
273 .setId(remoteDeviceId)
274 .setSalFacade(salFacade)
276 .setEventExecutor(eventExecutor)
277 .setNodeOptional(nodeOptional)
278 .setDeviceActionFactory(deviceActionFactory)
281 final YangLibrary yangLibrary = node.getYangLibrary();
282 if (yangLibrary != null) {
283 final Uri uri = yangLibrary.getYangLibraryUrl();
285 // FIXME: NETCONF-675: these registrations need to be torn down with the device. This does not look
286 // quite right, though, as we can end up adding a lot of registrations on a
288 // This leak is also detected by SpotBugs as soon as this initialization is switched
289 // to proper "new ArrayList<>" and hence we really need to attach these somewhere
291 // It seems we should be subclassing NetconfConnectorDTO for this purpose as a
292 // first step and then perhaps do some refcounting or similar based on the
293 // schemaRegistry instance.
294 final List<SchemaSourceRegistration<?>> registeredYangLibSources = Lists.newArrayList();
295 final String yangLibURL = uri.getValue();
296 final SchemaSourceRegistry schemaRegistry = resources.getSchemaRegistry();
298 // pre register yang library sources as fallback schemas to schema registry
299 final LibraryModulesSchemas schemas;
300 final String yangLibUsername = yangLibrary.getUsername();
301 final String yangLigPassword = yangLibrary.getPassword();
302 if (yangLibUsername != null && yangLigPassword != null) {
303 schemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
305 schemas = LibraryModulesSchemas.create(yangLibURL);
308 for (final Map.Entry<SourceIdentifier, URL> entry : schemas.getAvailableModels().entrySet()) {
309 registeredYangLibSources.add(schemaRegistry.registerSchemaSource(
310 new YangLibrarySchemaYangSourceProvider(remoteDeviceId, schemas.getAvailableModels()),
311 PotentialSchemaSource.create(entry.getKey(), YangTextSchemaSource.class,
312 PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
321 * Sets the private key path from location specified in configuration file using blueprint.
323 public void setPrivateKeyPath(final String privateKeyPath) {
324 this.privateKeyPath = privateKeyPath;
328 * Sets the private key passphrase from location specified in configuration file using blueprint.
330 public void setPrivateKeyPassphrase(final String privateKeyPassphrase) {
331 this.privateKeyPassphrase = privateKeyPassphrase;
334 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
335 final NetconfNode node) {
337 //setup default values since default value is not supported in mdsal
338 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
339 ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis().toJava();
340 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
341 ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts().toJava();
342 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
343 ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis().toJava();
344 final boolean useTcp = node.isTcpOnly() == null ? DEFAULT_IS_TCP_ONLY : node.isTcpOnly();
345 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
347 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue().toJava());
349 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
350 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
352 final NetconfReconnectingClientConfigurationBuilder reconnectingClientConfigurationBuilder;
353 final Protocol protocol = node.getProtocol();
355 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
356 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TCP)
357 .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
358 } else if (protocol == null || protocol.getName() == Name.SSH) {
359 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
360 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH)
361 .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
362 } else if (protocol.getName() == Name.TLS) {
363 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
364 .withSslHandlerFactory(new SslHandlerFactoryImpl(keystoreAdapter, protocol.getSpecification()))
365 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TLS);
367 throw new IllegalStateException("Unsupported protocol type: " + protocol.getName());
370 if (node.getOdlHelloMessageCapabilities() != null) {
371 reconnectingClientConfigurationBuilder
372 .withOdlHelloCapabilities(node.getOdlHelloMessageCapabilities().getCapability());
375 return reconnectingClientConfigurationBuilder
376 .withAddress(socketAddress)
377 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
378 .withReconnectStrategy(sf.createReconnectStrategy())
379 .withConnectStrategyFactory(sf)
380 .withSessionListener(listener)
384 private AuthenticationHandler getHandlerFromCredentials(final Credentials credentials) {
385 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
386 .rev150114.netconf.node.credentials.credentials.LoginPassword) {
387 final org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
388 .rev150114.netconf.node.credentials.credentials.LoginPassword loginPassword
389 = (org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
390 .rev150114.netconf.node.credentials.credentials.LoginPassword) credentials;
391 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
393 if (credentials instanceof LoginPwUnencrypted) {
394 final LoginPasswordUnencrypted loginPassword =
395 ((LoginPwUnencrypted) credentials).getLoginPasswordUnencrypted();
396 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
398 if (credentials instanceof LoginPw) {
399 final LoginPassword loginPassword = ((LoginPw) credentials).getLoginPassword();
400 return new LoginPasswordHandler(loginPassword.getUsername(),
401 encryptionService.decrypt(loginPassword.getPassword()));
403 if (credentials instanceof KeyAuth) {
404 final KeyBased keyPair = ((KeyAuth) credentials).getKeyBased();
405 return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(),
406 keystoreAdapter, encryptionService);
408 throw new IllegalStateException("Unsupported credential type: " + credentials.getClass());
411 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id);
413 private static InetSocketAddress getSocketAddress(final Host host, final int port) {
414 if (host.getDomainName() != null) {
415 return new InetSocketAddress(host.getDomainName().getValue(), port);
418 final IpAddress ipAddress = host.getIpAddress();
419 final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue()
420 : ipAddress.getIpv6Address().getValue();
421 return new InetSocketAddress(ip, port);
424 private static Optional<UserPreferences> getUserCapabilities(final NetconfNode node) {
425 // if none of yang-module-capabilities or non-module-capabilities is specified
426 // just return absent
427 if (node.getYangModuleCapabilities() == null && node.getNonModuleCapabilities() == null) {
428 return Optional.empty();
431 final List<String> capabilities = new ArrayList<>();
433 boolean overrideYangModuleCaps = false;
434 if (node.getYangModuleCapabilities() != null) {
435 capabilities.addAll(node.getYangModuleCapabilities().getCapability());
436 overrideYangModuleCaps = node.getYangModuleCapabilities().isOverride();
439 //non-module capabilities should not exist in yang module capabilities
440 final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(capabilities);
441 Preconditions.checkState(netconfSessionPreferences.getNonModuleCaps().isEmpty(),
442 "List yang-module-capabilities/capability should contain only module based capabilities. "
443 + "Non-module capabilities used: " + netconfSessionPreferences.getNonModuleCaps());
445 boolean overrideNonModuleCaps = false;
446 if (node.getNonModuleCapabilities() != null) {
447 capabilities.addAll(node.getNonModuleCapabilities().getCapability());
448 overrideNonModuleCaps = node.getNonModuleCapabilities().isOverride();
451 return Optional.of(new UserPreferences(NetconfSessionPreferences
452 .fromStrings(capabilities, CapabilityOrigin.UserDefined), overrideYangModuleCaps, overrideNonModuleCaps));
455 protected static class NetconfConnectorDTO implements AutoCloseable {
457 private final NetconfDeviceCommunicator communicator;
458 private final RemoteDeviceHandler<NetconfSessionPreferences> facade;
460 public NetconfConnectorDTO(final NetconfDeviceCommunicator communicator,
461 final RemoteDeviceHandler<NetconfSessionPreferences> facade) {
462 this.communicator = communicator;
463 this.facade = facade;
466 public NetconfDeviceCommunicator getCommunicator() {
470 public RemoteDeviceHandler<NetconfSessionPreferences> getFacade() {
474 public NetconfClientSessionListener getSessionListener() {
479 public void close() {
480 communicator.close();