import org.opendaylight.controller.messagebus.spi.EventSourceRegistration;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
if (netconfNode.getAvailableCapabilities() == null) {
return false;
}
- final List<String> capabilities = netconfNode.getAvailableCapabilities().getAvailableCapability();
+ final List<AvailableCapability> capabilities = netconfNode.getAvailableCapabilities().getAvailableCapability();
if (capabilities == null || capabilities.isEmpty()) {
return false;
}
- for (final String capability : netconfNode.getAvailableCapabilities().getAvailableCapability()) {
- if (capability.startsWith(NotificationCapabilityPrefix)) {
+ for (final AvailableCapability capability : netconfNode.getAvailableCapabilities().getAvailableCapability()) {
+ if (capability.getCapability().startsWith(NotificationCapabilityPrefix)) {
return true;
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
DomainName dn = new DomainName(hostName);
Host host = new Host(dn);
- List<String> avCapList = new ArrayList<>();
- avCapList.add(notificationCapabilityPrefix + "_availableCapabilityString1");
+ List<AvailableCapability> avCapList = new ArrayList<>();
+ avCapList.add(new AvailableCapabilityBuilder().setCapability(notificationCapabilityPrefix + "_availableCapabilityString1").build());
AvailableCapabilities avCaps = new AvailableCapabilitiesBuilder().setAvailableCapability(avCapList).build();
NetconfNode nn = new NetconfNodeBuilder().setConnectionStatus(cs).setHost(host).setAvailableCapabilities(avCaps)
.build();
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.stream.Collectors;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.MountPoint;
import org.opendaylight.controller.md.sal.binding.api.MountPointService;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.ModuleType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.Modules;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.ModuleKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.connector.netconf.rev150803.SalNetconfConnector;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
attributes.put(NetconfConsoleConstants.NETCONF_IP, ImmutableList.of(netconfNode.getHost().getIpAddress().getIpv4Address().getValue()));
attributes.put(NetconfConsoleConstants.NETCONF_PORT, ImmutableList.of(netconfNode.getPort().getValue().toString()));
attributes.put(NetconfConsoleConstants.STATUS, ImmutableList.of(netconfNode.getConnectionStatus().name()));
- attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, netconfNode.getAvailableCapabilities().getAvailableCapability());
+ attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
+ netconfNode.getAvailableCapabilities().getAvailableCapability().stream().map(AvailableCapability::getCapability).collect(Collectors.toList()));
device.put(node.getNodeId().getValue(), attributes);
}
}
attributes.put(NetconfConsoleConstants.NETCONF_IP, ImmutableList.of(netconfNode.getHost().getIpAddress().getIpv4Address().getValue()));
attributes.put(NetconfConsoleConstants.NETCONF_PORT, ImmutableList.of(netconfNode.getPort().getValue().toString()));
attributes.put(NetconfConsoleConstants.STATUS, ImmutableList.of(netconfNode.getConnectionStatus().name()));
- attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, netconfNode.getAvailableCapabilities().getAvailableCapability());
+ attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
+ netconfNode.getAvailableCapabilities().getAvailableCapability().stream().map(AvailableCapability::getCapability).collect(Collectors.toList()));
device.put(node.getNodeId().getValue(), attributes);
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
final Host host = HostBuilder.getDefaultInstance(ip);
final PortNumber port = new PortNumber(portNumber);
- final List<String> avCapList = new ArrayList<>();
- avCapList.add(notificationCapabilityPrefix + "_availableCapabilityString1");
+ final List<AvailableCapability> avCapList = new ArrayList<>();
+ avCapList.add(new AvailableCapabilityBuilder()
+ .setCapabilityOrigin(AvailableCapability.CapabilityOrigin.UserDefined)
+ .setCapability(notificationCapabilityPrefix + "_availableCapabilityString1").build());
final AvailableCapabilities avCaps = new AvailableCapabilitiesBuilder().setAvailableCapability(avCapList).build();
final NetconfNode nn = new NetconfNodeBuilder().setConnectionStatus(cs).setHost(host).setPort(port).
private List<InputStream> getYangSchemas() {
final List<String> schemaPaths = Arrays.asList("/schemas/network-topology@2013-10-21.yang",
- "/schemas/ietf-inet-types@2013-07-15.yang", "/schemas/yang-ext.yang", "/schemas/netconf-node-topology.yang");
+ "/schemas/ietf-inet-types@2013-07-15.yang", "/schemas/yang-ext.yang",
+ "/schemas/netconf-node-topology.yang");
+
final List<InputStream> schemas = new ArrayList<>();
for (String schemaPath : schemaPaths) {
final InputStream resourceAsStream = getClass().getResourceAsStream(schemaPath);
container available-capabilities {
config false;
- leaf-list available-capability {
- type string;
+ list available-capability {
+ leaf capability {
+ type string;
+ }
+ leaf capability-origin {
+ type enumeration {
+ enum user-defined;
+ enum device-advertised;
+ }
+ }
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.notifications;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class NetconfNotificationTest {
+
+ @Test
+ public void testWrapNotification() throws Exception {
+ final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ final DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+
+ final Document document = docBuilder.newDocument();
+
+ final Element rootElement = document.createElement("test-root");
+ document.appendChild(rootElement);
+
+ final Date eventTime = new Date();
+ eventTime.setTime(10000000);
+
+ final NetconfNotification netconfNotification = new NetconfNotification(document, eventTime);
+ final Document resultDoc = netconfNotification.getDocument();
+ final NodeList nodeList = resultDoc.getElementsByTagNameNS(NetconfNotification.NOTIFICATION_NAMESPACE,
+ NetconfNotification.NOTIFICATION);
+
+ assertNotNull(nodeList);
+ // expected only the one NOTIFICATION tag
+ assertEquals(1, nodeList.getLength());
+
+ final Element entireNotification = (Element) nodeList.item(0);
+ final NodeList childNodes = entireNotification.getElementsByTagNameNS(
+ NetconfNotification.NOTIFICATION_NAMESPACE, NetconfNotification.EVENT_TIME);
+
+ assertNotNull(childNodes);
+ // expected only the one EVENT_TIME tag
+ assertEquals(1, childNodes.getLength());
+
+ final Element eventTimeElement = (Element) childNodes.item(0);
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ assertEquals(eventTime.getTime(), sdf.parse(eventTimeElement.getTextContent()).getTime());
+
+ assertEquals(eventTime, netconfNotification.getEventTime());
+
+ }
+}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
return Optional.absent();
}
- final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities);
+ final NetconfSessionPreferences parsedOverrideCapabilities = NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined);
Preconditions.checkState(parsedOverrideCapabilities.getNonModuleCaps().isEmpty(), "Capabilities to override can " +
"only contain module based capabilities, non-module capabilities will be retrieved from the device," +
" configured non-module capabilities: " + parsedOverrideCapabilities.getNonModuleCaps());
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus.Status;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
.setFailureReason(input.getValue()).build();
}
};
- public static final Function<QName, String> AVAILABLE_CAPABILITY_TRANSFORMER = new Function<QName, String>() {
- @Override
- public String apply(QName qName) {
- // intern string representation of a capability to avoid duplicates
- return qName.toString().intern();
- }
- };
private static final String UNKNOWN_REASON = "Unknown reason";
.setHost(netconfNode.getHost())
.setPort(netconfNode.getPort())
.setConnectionStatus(ConnectionStatus.Connecting)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.setHost(netconfNode.getHost())
.setPort(netconfNode.getPort())
.setConnectionStatus(ConnectionStatus.UnableToConnect)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.build())
.setHost(netconfNode.getHost())
.setPort(netconfNode.getPort())
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.build()).build();
return currentOperationalNode;
.build())
.setHost(netconfNode.getHost())
.setPort(netconfNode.getPort())
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.build())
.build();
topologyDispatcher.registerMountPoint(cachedContext, new NodeId(nodeId), masterDataBrokerRef);
}
- List<String> capabilityList = new ArrayList<>();
+ List<AvailableCapability> capabilityList = new ArrayList<>();
capabilityList.addAll(netconfSessionPreferences.getNetconfDeviceCapabilities().getNonModuleBasedCapabilities());
- capabilityList.addAll(FluentIterable.from(netconfSessionPreferences.getNetconfDeviceCapabilities().getResolvedCapabilities()).transform(AVAILABLE_CAPABILITY_TRANSFORMER).toList());
+ capabilityList.addAll(netconfSessionPreferences.getNetconfDeviceCapabilities().getResolvedCapabilities());
final AvailableCapabilitiesBuilder avCapabalitiesBuilder = new AvailableCapabilitiesBuilder();
avCapabalitiesBuilder.setAvailableCapability(capabilityList);
.addAugmentation(NetconfNode.class,
new NetconfNodeBuilder()
.setConnectionStatus(ConnectionStatus.Connecting)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.addAugmentation(NetconfNode.class,
new NetconfNodeBuilder()
.setConnectionStatus(ConnectionStatus.UnableToConnect)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.NetconfMessageTransformer;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
import org.opendaylight.netconf.util.NetconfTopologyPathCreator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
LOG.debug("{}: Schema context built successfully.", id);
final NetconfDeviceCapabilities deviceCap = sessionPreferences.getNetconfDeviceCapabilities();
- final Set<QName> providedSourcesQnames = Sets.newHashSet();
+ final Set<AvailableCapability> providedSourcesQnames = Sets.newHashSet();
+ final Set<AvailableCapability> providedSourcesNonModuleCaps = Sets.newHashSet();
for(ModuleIdentifier id : schemaContext.getAllModuleIdentifiers()) {
- providedSourcesQnames.add(QName.create(id.getQNameModule(), id.getName()));
+ providedSourcesQnames.add(new AvailableCapabilityBuilder()
+ .setCapability(QName.create(id.getQNameModule(), id.getName()).toString()).build());
}
-
- deviceCap.addNonModuleBasedCapabilities(sessionPreferences.getNonModuleCaps());
+ sessionPreferences.getNonModuleCaps().forEach(e -> providedSourcesNonModuleCaps.add(new AvailableCapabilityBuilder()
+ .setCapability(e).build()));
+ deviceCap.addNonModuleBasedCapabilities(providedSourcesNonModuleCaps);
deviceCap.addCapabilities(providedSourcesQnames);
ClusteredNetconfDevice.super.handleSalInitializationSuccess(
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus.Status;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
.setHost(netconfNode.getHost())
.setPort(netconfNode.getPort())
.setConnectionStatus(ConnectionStatus.Connecting)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.setHost(netconfNode.getHost())
.setPort(netconfNode.getPort())
.setConnectionStatus(ConnectionStatus.UnableToConnect)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.setConnectionStatus(ConnectionStatus.Connected)
.setHost(augmentation.getHost())
.setPort(augmentation.getPort())
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.setConnectionStatus(ConnectionStatus.Connected)
.setHost(augmentation.getHost())
.setPort(augmentation.getPort())
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
.setConnectionStatus(ConnectionStatus.Connected)
.setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
.setPort(new PortNumber(2555))
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.build())
.build());
.setConnectionStatus(ConnectionStatus.Connected)
.setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
.setPort(new PortNumber(65535))
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.build())
.build());
.setConnectionStatus(ConnectionStatus.Connecting)
.setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
.setPort(new PortNumber(65535))
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.build())
.build();
.setConnectionStatus(ConnectionStatus.UnableToConnect)
.setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
.setPort(new PortNumber(65535))
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.build())
.build();
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@Test
public void testCombineCreateAttempts() throws ExecutionException, InterruptedException {
NetconfNode testingNode = new NetconfNodeBuilder().setAvailableCapabilities(
- new AvailableCapabilitiesBuilder().setAvailableCapability(Lists.<String>newArrayList()).build())
+ new AvailableCapabilitiesBuilder().setAvailableCapability(Lists.<AvailableCapability>newArrayList()).build())
.setClusteredConnectionStatus(new ClusteredConnectionStatusBuilder().setNodeStatus(Lists.newArrayList(
new NodeStatusBuilder().setStatus(NodeStatus.Status.Connected).build())).build())
.setConnectionStatus(NetconfNodeConnectionStatus.ConnectionStatus.Connected).build();
@Test
public void testSuccessfulCombineUpdateAttempts() throws ExecutionException, InterruptedException {
NetconfNode testingNode = new NetconfNodeBuilder().setAvailableCapabilities(
- new AvailableCapabilitiesBuilder().setAvailableCapability(Lists.<String>newArrayList()).build())
+ new AvailableCapabilitiesBuilder().setAvailableCapability(Lists.<AvailableCapability>newArrayList()).build())
.setClusteredConnectionStatus(new ClusteredConnectionStatusBuilder().setNodeStatus(Lists.newArrayList(
new NodeStatusBuilder().setStatus(NodeStatus.Status.Connected).build())).build())
.setConnectionStatus(NetconfNodeConnectionStatus.ConnectionStatus.Connected).build();
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatus.Status;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.clustered.connection.status.NodeStatusBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
.setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
.setPort(new PortNumber(17830))
.setConnectionStatus(ConnectionStatus.Connected)
- .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<String>()).build())
+ .setAvailableCapabilities(new AvailableCapabilitiesBuilder().setAvailableCapability(new ArrayList<AvailableCapability>()).build())
.setUnavailableCapabilities(new UnavailableCapabilitiesBuilder().setUnavailableCapability(new ArrayList<UnavailableCapability>()).build())
.setClusteredConnectionStatus(
new ClusteredConnectionStatusBuilder()
private boolean isHostAddressPresent(final Host address) {
return address.getDomainName() != null ||
- address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
+ address.getIpAddress() != null && (address.getIpAddress().getIpv4Address() != null || address.getIpAddress().getIpv6Address() != null);
}
@Override
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapabilityBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
final SchemaContext result = schemaBuilderFuture.checkedGet();
LOG.debug("{}: Schema context built successfully from {}", id, requiredSources);
final Collection<QName> filteredQNames = Sets.difference(deviceSources.getRequiredSourcesQName(), capabilities.getUnresolvedCapabilites().keySet());
- capabilities.addCapabilities(filteredQNames);
- capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps());
+ capabilities.addCapabilities(filteredQNames.stream().map(entry -> new AvailableCapabilityBuilder()
+ .setCapability(entry.toString()).setCapabilityOrigin(remoteSessionCapabilities.getModuleBasedCapsOrigin().get(entry)).build())
+ .collect(Collectors.toList()));
+
+ capabilities.addNonModuleBasedCapabilities(remoteSessionCapabilities.getNonModuleCaps().stream().map(entry -> new AvailableCapabilityBuilder()
+ .setCapability(entry).setCapabilityOrigin(AvailableCapability.CapabilityOrigin.DeviceAdvertised).build())
+ .collect(Collectors.toList()));
+
handleSalInitializationSuccess(result, remoteSessionCapabilities, getDeviceSpecificRpc(result));
return;
} catch (final Throwable t) {
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability.FailureReason;
import org.opendaylight.yangtools.yang.common.QName;
public final class NetconfDeviceCapabilities {
private final Map<QName, FailureReason> unresolvedCapabilites;
- private final Set<QName> resolvedCapabilities;
-
- private final Set<String> nonModuleBasedCapabilities;
+ private final Set<AvailableCapability> resolvedCapabilities;
+ private final Set<AvailableCapability> nonModuleBasedCapabilities;
public NetconfDeviceCapabilities() {
this.unresolvedCapabilites = new HashMap<>();
}
}
- public void addCapabilities(Collection<QName> availableSchemas) {
+ public void addCapabilities(Collection<AvailableCapability> availableSchemas) {
resolvedCapabilities.addAll(availableSchemas);
}
- public void addNonModuleBasedCapabilities(Collection<String> nonModuleCapabilities) {
+ public void addNonModuleBasedCapabilities(Collection<AvailableCapability> nonModuleCapabilities) {
this.nonModuleBasedCapabilities.addAll(nonModuleCapabilities);
}
- public Set<String> getNonModuleBasedCapabilities() {
+ public Set<AvailableCapability> getNonModuleBasedCapabilities() {
return nonModuleBasedCapabilities;
}
return unresolvedCapabilites;
}
- public Set<QName> getResolvedCapabilities() {
+ public Set<AvailableCapability> getResolvedCapabilities() {
return resolvedCapabilities;
}
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.net.URI;
import java.util.Collection;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import org.opendaylight.netconf.client.NetconfClientSession;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability.CapabilityOrigin;
import org.opendaylight.yangtools.yang.common.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
};
- private final Set<QName> moduleBasedCaps;
+ private final Map<QName, CapabilityOrigin> moduleBasedCaps;
private final Set<String> nonModuleCaps;
- NetconfSessionPreferences(final Set<String> nonModuleCaps, final Set<QName> moduleBasedCaps) {
+ NetconfSessionPreferences(final Set<String> nonModuleCaps, final Map<QName, CapabilityOrigin> moduleBasedCaps) {
this.nonModuleCaps = Preconditions.checkNotNull(nonModuleCaps);
this.moduleBasedCaps = Preconditions.checkNotNull(moduleBasedCaps);
}
public Set<QName> getModuleBasedCaps() {
+ return moduleBasedCaps.keySet();
+ }
+
+ public Map<QName, CapabilityOrigin> getModuleBasedCapsOrigin() {
return moduleBasedCaps;
}
}
public boolean containsModuleCapability(final QName capability) {
- return moduleBasedCaps.contains(capability);
+ return moduleBasedCaps.containsKey(capability);
}
@Override
* @return new instance of preferences with merged module-based capabilities
*/
public NetconfSessionPreferences addModuleCaps(final NetconfSessionPreferences netconfSessionModuleCapabilities) {
- final HashSet<QName> mergedCaps = Sets.newHashSetWithExpectedSize(moduleBasedCaps.size() + netconfSessionModuleCapabilities.getModuleBasedCaps().size());
- mergedCaps.addAll(moduleBasedCaps);
- mergedCaps.addAll(netconfSessionModuleCapabilities.getModuleBasedCaps());
+ final Map<QName, CapabilityOrigin> mergedCaps = Maps.newHashMapWithExpectedSize(moduleBasedCaps.size() + netconfSessionModuleCapabilities.getModuleBasedCaps().size());
+ mergedCaps.putAll(moduleBasedCaps);
+ mergedCaps.putAll(netconfSessionModuleCapabilities.getModuleBasedCapsOrigin());
return new NetconfSessionPreferences(getNonModuleCaps(), mergedCaps);
}
* @return new instance of preferences with replaced module-based capabilities
*/
public NetconfSessionPreferences replaceModuleCaps(final NetconfSessionPreferences netconfSessionPreferences) {
- return new NetconfSessionPreferences(getNonModuleCaps(), netconfSessionPreferences.getModuleBasedCaps());
+ return new NetconfSessionPreferences(getNonModuleCaps(), netconfSessionPreferences.getModuleBasedCapsOrigin());
+ }
+
+ public NetconfSessionPreferences replaceModuleCaps(Map<QName, CapabilityOrigin> newModuleBasedCaps) {
+ return new NetconfSessionPreferences(getNonModuleCaps(), newModuleBasedCaps);
}
public static NetconfSessionPreferences fromNetconfSession(final NetconfClientSession session) {
}
public static NetconfSessionPreferences fromStrings(final Collection<String> capabilities) {
- final Set<QName> moduleBasedCaps = new HashSet<>();
+ // we do not know origin of capabilities from only Strings, so we set it to default value
+ return fromStrings(capabilities, CapabilityOrigin.DeviceAdvertised);
+ }
+
+ public static NetconfSessionPreferences fromStrings(final Collection<String> capabilities, CapabilityOrigin capabilityOrigin) {
+ final Map<QName, CapabilityOrigin> moduleBasedCaps = new HashMap<>();
final Set<String> nonModuleCaps = Sets.newHashSet(capabilities);
for (final String capability : capabilities) {
String revision = REVISION_PARAM.from(queryParams);
if (!Strings.isNullOrEmpty(revision)) {
- addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName));
+ addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName), capabilityOrigin);
continue;
}
revision = BROKEN_REVISON_PARAM.from(queryParams);
if (Strings.isNullOrEmpty(revision)) {
LOG.warn("Netconf device returned revision incorrectly escaped for {}, ignoring it", capability);
- addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName));
+ addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName), capabilityOrigin);
} else {
- addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName));
+ addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, revision, moduleName), capabilityOrigin);
}
continue;
}
// Fallback, no revision provided for module
- addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName));
+ addModuleQName(moduleBasedCaps, nonModuleCaps, capability, cachedQName(namespace, moduleName), capabilityOrigin);
}
- return new NetconfSessionPreferences(ImmutableSet.copyOf(nonModuleCaps), ImmutableSet.copyOf(moduleBasedCaps));
+ return new NetconfSessionPreferences(ImmutableSet.copyOf(nonModuleCaps), ImmutableMap.copyOf(moduleBasedCaps));
}
-
- private static void addModuleQName(final Set<QName> moduleBasedCaps, final Set<String> nonModuleCaps, final String capability, final QName qName) {
- moduleBasedCaps.add(qName);
+ private static void addModuleQName(final Map<QName, CapabilityOrigin> moduleBasedCaps, final Set<String> nonModuleCaps, final String capability, final QName qName, CapabilityOrigin capabilityOrigin) {
+ moduleBasedCaps.put(qName, capabilityOrigin);
nonModuleCaps.remove(capability);
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilitiesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilitiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability.FailureReason;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapabilityBuilder;
.setFailureReason(input.getValue()).build();
}
};
- public static final Function<QName, String> AVAILABLE_CAPABILITY_TRANSFORMER = new Function<QName, String>() {
- @Override
- public String apply(QName qName) {
- // intern string representation of a capability to avoid duplicates
- return qName.toString().intern();
- }
- };
private final RemoteDeviceId id;
private BindingTransactionChain txChain;
}
private NetconfNode buildDataForNetconfNode(boolean up, NetconfDeviceCapabilities capabilities) {
- List<String> capabilityList = new ArrayList<>();
+ List<AvailableCapability> capabilityList = new ArrayList<>();
capabilityList.addAll(capabilities.getNonModuleBasedCapabilities());
- capabilityList.addAll(FluentIterable.from(capabilities.getResolvedCapabilities()).transform(AVAILABLE_CAPABILITY_TRANSFORMER).toList());
+ capabilityList.addAll(capabilities.getResolvedCapabilities());
+
final AvailableCapabilitiesBuilder avCapabalitiesBuilder = new AvailableCapabilitiesBuilder();
avCapabalitiesBuilder.setAvailableCapability(capabilityList);
container available-capabilities {
config false;
- leaf-list available-capability {
- type string;
+ list available-capability {
+ leaf capability {
+ type string;
+ }
+ leaf capability-origin {
+ type enumeration {
+ enum user-defined;
+ enum device-advertised;
+ }
+ }
}
}
package org.opendaylight.netconf.sal.connect.netconf;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyCollectionOf;
import static org.mockito.Matchers.eq;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas;
import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemasResolver;
import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
verify(facade, timeout(5000).times(2)).onDeviceConnected(any(SchemaContext.class), any(NetconfSessionPreferences.class), any(DOMRpcService.class));
}
+ @Test
+ public void testNetconfDeviceAvailableCapabilitiesBuilding() throws Exception {
+ final RemoteDeviceHandler<NetconfSessionPreferences> facade = getFacade();
+ final NetconfDeviceCommunicator listener = getListener();
+
+ final SchemaContextFactory schemaContextProviderFactory = getSchemaFactory();
+
+ final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO
+ = new NetconfDevice.SchemaResourcesDTO(getSchemaRegistry(), getSchemaRepository(), schemaContextProviderFactory, stateSchemasResolver);
+ final NetconfDevice device = new NetconfDeviceBuilder()
+ .setReconnectOnSchemasChange(true)
+ .setSchemaResourcesDTO(schemaResourcesDTO)
+ .setGlobalProcessingExecutor(getExecutor())
+ .setId(getId())
+ .setSalFacade(facade)
+ .build();
+ NetconfDevice netconfSpy = Mockito.spy(device);
+
+ final NetconfSessionPreferences sessionCaps = getSessionCaps(true,
+ Lists.newArrayList(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
+ Map<QName, AvailableCapability.CapabilityOrigin> moduleBasedCaps = new HashMap<>();
+ moduleBasedCaps.putAll(sessionCaps.getModuleBasedCapsOrigin());
+ moduleBasedCaps.put(QName.create("test:qname:side:loading"), AvailableCapability.CapabilityOrigin.UserDefined);
+
+ netconfSpy.onRemoteSessionUp(sessionCaps.replaceModuleCaps(moduleBasedCaps), listener);
+
+ ArgumentCaptor argument = ArgumentCaptor.forClass(NetconfSessionPreferences.class);
+ verify(netconfSpy, timeout(5000)).handleSalInitializationSuccess(any(SchemaContext.class), (NetconfSessionPreferences) argument.capture(), any(DOMRpcService.class));
+ NetconfDeviceCapabilities netconfDeviceCaps = ((NetconfSessionPreferences) argument.getValue()).getNetconfDeviceCapabilities();
+
+ netconfDeviceCaps.getResolvedCapabilities().forEach(entry -> assertEquals("Builded 'AvailableCapability' schemas should match input capabilities.",
+ moduleBasedCaps.get(QName.create(entry.getCapability())).getName(), entry.getCapabilityOrigin().getName()));
+ }
+
private SchemaContextFactory getSchemaFactory() {
final SchemaContextFactory schemaFactory = mockClass(SchemaContextFactory.class);
doReturn(Futures.immediateCheckedFuture(getSchema())).when(schemaFactory).createSchemaContext(any(Collection.class));
assertEquals( "containsModuleCapability", false, actualCapabilites.containsNonModuleCapability(testCapability) );
assertEquals( "getModuleBasedCaps", Sets.newHashSet(
QName.create( "urn:opendaylight:params:xml:ns:test", "2014-06-02", "test-module" )),
- actualCapabilites.getModuleBasedCaps() );
+ actualCapabilites.getModuleBasedCaps());
assertEquals( "isRollbackSupported", true, actualCapabilites.isRollbackSupported() );
assertEquals( "isMonitoringSupported", true, actualCapabilites.isMonitoringSupported() );
}
container available-capabilities {
config false;
- leaf-list available-capability {
- type string;
+ list available-capability {
+ leaf capability {
+ type string;
+ }
+ leaf capability-origin {
+ type enumeration {
+ enum user-defined;
+ enum device-advertised;
+ }
+ }
}
}
uses netconf-node-fields;
}
-}
+}
\ No newline at end of file
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
-import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
-import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
-import org.opendaylight.restconf.RestConnectorProvider;
import org.opendaylight.restconf.common.references.SchemaContextRef;
import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
import org.opendaylight.restconf.utils.parser.ParserIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
final SchemaContext schemaContext) {
final DOMTransactionChain transactionChain = transactionNode.getTransactionChain();
final DOMDataReadWriteTransaction transaction = transactionChain.newReadWriteTransaction();
- final NormalizedNode<?, ?> node = ImmutableNodes.fromInstanceId(schemaContext, path);
- transaction.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(node.getIdentifier()), node);
- TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
if (data instanceof MapNode) {
+ boolean merge = false;
for (final MapEntryNode child : ((MapNode) data).getValue()) {
- putChild(child, transactionChain, transaction, path);
- }
- } else if (data instanceof AugmentationNode) {
- for (final DataContainerChild<? extends PathArgument, ?> child : ((AugmentationNode) data).getValue()) {
- putChild(child, transactionChain, transaction, path);
- }
- } else if (data instanceof ChoiceNode) {
- for (final DataContainerChild<? extends PathArgument, ?> child : ((ChoiceNode) data).getValue()) {
- putChild(child, transactionChain, transaction, path);
- }
- } else if (data instanceof LeafSetNode<?>) {
- for (final LeafSetEntryNode<?> child : ((LeafSetNode<?>) data).getValue()) {
- putChild(child, transactionChain, transaction, path);
- }
- } else if (data instanceof ContainerNode) {
- for (final DataContainerChild<? extends PathArgument, ?> child : ((ContainerNode) data).getValue()) {
- putChild(child, transactionChain, transaction, path);
+ final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
+ TransactionUtil.checkItemDoesNotExists(
+ transactionChain, transaction, LogicalDatastoreType.CONFIGURATION, childPath,
+ RestconfDataServiceConstant.PostData.POST_TX_TYPE);
+ if (!merge) {
+ merge = true;
+ TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
+ final NormalizedNode<?, ?> emptySubTree = ImmutableNodes.fromInstanceId(schemaContext, path);
+ transaction.merge(LogicalDatastoreType.CONFIGURATION,
+ YangInstanceIdentifier.create(emptySubTree.getIdentifier()), emptySubTree);
+ }
+ transaction.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
}
} else {
- transaction.cancel();
- RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain);
+ TransactionUtil.checkItemDoesNotExists(
+ transactionChain, transaction, LogicalDatastoreType.CONFIGURATION, path,
+ RestconfDataServiceConstant.PostData.POST_TX_TYPE);
- final String errMsg = "Only Map, Choice, Augmentation, LeafSet and Container nodes are supported";
- LOG.trace("{}:{}", errMsg, path);
- throw new RestconfDocumentedException(
- "Node not supported", RestconfError.ErrorType.PROTOCOL, RestconfError.ErrorTag.BAD_ELEMENT, path);
+ TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction);
+ transaction.put(LogicalDatastoreType.CONFIGURATION, path, data);
}
return transaction.submit();
}
- /**
- * Prepare data for submit
- *
- * @param child
- * - data
- * @param transactionChain
- * - transaction chain
- * @param readWriteTx
- * - transaction
- * @param path
- * - path to data
- */
- private static void putChild(final NormalizedNode<?, ?> child, final DOMTransactionChain transactionChain,
- final DOMDataReadWriteTransaction readWriteTx, final YangInstanceIdentifier path) {
- final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
- TransactionUtil.checkItemDoesNotExists(
- transactionChain, readWriteTx, LogicalDatastoreType.CONFIGURATION, childPath,
- RestconfDataServiceConstant.PostData.POST_TX_TYPE);
- readWriteTx.put(LogicalDatastoreType.CONFIGURATION, childPath, child);
- }
-
/**
* Get location from {@link YangInstanceIdentifier} and {@link UriInfo}
*
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
-import com.google.common.base.Optional;
+
import com.google.common.util.concurrent.Futures;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
- doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iid2);
+ doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
final YangInstanceIdentifier.NodeIdentifier identifier = ((ContainerNode) ((SingletonSet) payload.getData().getValue()).iterator().next()).getIdentifier();
final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
final TransactionVarsWrapper wrapper = new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain);
final Response response = PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx);
assertEquals(201, response.getStatus());
- verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
- verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, (NormalizedNode<?, ?>) ((SingletonSet) payload.getData().getValue()).iterator().next());
+ verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
+ verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
}
@Test
final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildList);
- doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iid2);
final MapNode data = (MapNode) payload.getData();
final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier = data.getValue().iterator().next().getIdentifier();
final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iid2, null, null, this.schema);
final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
- doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iid2);
+ doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iid2);
final YangInstanceIdentifier.NodeIdentifier identifier = ((ContainerNode) ((SingletonSet) payload.getData().getValue()).iterator().next()).getIdentifier();
final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
final TransactionVarsWrapper wrapper = new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, this.transactionChain);
final Response response = PostDataTransactionUtil.postData(this.uriInfo, payload, wrapper, this.refSchemaCtx);
assertEquals(Response.Status.INTERNAL_SERVER_ERROR, response.getStatusInfo());
- verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
- verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, (NormalizedNode<?, ?>) ((SingletonSet) payload.getData().getValue()).iterator().next());
+ verify(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iid2);
+ verify(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
}
}