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.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.ListeningExecutorService;
18 import com.google.common.util.concurrent.MoreExecutors;
19 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 java.util.Optional;
28 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
29 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
30 import org.opendaylight.controller.config.threadpool.ThreadPool;
31 import org.opendaylight.mdsal.binding.api.DataBroker;
32 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
33 import org.opendaylight.netconf.api.NetconfMessage;
34 import org.opendaylight.netconf.client.NetconfClientDispatcher;
35 import org.opendaylight.netconf.client.NetconfClientSessionListener;
36 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
37 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
38 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
39 import org.opendaylight.netconf.nettyutil.ReconnectStrategyFactory;
40 import org.opendaylight.netconf.nettyutil.TimedReconnectStrategyFactory;
41 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
42 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswordHandler;
43 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
44 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
45 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
46 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
47 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
48 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
49 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
50 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
51 import org.opendaylight.netconf.sal.connect.netconf.auth.DatastoreBackedPublicKeyAuth;
52 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
53 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
54 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
55 import org.opendaylight.netconf.sal.connect.netconf.listener.UserPreferences;
56 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
57 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfKeystoreAdapter;
58 import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYangSourceProvider;
59 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
60 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
61 import org.opendaylight.netconf.sal.connect.util.SslHandlerFactoryImpl;
62 import org.opendaylight.netconf.topology.api.NetconfTopology;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
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);
103 private final NetconfClientDispatcher clientDispatcher;
104 private final EventExecutor eventExecutor;
105 private final DeviceActionFactory deviceActionFactory;
106 private final NetconfKeystoreAdapter keystoreAdapter;
107 private final SchemaResourceManager schemaManager;
108 private final BaseNetconfSchemas baseSchemas;
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<>();
121 protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
122 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
123 final ThreadPool processingExecutor, final SchemaResourceManager schemaManager,
124 final DataBroker dataBroker, final DOMMountPointService mountPointService,
125 final AAAEncryptionService encryptionService,
126 final DeviceActionFactory deviceActionFactory,
127 final BaseNetconfSchemas baseSchemas) {
128 this.topologyId = topologyId;
129 this.clientDispatcher = clientDispatcher;
130 this.eventExecutor = eventExecutor;
131 this.keepaliveExecutor = keepaliveExecutor;
132 this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor.getExecutor());
133 this.schemaManager = requireNonNull(schemaManager);
134 this.deviceActionFactory = deviceActionFactory;
135 this.dataBroker = dataBroker;
136 this.mountPointService = mountPointService;
137 this.encryptionService = encryptionService;
138 this.baseSchemas = requireNonNull(baseSchemas);
140 this.keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
144 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
145 LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, hideCredentials(configNode));
146 return setupConnection(nodeId, configNode);
150 * Hiding of private credentials from node configuration (credentials data is replaced by asterisks).
152 * @param nodeConfiguration Node configuration container.
153 * @return String representation of node configuration with credentials replaced by asterisks.
156 public static String hideCredentials(final Node nodeConfiguration) {
157 final NetconfNode netconfNodeAugmentation = nodeConfiguration.augmentation(NetconfNode.class);
158 final String nodeCredentials = netconfNodeAugmentation.getCredentials().toString();
159 final String nodeConfigurationString = nodeConfiguration.toString();
160 return nodeConfigurationString.replace(nodeCredentials, "***");
164 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
165 LOG.debug("Disconnecting RemoteDevice{{}}", nodeId.getValue());
167 final NetconfConnectorDTO connectorDTO = activeConnectors.remove(nodeId);
168 if (connectorDTO == null) {
169 return Futures.immediateFailedFuture(
170 new IllegalStateException("Unable to disconnect device that is not connected"));
173 connectorDTO.close();
174 return Futures.immediateFuture(null);
177 protected ListenableFuture<NetconfDeviceCapabilities> setupConnection(final NodeId nodeId,
178 final Node configNode) {
179 final NetconfNode netconfNode = configNode.augmentation(NetconfNode.class);
180 final NetconfNodeAugmentedOptional nodeOptional = configNode.augmentation(NetconfNodeAugmentedOptional.class);
182 requireNonNull(netconfNode.getHost());
183 requireNonNull(netconfNode.getPort());
185 final NetconfConnectorDTO deviceCommunicatorDTO = createDeviceCommunicator(nodeId, netconfNode, nodeOptional);
186 final NetconfDeviceCommunicator deviceCommunicator = deviceCommunicatorDTO.getCommunicator();
187 final NetconfClientSessionListener netconfClientSessionListener = deviceCommunicatorDTO.getSessionListener();
188 final NetconfReconnectingClientConfiguration clientConfig =
189 getClientConfig(netconfClientSessionListener, netconfNode);
190 final ListenableFuture<NetconfDeviceCapabilities> future =
191 deviceCommunicator.initializeRemoteConnection(clientDispatcher, clientConfig);
193 activeConnectors.put(nodeId, deviceCommunicatorDTO);
195 Futures.addCallback(future, new FutureCallback<NetconfDeviceCapabilities>() {
197 public void onSuccess(final NetconfDeviceCapabilities result) {
198 LOG.debug("Connector for {} started succesfully", nodeId.getValue());
202 public void onFailure(final Throwable throwable) {
203 LOG.error("Connector for {} failed", nodeId.getValue(), throwable);
204 // remove this node from active connectors?
206 }, MoreExecutors.directExecutor());
211 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node) {
212 return createDeviceCommunicator(nodeId, node, null);
215 protected NetconfConnectorDTO createDeviceCommunicator(final NodeId nodeId, final NetconfNode node,
216 final NetconfNodeAugmentedOptional nodeOptional) {
217 //setup default values since default value is not supported in mdsal
218 final long defaultRequestTimeoutMillis = node.getDefaultRequestTimeoutMillis() == null
219 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis().toJava();
220 final long keepaliveDelay = node.getKeepaliveDelay() == null
221 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay().toJava();
223 final InetSocketAddress address;
224 final Host host = node.getHost();
225 final IpAddress ipAddress = host.getIpAddress();
226 if (ipAddress != null) {
227 address = new InetSocketAddress(IetfInetUtil.INSTANCE.inetAddressFor(ipAddress),
228 node.getPort().getValue().toJava());
230 address = new InetSocketAddress(host.getDomainName().getValue(),
231 node.getPort().getValue().toJava());
233 final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
235 RemoteDeviceHandler<NetconfSessionPreferences> salFacade = createSalFacade(remoteDeviceId);
237 if (keepaliveDelay > 0) {
238 LOG.warn("Adding keepalive facade, for device {}", nodeId);
239 salFacade = new KeepaliveSalFacade(remoteDeviceId, salFacade, this.keepaliveExecutor.getExecutor(),
240 keepaliveDelay, defaultRequestTimeoutMillis);
243 final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
244 final List<SchemaSourceRegistration<?>> yanglibRegistrations;
245 if (node.getSchemaless()) {
246 device = new SchemalessNetconfDevice(baseSchemas, remoteDeviceId, salFacade);
247 yanglibRegistrations = List.of();
249 final boolean reconnectOnChangedSchema = node.getReconnectOnChangedSchema() == null
250 ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.getReconnectOnChangedSchema();
252 final SchemaResourcesDTO resources = schemaManager.getSchemaResources(node, nodeId.getValue());
253 device = new NetconfDeviceBuilder()
254 .setReconnectOnSchemasChange(reconnectOnChangedSchema)
255 .setSchemaResourcesDTO(resources)
256 .setGlobalProcessingExecutor(this.processingExecutor)
257 .setId(remoteDeviceId)
258 .setSalFacade(salFacade)
260 .setEventExecutor(eventExecutor)
261 .setNodeOptional(nodeOptional)
262 .setDeviceActionFactory(deviceActionFactory)
263 .setBaseSchemas(baseSchemas)
265 yanglibRegistrations = registerDeviceSchemaSources(remoteDeviceId, nodeId, node, resources);
268 final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
269 final int rpcMessageLimit = node.getConcurrentRpcLimit() == null ? DEFAULT_CONCURRENT_RPC_LIMIT
270 : node.getConcurrentRpcLimit().toJava();
272 if (rpcMessageLimit < 1) {
273 LOG.info("Concurrent rpc limit is smaller than 1, no limit will be enforced for device {}", remoteDeviceId);
276 NetconfDeviceCommunicator netconfDeviceCommunicator =
277 userCapabilities.isPresent() ? new NetconfDeviceCommunicator(remoteDeviceId, device,
278 userCapabilities.get(), rpcMessageLimit)
279 : new NetconfDeviceCommunicator(remoteDeviceId, device, rpcMessageLimit);
281 if (salFacade instanceof KeepaliveSalFacade) {
282 ((KeepaliveSalFacade)salFacade).setListener(netconfDeviceCommunicator);
285 return new NetconfConnectorDTO(netconfDeviceCommunicator, salFacade, yanglibRegistrations);
288 private List<SchemaSourceRegistration<?>> registerDeviceSchemaSources(final RemoteDeviceId remoteDeviceId,
289 final NodeId nodeId, final NetconfNode node, final SchemaResourcesDTO resources) {
290 final YangLibrary yangLibrary = node.getYangLibrary();
291 if (yangLibrary != null) {
292 final Uri uri = yangLibrary.getYangLibraryUrl();
294 final List<SchemaSourceRegistration<?>> registrations = new ArrayList<>();
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 registrations.add(schemaRegistry.registerSchemaSource(new YangLibrarySchemaYangSourceProvider(
310 remoteDeviceId, schemas.getAvailableModels()),
311 PotentialSchemaSource.create(entry.getKey(), YangTextSchemaSource.class,
312 PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
314 return List.copyOf(registrations);
322 * Sets the private key path from location specified in configuration file using blueprint.
324 public void setPrivateKeyPath(final String privateKeyPath) {
325 this.privateKeyPath = privateKeyPath;
329 * Sets the private key passphrase from location specified in configuration file using blueprint.
331 public void setPrivateKeyPassphrase(final String privateKeyPassphrase) {
332 this.privateKeyPassphrase = privateKeyPassphrase;
335 public NetconfReconnectingClientConfiguration getClientConfig(final NetconfClientSessionListener listener,
336 final NetconfNode node) {
338 //setup default values since default value is not supported in mdsal
339 final long clientConnectionTimeoutMillis = node.getConnectionTimeoutMillis() == null
340 ? DEFAULT_CONNECTION_TIMEOUT_MILLIS : node.getConnectionTimeoutMillis().toJava();
341 final long maxConnectionAttempts = node.getMaxConnectionAttempts() == null
342 ? DEFAULT_MAX_CONNECTION_ATTEMPTS : node.getMaxConnectionAttempts().toJava();
343 final int betweenAttemptsTimeoutMillis = node.getBetweenAttemptsTimeoutMillis() == null
344 ? DEFAULT_BETWEEN_ATTEMPTS_TIMEOUT_MILLIS : node.getBetweenAttemptsTimeoutMillis().toJava();
345 final boolean useTcp = node.getTcpOnly() == null ? DEFAULT_IS_TCP_ONLY : node.getTcpOnly();
346 final BigDecimal sleepFactor = node.getSleepFactor() == null ? DEFAULT_SLEEP_FACTOR : node.getSleepFactor();
348 final InetSocketAddress socketAddress = getSocketAddress(node.getHost(), node.getPort().getValue().toJava());
350 final ReconnectStrategyFactory sf = new TimedReconnectStrategyFactory(eventExecutor,
351 maxConnectionAttempts, betweenAttemptsTimeoutMillis, sleepFactor);
353 final NetconfReconnectingClientConfigurationBuilder reconnectingClientConfigurationBuilder;
354 final Protocol protocol = node.getProtocol();
356 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
357 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TCP)
358 .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
359 } else if (protocol == null || protocol.getName() == Name.SSH) {
360 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
361 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH)
362 .withAuthHandler(getHandlerFromCredentials(node.getCredentials()));
363 } else if (protocol.getName() == Name.TLS) {
364 reconnectingClientConfigurationBuilder = NetconfReconnectingClientConfigurationBuilder.create()
365 .withSslHandlerFactory(new SslHandlerFactoryImpl(keystoreAdapter, protocol.getSpecification()))
366 .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.TLS);
368 throw new IllegalStateException("Unsupported protocol type: " + protocol.getName());
371 if (node.getOdlHelloMessageCapabilities() != null) {
372 reconnectingClientConfigurationBuilder
373 .withOdlHelloCapabilities(node.getOdlHelloMessageCapabilities().getCapability());
376 return reconnectingClientConfigurationBuilder
377 .withAddress(socketAddress)
378 .withConnectionTimeoutMillis(clientConnectionTimeoutMillis)
379 .withReconnectStrategy(sf.createReconnectStrategy())
380 .withConnectStrategyFactory(sf)
381 .withSessionListener(listener)
385 private AuthenticationHandler getHandlerFromCredentials(final Credentials credentials) {
386 if (credentials instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
387 .rev150114.netconf.node.credentials.credentials.LoginPassword) {
388 final org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
389 .rev150114.netconf.node.credentials.credentials.LoginPassword loginPassword
390 = (org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology
391 .rev150114.netconf.node.credentials.credentials.LoginPassword) credentials;
392 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
394 if (credentials instanceof LoginPwUnencrypted) {
395 final LoginPasswordUnencrypted loginPassword =
396 ((LoginPwUnencrypted) credentials).getLoginPasswordUnencrypted();
397 return new LoginPasswordHandler(loginPassword.getUsername(), loginPassword.getPassword());
399 if (credentials instanceof LoginPw) {
400 final LoginPassword loginPassword = ((LoginPw) credentials).getLoginPassword();
401 return new LoginPasswordHandler(loginPassword.getUsername(),
402 encryptionService.decrypt(loginPassword.getPassword()));
404 if (credentials instanceof KeyAuth) {
405 final KeyBased keyPair = ((KeyAuth) credentials).getKeyBased();
406 return new DatastoreBackedPublicKeyAuth(keyPair.getUsername(), keyPair.getKeyId(),
407 keystoreAdapter, encryptionService);
409 throw new IllegalStateException("Unsupported credential type: " + credentials.getClass());
412 protected abstract RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id);
414 private static InetSocketAddress getSocketAddress(final Host host, final int port) {
415 if (host.getDomainName() != null) {
416 return new InetSocketAddress(host.getDomainName().getValue(), port);
419 final IpAddress ipAddress = host.getIpAddress();
420 final String ip = ipAddress.getIpv4Address() != null ? ipAddress.getIpv4Address().getValue()
421 : ipAddress.getIpv6Address().getValue();
422 return new InetSocketAddress(ip, port);
425 private static Optional<UserPreferences> getUserCapabilities(final NetconfNode node) {
426 // if none of yang-module-capabilities or non-module-capabilities is specified
427 // just return absent
428 if (node.getYangModuleCapabilities() == null && node.getNonModuleCapabilities() == null) {
429 return Optional.empty();
432 final List<String> capabilities = new ArrayList<>();
434 boolean overrideYangModuleCaps = false;
435 if (node.getYangModuleCapabilities() != null) {
436 capabilities.addAll(node.getYangModuleCapabilities().getCapability());
437 overrideYangModuleCaps = node.getYangModuleCapabilities().getOverride();
440 //non-module capabilities should not exist in yang module capabilities
441 final NetconfSessionPreferences netconfSessionPreferences = NetconfSessionPreferences.fromStrings(capabilities);
442 Preconditions.checkState(netconfSessionPreferences.getNonModuleCaps().isEmpty(),
443 "List yang-module-capabilities/capability should contain only module based capabilities. "
444 + "Non-module capabilities used: " + netconfSessionPreferences.getNonModuleCaps());
446 boolean overrideNonModuleCaps = false;
447 if (node.getNonModuleCapabilities() != null) {
448 capabilities.addAll(node.getNonModuleCapabilities().getCapability());
449 overrideNonModuleCaps = node.getNonModuleCapabilities().getOverride();
452 return Optional.of(new UserPreferences(NetconfSessionPreferences
453 .fromStrings(capabilities, CapabilityOrigin.UserDefined), overrideYangModuleCaps, overrideNonModuleCaps));