2 * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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 java.net.InetSocketAddress;
11 import java.util.ArrayList;
12 import java.util.NoSuchElementException;
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.eclipse.jdt.annotation.Nullable;
15 import org.opendaylight.netconf.client.mdsal.UserPreferences;
16 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
17 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev231121.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNode;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.network.topology.topology.topology.types.TopologyNetconf;
22 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
27 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
35 * Utility methods to work with {@link NetconfNode} information.
37 public final class NetconfNodeUtils {
38 // FIXME: extract all of this to users, as they are in control of topology-id
39 @Deprecated(forRemoval = true)
40 public static final String DEFAULT_TOPOLOGY_NAME = TopologyNetconf.QNAME.getLocalName();
42 // FIXME: extract this into caller and pass to constructor
43 @Deprecated(forRemoval = true)
44 public static final KeyedInstanceIdentifier<Topology, TopologyKey> DEFAULT_TOPOLOGY_IID =
45 InstanceIdentifier.create(NetworkTopology.class)
46 .child(Topology.class, new TopologyKey(new TopologyId(DEFAULT_TOPOLOGY_NAME)));
48 private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "node-id").intern();
49 // FIXME: push this out to callers
50 private static final YangInstanceIdentifier DEFAULT_TOPOLOGY_NODE = YangInstanceIdentifier.builder()
51 .node(NetworkTopology.QNAME).node(Topology.QNAME)
52 .nodeWithKey(Topology.QNAME, QName.create(Topology.QNAME, "topology-id"), DEFAULT_TOPOLOGY_NAME)
56 private NetconfNodeUtils() {
61 * Create an {@link InetSocketAddress} targeting a particular {@link NetconfNode}.
63 * @param node A {@link NetconfNode}
64 * @return A {@link InetSocketAddress}
65 * @throws NullPointerException if {@code node} is {@code null}
66 * @throws NoSuchElementException if either host or port configuration is missing
68 public static @NonNull InetSocketAddress toInetSocketAddress(final NetconfNode node) {
69 final var host = node.requireHost();
70 final int port = node.requirePort().getValue().toJava();
71 final var ipAddress = host.getIpAddress();
72 return ipAddress != null ? new InetSocketAddress(IetfInetUtil.inetAddressFor(ipAddress), port)
73 : new InetSocketAddress(host.getDomainName().getValue(), port);
76 public static @NonNull RemoteDeviceId toRemoteDeviceId(final NodeId nodeId, final NetconfNode node) {
77 return new RemoteDeviceId(nodeId.getValue(), toInetSocketAddress(node));
81 * Extract {@link UserPreferences} from na {@link NetconfNode}.
83 * @param node A {@link NetconfNode}
84 * @return {@link UserPreferences}, potentially {@code null}
85 * @throws NullPointerException if {@code node} is {@code null}
86 * @throws IllegalArgumentException there are any non-module capabilities
88 public static @Nullable UserPreferences extractUserCapabilities(final NetconfNode node) {
89 final var moduleCaps = node.getYangModuleCapabilities();
90 final var nonModuleCaps = node.getNonModuleCapabilities();
92 if (moduleCaps == null && nonModuleCaps == null) {
93 // if none of yang-module-capabilities or non-module-capabilities is specified
97 final var capabilities = new ArrayList<String>();
98 final boolean overrideYangModuleCaps;
99 if (moduleCaps != null) {
100 capabilities.addAll(moduleCaps.getCapability());
101 overrideYangModuleCaps = moduleCaps.getOverride();
103 overrideYangModuleCaps = false;
106 //non-module capabilities should not exist in yang module capabilities
107 final var sessionPreferences = NetconfSessionPreferences.fromStrings(capabilities,
108 CapabilityOrigin.DeviceAdvertised, node.getSessionId());
109 final var nonModulePrefs = sessionPreferences.nonModuleCaps();
110 if (!nonModulePrefs.isEmpty()) {
111 throw new IllegalArgumentException("List yang-module-capabilities/capability should contain only module "
112 + "based capabilities. Non-module capabilities used: " + nonModulePrefs);
115 final boolean overrideNonModuleCaps;
116 if (nonModuleCaps != null) {
117 capabilities.addAll(nonModuleCaps.getCapability());
118 overrideNonModuleCaps = nonModuleCaps.getOverride();
120 overrideNonModuleCaps = false;
123 // FIXME: UserPreferences is constructor parameter of NetconfDeviceCommunicator and NetconfSessionPreferences
124 // are created in NetconfDeviceCommunicator#onSessionUp from session. What are we doing here?
125 // IMO we should rework UserPreferences and NetconfSessionPreferences and this method.
126 return new UserPreferences(NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined,
127 node.getSessionId()), overrideYangModuleCaps, overrideNonModuleCaps);
130 @Deprecated(forRemoval = true)
131 public static @NonNull YangInstanceIdentifier defaultTopologyMountPath(final RemoteDeviceId id) {
132 return DEFAULT_TOPOLOGY_NODE.node(NodeIdentifierWithPredicates.of(Node.QNAME, NODE_ID_QNAME, id.name()));