xtend-gen
classes
out/
+.externalToolBuilders
+maven-eclipse.xml
<version>1.1-SNAPSHOT</version>
<packaging>maven-archetype</packaging>
+ <properties>
+ <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ <nexus.repository.release>opendaylight.release</nexus.repository.release>
+ <nexus.repository.snapshot>opendaylight.snapshot</nexus.repository.snapshot>
+ </properties>
+
<name>odl-model-project</name>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
<distributionManagement>
<repository>
<id>opendaylight-release</id>
- <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<site>
<id>website</id>
<properties>\r
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r
<nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>\r
+ <nexus.repository.release>opendaylight.release</nexus.repository.release>
+ <nexus.repository.snapshot>opendaylight.release</nexus.repository.snaphot>
<yang.version>0.6.2-SNAPSHOT</yang.version>\r
<yang.codegen.version>0.6.2-SNAPSHOT</yang.codegen.version>\r
<bundle.plugin.version>2.3.7</bundle.plugin.version>\r
<pluginRepository>\r
<id>opendaylight-snapshot</id>\r
<name>opendaylight-snapshot</name>\r
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>\r
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
<snapshots>\r
<enabled>true</enabled>\r
</snapshots>\r
<repository>\r
<id>opendaylight-snapshot</id>\r
<name>opendaylight-snapshot</name>\r
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>\r
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
<snapshots>\r
<enabled>true</enabled>\r
</snapshots>\r
<!-- OpenDayLight Released artifact -->\r
<repository>\r
<id>opendaylight-release</id>\r
- <url>${nexusproxy}/repositories/opendaylight.release/</url>\r
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>\r
<!-- OpenDayLight Snapshot artifact -->\r
<snapshotRepository>\r
<id>opendaylight-snapshot</id>\r
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>\r
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>\r
<!-- Site deployment -->\r
<site>\r
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
byte[] targetIP = tIP.getAddress();
ARP arp = createARP(ARP.REPLY, sMAC, senderIP, tMAC, targetIP);
+ if(log.isTraceEnabled()) {
+ log.trace("Sending Arp Reply with srcMac {} - srcIp {} - dstMac {} - dstIp {} - outport {}",
+ HexEncode.bytesToHexString(sMAC),
+ sIP, HexEncode.bytesToHexString(tMAC), tIP, p);
+ }
+
Ethernet ethernet = createEthernet(sMAC, tMAC, arp);
RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet);
this.dataPacketService.transmitDataPacket(destPkt);
}
+ private void logArpPacket(ARP pkt, NodeConnector p) {
+ try {
+ if (pkt.getOpCode() == ARP.REQUEST) {
+ log.trace("Received Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {}", HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()),
+ InetAddress.getByAddress(pkt.getSenderProtocolAddress()), HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()),
+ InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p);
+ } else if(pkt.getOpCode() == ARP.REPLY) {
+ log.trace("Received Arp Reply with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {}", HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()),
+ InetAddress.getByAddress(pkt.getSenderProtocolAddress()), HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()),
+ InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p);
+ }
+ } catch(UnknownHostException e) {
+ log.warn("Illegal Ip Address in the ARP packet", e);
+ }
+ }
+
protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p) {
+ if(log.isTraceEnabled()) {
+ logArpPacket(pkt, p);
+ }
+
byte[] sourceMAC = eHeader.getSourceMACAddress();
byte[] targetMAC = eHeader.getDestinationMACAddress();
/*
byte[] targetIPByte = targetIP.getAddress();
ARP arp = createARP(ARP.REQUEST, getControllerMAC(), senderIP, targetHardwareAddress, targetIPByte);
+ if(log.isTraceEnabled()) {
+ log.trace("Sending Broadcast Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - outport {}", HexEncode.bytesToHexString(getControllerMAC()),
+ subnet.getNetworkAddress(), HexEncode.bytesToHexString(targetHardwareAddress), targetIP, p);
+ }
+
byte[] destMACAddress = NetUtils.getBroadcastMACAddr();
Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp);
byte[] targetMAC = host.getDataLayerAddressBytes();
ARP arp = createARP(ARP.REQUEST, getControllerMAC(), senderIP, targetMAC, targetIP);
+ if(log.isTraceEnabled()) {
+ log.trace("Sending Unicast Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - outport {}",
+ HexEncode.bytesToHexString(getControllerMAC()),
+ subnet.getNetworkAddress(), HexEncode.bytesToHexString(targetMAC), host.getNetworkAddress(),
+ outPort);
+ }
+
Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp);
RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet);
package org.opendaylight.controller.clustering.services_implementation.internal;
import java.util.Map;
+
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.slf4j.Logger;
@Override
void setCacheUpdateAware(Map props, ICacheUpdateAware s) {
- logger.trace("setCacheUpdateAware");
+ logger.trace("setCacheUpdateAware: {}",s);
if (props.get("containerName") != null) {
// If we got a reference with the containerName property
// that is not what we are looking for, so filter it out.
@Override
void unsetCacheUpdateAware(Map props, ICacheUpdateAware s) {
- logger.trace("unsetCacheUpdateAware");
+ logger.trace("unsetCacheUpdateAware: {}",s);
if (props.get("containerName") != null) {
// If we got a reference with the containerName property
// that is not what we are looking for, so filter it out.
* export the interface ICoordinatorChangeAware
*/
class ListenCoordinatorChange implements IListenRoleChange {
+ @Override
public void newActiveAvailable() {
if (coordinatorChangeAware != null) {
// Make sure to look the set while walking it
logger.trace("cachenames provided below:");
for (String cache : caches) {
if (this.cacheUpdateAware.get(cache) != null) {
- logger.error("cachename:{} on container:{} has " +
- "already a listener", cache,
- this.containerName);
+ logger.error("cachename:{} on container:{} has already a listener", cache, this.containerName);
} else {
- GetUpdatesContainer<?, ?> up =
- new GetUpdatesContainer(s, this.containerName,
- cache);
+ GetUpdatesContainer<?, ?> up = new GetUpdatesContainer(s, this.containerName, cache);
if (up != null) {
try {
this.clusterService.addListener(this.containerName,
"been registered", cache,
this.containerName);
} catch (CacheListenerAddException exc) {
+ logger.debug("Cache {} didn't exist when {} tried to register to its updates", cache, s);
// Do nothing, the important is that
// we don't register the listener in
// the shadow, and we are not doing
<properties>
<nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ <nexus.repository.release>opendaylight.release</nexus.repository.release>
+ <nexus.repository.snapshot>opendaylight.snapshot</nexus.repository.snapshot>
<sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
</properties>
<distributionManagement>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
<pluginRepository>
<id>opendaylight-snapshot</id>
<name>opendaylight-snapshot</name>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<repository>
<id>opendaylight-snapshot</id>
<name>opendaylight-snapshot</name>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
</scm>
<properties>
- <nexusdeploy>http://nexus.opendaylight.org/content</nexusdeploy>
+ <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ <nexus.repository.release>opendaylight.release</nexus.repository.release>
+ <nexus.repository.snapshot>opendaylight.snapshot</nexus.repository.snapshot>
<sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
<releaseplugin.version>2.3.2</releaseplugin.version>
</properties>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusdeploy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusdeploy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
import org.opendaylight.controller.config.manager.impl.osgi.mapping.ModuleInfoBundleTracker;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.RuntimeGeneratedMappingServiceActivator;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleActivator;
public class ConfigManagerActivator implements BundleActivator {
private static final Logger logger = LoggerFactory.getLogger(ConfigManagerActivator.class);
- private ExtensibleBundleTracker<Collection<Registration<YangModuleInfo>>> bundleTracker;
+ private final MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
+ private ExtensibleBundleTracker<Collection<ObjectRegistration<YangModuleInfo>>> bundleTracker;
private ConfigRegistryImpl configRegistry;
private ConfigRegistryJMXRegistrator configRegistryJMXRegistrator;
- private ServiceRegistration configRegistryServiceRegistration;
-
- private final MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
-
+ private ServiceRegistration<?> configRegistryServiceRegistration;
private RuntimeGeneratedMappingServiceActivator mappingServiceActivator;
@Override
*/
package org.opendaylight.controller.config.manager.impl.osgi.mapping;
+import static java.lang.String.format;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
import org.apache.commons.io.IOUtils;
-import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-import static java.lang.String.format;
-
/**
* Tracks bundles and attempts to retrieve YangModuleInfo.
*/
-public final class ModuleInfoBundleTracker implements BundleTrackerCustomizer<Collection<Registration<YangModuleInfo>>> {
+public final class ModuleInfoBundleTracker implements BundleTrackerCustomizer<Collection<ObjectRegistration<YangModuleInfo>>> {
private static final Logger logger = LoggerFactory.getLogger(ModuleInfoBundleTracker.class);
public static final String GET_MODULE_INFO_METHOD = "getModuleInfo";
public static final String MODULE_INFO_PROVIDER_PATH_PREFIX = "META-INF/services/";
- private ModuleInfoBackedContext moduleInfoLoadingStrategy = ModuleInfoBackedContext.create();
+ private final ModuleInfoBackedContext moduleInfoLoadingStrategy = ModuleInfoBackedContext.create();
public GeneratedClassLoadingStrategy getModuleInfoLoadingStrategy() {
return moduleInfoLoadingStrategy;
}
@Override
- public Collection<Registration<YangModuleInfo>> addingBundle(Bundle bundle, BundleEvent event) {
+ public Collection<ObjectRegistration<YangModuleInfo>> addingBundle(Bundle bundle, BundleEvent event) {
URL resource = bundle.getEntry(MODULE_INFO_PROVIDER_PATH_PREFIX + YangModelBindingProvider.class.getName());
if(resource==null) {
return null;
}
- List<Registration<YangModuleInfo>> registrations = new LinkedList<>();
+ List<ObjectRegistration<YangModuleInfo>> registrations = new LinkedList<>();
try (InputStream inputStream = resource.openStream()) {
List<String> lines = IOUtils.readLines(inputStream);
}
@Override
- public void modifiedBundle(Bundle bundle, BundleEvent event, Collection<Registration<YangModuleInfo>> object) {
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Collection<ObjectRegistration<YangModuleInfo>> object) {
// NOOP
}
@Override
- public void removedBundle(Bundle bundle, BundleEvent event, Collection<Registration<YangModuleInfo>> regs) {
+ public void removedBundle(Bundle bundle, BundleEvent event, Collection<ObjectRegistration<YangModuleInfo>> regs) {
if(regs == null) {
return;
}
- for (Registration<YangModuleInfo> reg : regs) {
+ for (ObjectRegistration<YangModuleInfo> reg : regs) {
try {
reg.close();
} catch (Exception e) {
private void assertSnapshot(ConfigSnapshotHolder result, String directory) throws Exception {
SortedSet<String> expectedCapabilities = new TreeSet<>(IOUtils.readLines(getClass().getResourceAsStream("/" + directory + "/expectedCapabilities.txt")));
String expectedSnapshot = IOUtils.toString(getClass().getResourceAsStream("/" + directory + "/expectedSnapshot.xml"));
+ expectedSnapshot = expectedSnapshot.replaceAll("\r","");
+ String _snapshot = result.getConfigSnapshot();
+ _snapshot = _snapshot.replaceAll("\r","");
assertEquals(expectedCapabilities, result.getCapabilities());
- assertEquals(expectedSnapshot, result.getConfigSnapshot());
+ assertEquals(expectedSnapshot, _snapshot);
}
}
}
public void started() {
- String schemeStr = System.getProperty("connection.scheme");
- for (ConnectionMgmtScheme scheme : ConnectionMgmtScheme.values()) {
- AbstractScheme schemeImpl = SchemeFactory.getScheme(scheme,
- clusterServices);
- if (schemeImpl != null) {
- schemes.put(scheme, schemeImpl);
- if (scheme.name().equalsIgnoreCase(schemeStr)) {
- activeScheme = scheme;
- }
- }
- }
connectionEventThread.start();
"ConnectionEvent Thread");
this.connectionEvents = new LinkedBlockingQueue<ConnectionMgmtEvent>();
schemes = new ConcurrentHashMap<ConnectionMgmtScheme, AbstractScheme>();
+
+ String schemeStr = System.getProperty("connection.scheme");
+ for (ConnectionMgmtScheme scheme : ConnectionMgmtScheme.values()) {
+ AbstractScheme schemeImpl = SchemeFactory.getScheme(scheme, clusterServices);
+ if (schemeImpl != null) {
+ schemes.put(scheme, schemeImpl);
+ if (scheme.name().equalsIgnoreCase(schemeStr)) {
+ activeScheme = scheme;
+ }
+ }
+ }
}
public void stopping() {
}
/*
- * Clustering Services' doesnt provide the existing states in the cache
+ * Clustering Services doesn't provide the existing states in the cache
* update callbacks. Hence, using a scratch local cache to maintain the
* existing state.
*/
return;
Set<InetAddress> existingControllers = existingConnections.get(node);
if (existingControllers != null) {
- logger.debug(
- "Processing Update for : {} NewControllers : {} existingControllers : {}",
- node, newControllers.toString(),
- existingControllers.toString());
+ logger.debug("Processing Update for : {} NewControllers : {} existingControllers : {}", node,
+ newControllers.toString(), existingControllers.toString());
if (newControllers.size() < existingControllers.size()) {
- Set<InetAddress> removed = new HashSet<InetAddress>(
- existingControllers);
+ Set<InetAddress> removed = new HashSet<InetAddress>(existingControllers);
if (removed.removeAll(newControllers)) {
logger.debug("notifyNodeDisconnectFromMaster({})", node);
notifyNodeDisconnectedEvent(node);
}
}
} else {
- logger.debug("Ignoring the Update for : {} NewControllers : {}",
- node, newControllers.toString());
+ logger.debug("Ignoring the Update for : {} NewControllers : {}", node, newControllers.toString());
}
existingConnections.put(node, newControllers);
}
public void entryDeleted(Node key, String cacheName, boolean originLocal) {
if (originLocal)
return;
- logger.debug("Deleted : {} cache : {}", key, cacheName);
+ logger.debug("Deleted entry {} from cache : {}", key, cacheName);
notifyNodeDisconnectedEvent(key);
}
allocateCaches();
retrieveCaches();
} else {
- log.error("Couldn't retrieve caches for scheme %s. Clustering service unavailable", name);
+ log.error("Couldn't retrieve caches for scheme {}. Clustering service unavailable", name);
}
}
log.error("An error occured",e);
}
}
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((nodeConnections == null) ? 0 : nodeConnections.hashCode());
+ result = prime * result + ((nodeConnectionsCacheName == null) ? 0 : nodeConnectionsCacheName.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof AbstractScheme)) {
+ return false;
+ }
+ AbstractScheme other = (AbstractScheme) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (nodeConnections == null) {
+ if (other.nodeConnections != null) {
+ return false;
+ }
+ } else if (!nodeConnections.equals(other.nodeConnections)) {
+ return false;
+ }
+ if (nodeConnectionsCacheName == null) {
+ if (other.nodeConnectionsCacheName != null) {
+ return false;
+ }
+ } else if (!nodeConnectionsCacheName.equals(other.nodeConnectionsCacheName)) {
+ return false;
+ }
+ return true;
+ }
}
reference\:file\:../lib/slf4j-api-1.7.2.jar@1:start,\
reference\:file\:../lib/logback-classic-1.0.9.jar@1:start,\
reference\:file\:../lib/logback-core-1.0.9.jar@1:start,\
- reference\:file\:../lib/logging.bridge-0.4.1-SNAPSHOT@1:start,\
+ reference\:file\:../lib/logging.bridge-0.4.2-SNAPSHOT@1:start,\
reference\:file\:../lib/jersey-core-1.17.jar@2:start,\
reference\:file\:../lib/jersey-server-1.17.jar@2:start
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
+ <version>1.1-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<scm>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
<executions>
<execution>
<goals>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-core-api</artifactId>
- <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
- <version>0.2.3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.7.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
- <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
leaf-list current-capability {
type string;
}
+
+ container pass-through {
+ when "../connected = true";
+ description
+ "When the underlying node is connected, its NETCONF context
+ is available verbatim under this container through the
+ mount extension.";
+ }
}
augment /inv:nodes/inv:node {
uses netconf-node-fields;
}
-}
\ No newline at end of file
+}
* removes direct dependencies between providers and consumers.
*
* The Binding-aware broker is also responsible for translation from Java
- * classes modeling the functionality and data to binding-indpenedent form which
+ * classes modeling the functionality and data to binding-independent form which
* is used in SAL Core.
*
*
import org.opendaylight.yangtools.yang.binding.Notification;
+/**
+ * Interface implemented by objects interested in some sort of Notification. This
+ * class acts as a base interface for specific listeners which usually are a type
+ * capture of this interface.
+ *
+ * @param <T> Notification type
+ */
public interface NotificationListener<T extends Notification> extends EventListener {
-
+ /**
+ * Invoked to deliver the notification. Note that this method may be invoked
+ * from a shared thread pool, so implementations SHOULD NOT perform CPU-intensive
+ * operations and they definitely MUST NOT invoke any potentially blocking
+ * operations.
+ *
+ * @param notification Notification being delivered.
+ */
void onNotification(T notification);
}
import org.opendaylight.yangtools.yang.binding.Notification;
public interface NotificationProviderService extends NotificationService, NotificationPublishService<Notification> {
-
-
- /**
- * Deprecated. Use {@link #publish(Notification)}.
- *
- * @param notification
- */
- @Deprecated
- void notify(Notification notification);
-
- /**
- * Deprecated. Use {@link #publish(Notification,ExecutorService)}.
- *
- * @param notification
- */
- @Deprecated
- void notify(Notification notification, ExecutorService service);
-
/**
* Publishes a notification.
*
import org.opendaylight.yangtools.yang.binding.Notification;
public interface NotificationService extends BindingAwareService {
- /**
- *
- * Deprecated: use {@link #addNotificationListener(Class, NotificationListener)} istead.
- *
- * @param listener
- */
- @Deprecated
- <T extends Notification> void addNotificationListener(Class<T> notificationType, NotificationListener<T> listener);
-
- /**
- *
- * Deprecated: use {@link #addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)} istead.
- *
- * @param listener
- */
- @Deprecated
- void addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener);
-
- /**
- * Deprecated: use {@link Registration#close()} istead.
- * @param listener
- */
- @Deprecated
- void removeNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener);
-
- /**
- * Deprecated: use {@link Registration#close()} istead.
- * @param listener
- */
- @Deprecated
- <T extends Notification> void removeNotificationListener(Class<T> notificationType, NotificationListener<T> listener);
-
-
/**
* Register a generic listener for specified notification type only.
*
<T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(
Class<T> notificationType, NotificationListener<T> listener);
-
/**
* Register a listener which implements generated notification interfaces derived from
* {@link org.opendaylight.yangtools.yang.binding.NotificationListener}.
public interface RpcConsumerRegistry extends BindingAwareService {
/**
* Returns a session specific instance (implementation) of requested
- * YANG module implentation / service provided by consumer.
+ * YANG module implementation / service provided by consumer.
*
* @return Session specific implementation of service
*/
RpcConsumerRegistry, //
RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
/**
- * Registers an global RpcService implementation.
+ * Registers a global RpcService implementation.
*
* @param type
* @param implementation
/**
*
- * Register an Routed RpcService where routing is determined on annotated
+ * Register a Routed RpcService where routing is determined on annotated
* (in YANG model) context-reference and value of annotated leaf.
*
* @param type
* Type of RpcService, use generated interface class, not your
- * implementation clas
+ * implementation class
* @param implementation
* Implementation of RpcService
- * @return Registration object for routed Rpc which could be used to close
- * an
+ * @return Registration object for routed Rpc which could be used to unregister
*
* @throws IllegalStateException
*/
/**
* Synchronized wrapper for DataModificationTransaction.
- *
+ *
* To get instance of synchronized wrapper use {@link #from(DataModificationTransaction)}
*
*/
public final class SynchronizedTransaction implements DataModificationTransaction,Delegator<DataModificationTransaction> {
private final DataModificationTransaction delegate;
-
+
private SynchronizedTransaction(DataModificationTransaction delegate) {
this.delegate = delegate;
}
/**
* Returns synchronized wrapper on supplied transaction.
- *
+ *
* @param transaction Transaction for which synchronized wrapper should be created.
* @return Synchronized wrapper over transaction.
*/
return delegate.getUpdatedOperationalData();
}
- @Deprecated
- public synchronized void putRuntimeData(InstanceIdentifier<? extends DataObject> path, DataObject data) {
- delegate.putRuntimeData(path, data);
- }
-
@Override
public synchronized Object getIdentifier() {
return delegate.getIdentifier();
return delegate.getUpdatedConfigurationData();
}
- @Deprecated
- public synchronized void removeRuntimeData(InstanceIdentifier<? extends DataObject> path) {
- delegate.removeRuntimeData(path);
- }
-
@Override
public synchronized void removeOperationalData(InstanceIdentifier<? extends DataObject> path) {
delegate.removeOperationalData(path);
/**
* RpcRouter is responsible for selecting RpcService based on provided routing
* context identifier {@link RpcRoutingTable#getContextIdentifier()} and path in
- * overal data tree (@link {@link InstanceIdentifier}.
+ * overall data tree (@link {@link InstanceIdentifier}.
*
*
* @author Tony Tkacik <ttkacik@cisco.com>
this.executor = executor;\r
}\r
\r
- @Deprecated\r
- override <T extends Notification> addNotificationListener(Class<T> notificationType,\r
- NotificationListener<T> listener) {\r
- listeners.put(notificationType, listener)\r
- }\r
-\r
- @Deprecated\r
- override <T extends Notification> removeNotificationListener(Class<T> notificationType,\r
- NotificationListener<T> listener) {\r
- listeners.remove(notificationType, listener)\r
- }\r
-\r
- override notify(Notification notification) {\r
- publish(notification)\r
- }\r
-\r
def getNotificationTypes(Notification notification) {\r
notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)]\r
}\r
\r
- @Deprecated\r
- override addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {\r
- throw new UnsupportedOperationException("Deprecated method. Use registerNotificationListener instead.");\r
-\r
- }\r
-\r
- @Deprecated\r
- override removeNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {\r
- throw new UnsupportedOperationException(\r
- "Deprecated method. Use RegisterNotificationListener returned value to close registration.")\r
- }\r
-\r
- @Deprecated\r
- override notify(Notification notification, ExecutorService service) {\r
- publish(notification, service)\r
- }\r
-\r
override publish(Notification notification) {\r
publish(notification, executor)\r
}\r
*/
package org.opendaylight.controller.sal.binding.impl;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.EventListener;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.WeakHashMap;
-
import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import static com.google.common.base.Preconditions.checkState;
+
public class RpcProviderRegistryImpl implements //
RpcProviderRegistry, //
RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
private RuntimeCodeGenerator rpcFactory = SingletonHolder.RPC_GENERATOR_IMPL;
+ // publicProxies is a cache of proxy objects where each value in the map corresponds to a specific RpcService
private final Map<Class<? extends RpcService>, RpcService> publicProxies = new WeakHashMap<>();
private final Map<Class<? extends RpcService>, RpcRouter<?>> rpcRouters = new WeakHashMap<>();
private final ListenerRegistry<RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> routeChangeListeners = ListenerRegistry
return getRpcRegistryChecked().getRpcService(module);
}
- @Override
- @Deprecated
- public <T extends Notification> void addNotificationListener(Class<T> notificationType,
- NotificationListener<T> listener) {
- getNotificationBrokerChecked().addNotificationListener(notificationType, listener);
- }
-
- @Override
- @Deprecated
- public void addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
- getNotificationBrokerChecked().addNotificationListener(listener);
- }
-
- @Override
- @Deprecated
- public void removeNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
- getNotificationBrokerChecked().removeNotificationListener(listener);
- }
-
- @Override
- @Deprecated
- public <T extends Notification> void removeNotificationListener(Class<T> notificationType,
- NotificationListener<T> listener) {
- getNotificationBrokerChecked().removeNotificationListener(notificationType, listener);
- }
-
@Override
public <T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(
Class<T> notificationType, NotificationListener<T> listener) {
return getRpcRegistryChecked().addRoutedRpcImplementation(type, implementation);
}
- @Override
- @Deprecated
- public void notify(Notification notification) {
- getNotificationBrokerChecked().notify(notification);
- }
-
- @Override
- @Deprecated
- public void notify(Notification notification, ExecutorService service) {
- getNotificationBrokerChecked().notify(notification, service);
- }
-
@Override
public void publish(Notification notification) {
getNotificationBrokerChecked().publish(notification);
import org.opendaylight.yangtools.yang.common.RpcResult;
public interface DataModification<P extends Path<P>, D> extends DataChange<P, D>, DataReader<P, D> {
-
/**
* Returns transaction identifier
*
TransactionStatus getStatus();
- /**
- *
- * @deprecated Use {@link #putOperationalData(Object, Object)} instead.
- *
- * @param path
- * @param data
- */
- @Deprecated
- void putRuntimeData(P path, D data);
-
/**
* Store a piece of data at specified path. This acts as a merge operation,
* which is to say that any pre-existing data which is not explicitly
*/
void putConfigurationData(P path, D data);
- /**
- * @deprecated Use {@link #removeOperationalData(Object)}
- *
- * @param path
- */
- @Deprecated
- void removeRuntimeData(P path);
-
void removeOperationalData(P path);
void removeConfigurationData(P path);
* {@link TransactionStatus#FAILED} is reached.
*/
Future<RpcResult<TransactionStatus>> commit();
-
}
private final Map<P, D> unmodifiable_operationalUpdate;
private final Set<P> unmodifiable_configurationRemove;
private final Set<P> unmodifiable_OperationalRemove;
- private DataReader<P, D> reader;
+ private final DataReader<P, D> reader;
public AbstractDataModification(DataReader<P, D> reader) {
this.reader = reader;
operationalUpdate.put(path, mergeOperationalData(path,original,data));
}
- @Override
- public final void putRuntimeData(P path, D data) {
- putOperationalData(path, data);
- }
-
@Override
public final void removeOperationalData(P path) {
checkMutable();
operationalRemove.put(path, path);
}
- @Override
- public final void removeRuntimeData(P path) {
- removeOperationalData(path);
- }
-
@Override
public final void removeConfigurationData(P path) {
checkMutable();
}
return null;
}
-
+
protected D mergeOperationalData(P path,D stored, D modified) {
return modified;
}
-
+
protected D mergeConfigurationData(P path,D stored, D modified) {
return modified;
}
final Future<RpcResult<TransactionStatus>> commit(final AbstractDataTransaction<P, D> transaction) {
Preconditions.checkNotNull(transaction);
- transaction.changeStatus(TransactionStatus.SUBMITED);
final TwoPhaseCommit<P, D, DCL> task = new TwoPhaseCommit<P, D, DCL>(transaction, this);
this.getSubmittedTransactionsCount().getAndIncrement();
package org.opendaylight.controller.md.sal.common.impl.service;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-@SuppressWarnings("all")
+import com.google.common.base.Preconditions;
+
public abstract class AbstractDataTransaction<P extends Path<P>, D extends Object> extends
AbstractDataModification<P, D> {
private final static Logger LOG = LoggerFactory.getLogger(AbstractDataTransaction.class);
private final Object identifier;
+ private final long allocationTime;
+ private long readyTime = 0;
+ private long completeTime = 0;
- @Override
- public Object getIdentifier() {
- return this.identifier;
- }
-
- private TransactionStatus status;
+ private TransactionStatus status = TransactionStatus.NEW;
private final AbstractDataBroker<P, D, ? extends Object> broker;
protected AbstractDataTransaction(final Object identifier,
final AbstractDataBroker<P, D, ? extends Object> dataBroker) {
super(dataBroker);
- this.identifier = identifier;
- this.broker = dataBroker;
- this.status = TransactionStatus.NEW;
- AbstractDataTransaction.LOG.debug("Transaction {} Allocated.", identifier);
+ this.identifier = Preconditions.checkNotNull(identifier);
+ this.broker = Preconditions.checkNotNull(dataBroker);
+ this.allocationTime = System.nanoTime();
+ LOG.debug("Transaction {} Allocated.", identifier);
+ }
+
+ @Override
+ public Object getIdentifier() {
+ return this.identifier;
}
@Override
public Future<RpcResult<TransactionStatus>> commit() {
+ readyTime = System.nanoTime();
+ LOG.debug("Transaction {} Ready after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(readyTime - allocationTime));
+ changeStatus(TransactionStatus.SUBMITED);
+
return this.broker.commit(this);
}
return this.broker.readOperationalData(path);
}
-
-
@Override
public int hashCode() {
final int prime = 31;
return false;
if (getClass() != obj.getClass())
return false;
- AbstractDataTransaction other = (AbstractDataTransaction) obj;
+ AbstractDataTransaction<?, ?> other = (AbstractDataTransaction<?, ?>) obj;
if (identifier == null) {
if (other.identifier != null)
return false;
protected abstract void onStatusChange(final TransactionStatus status);
- public void changeStatus(final TransactionStatus status) {
- Object _identifier = this.getIdentifier();
- AbstractDataTransaction.LOG
- .debug("Transaction {} transitioned from {} to {}", _identifier, this.status, status);
+ public void succeeded() {
+ this.completeTime = System.nanoTime();
+ LOG.debug("Transaction {} Committed after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(completeTime - readyTime));
+ changeStatus(TransactionStatus.COMMITED);
+ }
+
+ public void failed() {
+ this.completeTime = System.nanoTime();
+ LOG.debug("Transaction {} Failed after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(completeTime - readyTime));
+ changeStatus(TransactionStatus.FAILED);
+ }
+
+ private void changeStatus(final TransactionStatus status) {
+ LOG.debug("Transaction {} transitioned from {} to {}", getIdentifier(), this.status, status);
this.status = status;
this.onStatusChange(status);
}
// The transaction has no effects, let's just shortcut it
if (changedPaths.isEmpty()) {
dataBroker.getFinishedTransactionsCount().getAndIncrement();
- transaction.changeStatus(TransactionStatus.COMMITED);
+ transaction.succeeded();
log.trace("Transaction: {} Finished successfully (no effects).", transactionId);
} catch (Exception e) {
log.error("Transaction: {} Request Commit failed", transactionId, e);
dataBroker.getFailedTransactionsCount().getAndIncrement();
- this.transaction.changeStatus(TransactionStatus.FAILED);
+ this.transaction.failed();
return this.rollback(handlerTransactions, e);
}
} catch (Exception e) {
log.error("Transaction: {} Finish Commit failed", transactionId, e);
dataBroker.getFailedTransactionsCount().getAndIncrement();
- transaction.changeStatus(TransactionStatus.FAILED);
+ transaction.failed();
return this.rollback(handlerTransactions, e);
}
dataBroker.getFinishedTransactionsCount().getAndIncrement();
- transaction.changeStatus(TransactionStatus.COMMITED);
+ transaction.succeeded();
log.trace("Transaction: {} Finished successfully.", transactionId);
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
/**
* Notification Publishing Service
*
* <li>For each subscriber {@link Broker} invokes
* {@link NotificationListener#onNotification(CompositeNode)}
* </ol>
- *
- *
- *
*/
public interface NotificationPublishService extends NotificationService {
-
/**
* Publishes a notification.
*
* @param notification
* Notification to publish
*/
- @Deprecated
- void sendNotification(CompositeNode notification);
-
void publish(CompositeNode notification);
}
private final DataBrokerImpl dataReader;
private final NotificationRouter notificationRouter;
private final DataReader<InstanceIdentifier,CompositeNode> readWrapper;
-
-
+
+
private final InstanceIdentifier mountPath;
private SchemaContext schemaContext;
return dataReader.readOperationalData(path);
}
+ @Override
public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
return dataReader.registerOperationalReader(path, reader);
}
+ @Override
public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
return dataReader.registerConfigurationReader(path, reader);
return rpcs.addRpcImplementation(rpcType, implementation);
}
+ @Override
public Set<QName> getSupportedRpcs() {
return rpcs.getSupportedRpcs();
}
-
+
+ @Override
public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
return rpcs.invokeRpc(rpc, input);
}
+ @Override
public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(RpcRegistrationListener listener) {
return rpcs.addRpcRegistrationListener(listener);
}
return dataReader.registerDataChangeListener(path, listener);
}
- @Override
- public void sendNotification(CompositeNode notification) {
- publish(notification);
- }
-
@Override
public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
return dataReader.registerCommitHandler(path, commitHandler);
}
-
+
@Override
public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
// NOOP
}
-
+
@Override
public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
// NOOP
}
-
+
@Override
public void addValidator(DataStoreIdentifier store, DataValidator validator) {
// NOOP
public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
// NOOP
}
-
+
+ @Override
public SchemaContext getSchemaContext() {
return schemaContext;
}
+ @Override
public void setSchemaContext(SchemaContext schemaContext) {
this.schemaContext = schemaContext;
}
class ReadWrapper implements DataReader<InstanceIdentifier, CompositeNode> {
-
-
+
+
private InstanceIdentifier shortenPath(InstanceIdentifier path) {
InstanceIdentifier ret = null;
if(mountPath.contains(path)) {
}
return ret;
}
-
+
@Override
public CompositeNode readConfigurationData(InstanceIdentifier path) {
InstanceIdentifier newPath = shortenPath(path);
}
return MountPointImpl.this.readConfigurationData(newPath);
}
-
+
@Override
public CompositeNode readOperationalData(InstanceIdentifier path) {
InstanceIdentifier newPath = shortenPath(path);
NotificationPublishService {
@Override
- public void sendNotification(CompositeNode notification) {
+ public void publish(CompositeNode notification) {
checkSessionState();
if (notification == null)
throw new IllegalArgumentException(
"Notification must not be null.");
NotificationModule.this.sendNotification(notification);
}
-
- @Override
- public void publish(CompositeNode notification) {
- sendNotification(notification);
- }
}
@Override
super(ref, delegate);
}
- public void sendNotification(CompositeNode notification) {
- getDelegate().sendNotification(notification);
- }
-
+ @Override
public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
return addRegistration(getDelegate().addNotificationListener(notification, listener));
}
+ @Override
public void publish(CompositeNode notification) {
getDelegate().publish(notification);
}
<dependency>
<groupId> ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
- <version>1.0.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
- <version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
- <version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
- <version>${jackson.version}</version>
</dependency>
<dependency>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
- <version>${yangtools.version}</version>
<executions>
<execution>
<goals>
@Path("/streams/stream/{identifier:.+}")
public Response subscribeToStream(@Encoded @PathParam("identifier") String identifier, @Context UriInfo uriInfo);
+ @GET
+ @Path("/streams")
+ @Produces({Draft02.MediaTypes.API+XML, Draft02.MediaTypes.API+JSON,
+ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
+ public StructuredData getAvailableStreams();
+
+
}
val static RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE = "restconf"
val static RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE = "modules"
val static RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE = "module"
+ val static RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE = "streams"
+ val static RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE = "stream"
val static RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE = "operations"
val static SAL_REMOTE_NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote"
val static SAL_REMOTE_RPC_SUBSRCIBE = "create-data-change-event-subscription"
return new StructuredData(modulesNode, modulesSchemaNode, null)
}
+ override getAvailableStreams(){
+ var Set<String> availableStreams = Notificator.getStreamNames();
+ val List<Node<?>> streamsAsData = new ArrayList
+ val streamSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE)
+ for (String streamName:availableStreams){
+ streamsAsData.add(streamName.toStreamCompositeNode(streamSchemaNode))
+ }
+ val streamsSchemaNode = restconfModule.getSchemaNode(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE)
+ val streamsNode = NodeFactory.createImmutableCompositeNode(streamsSchemaNode.QName, null, streamsAsData)
+ return new StructuredData(streamsNode, streamsSchemaNode, null)
+ }
override getModules(String identifier) {
var Set<Module> modules = null
var MountInstance mountPoint = null
}
}
+ private def CompositeNode toStreamCompositeNode(String streamName, DataSchemaNode streamSchemaNode) {
+ val List<Node<?>> streamNodeValues = new ArrayList
+ val nameSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("name").head
+ streamNodeValues.add(NodeFactory.createImmutableSimpleNode(nameSchemaNode.QName, null, streamName))
+
+ val descriptionSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("description").head
+ streamNodeValues.add(NodeFactory.createImmutableSimpleNode(descriptionSchemaNode.QName, null, "DESCRIPTION_PLACEHOLDER"))
+
+ val replaySupportSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("replay-support").head
+ streamNodeValues.add(NodeFactory.createImmutableSimpleNode(replaySupportSchemaNode.QName, null, true))
+
+ val replayLogCreationTimeSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("replay-log-creation-time").head
+ streamNodeValues.add(NodeFactory.createImmutableSimpleNode(replayLogCreationTimeSchemaNode.QName, null, ""))
+
+ val eventsSchemaNode = (streamSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("events").head
+ streamNodeValues.add(NodeFactory.createImmutableSimpleNode(eventsSchemaNode.QName, null, ""))
+
+ return NodeFactory.createImmutableCompositeNode(streamSchemaNode.QName, null, streamNodeValues)
+ }
private def CompositeNode toModuleCompositeNode(Module module, DataSchemaNode moduleSchemaNode) {
val List<Node<?>> moduleNodeValues = new ArrayList
val nameSchemaNode = (moduleSchemaNode as DataNodeContainer).findInstanceDataChildrenByName("name").head
val restconfContainer = restconfGrouping.findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_RESTCONF_CONTAINER_SCHEMA_NODE).head
if (schemaNodeName == RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE) {
return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_OPERATIONS_CONTAINER_SCHEMA_NODE).head
- } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE) {
+ } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE) {
+ return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE).head
+ } else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE) {
+ val modules = (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAMS_CONTAINER_SCHEMA_NODE).head
+ return (modules as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_STREAM_LIST_SCHEMA_NODE).head
+ }else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE) {
return (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE).head
} else if (schemaNodeName == RESTCONF_MODULE_DRAFT02_MODULE_LIST_SCHEMA_NODE) {
val modules = (restconfContainer as DataNodeContainer).findInstanceDataChildrenByName(RESTCONF_MODULE_DRAFT02_MODULES_CONTAINER_SCHEMA_NODE).head
package org.opendaylight.controller.sal.streams.listeners;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
*/
public class Notificator {
- private static Map<String, ListenerAdapter> listenersByStreamName = new ConcurrentHashMap<>();
+ private static Map<String, ListenerAdapter> listenersByStreamName = new ConcurrentHashMap<>();
private static Map<InstanceIdentifier, ListenerAdapter> listenersByInstanceIdentifier = new ConcurrentHashMap<>();
private static final Lock lock = new ReentrantLock();
private Notificator() {
}
+ /**
+ * Returns list of all stream names
+ */
+ public static Set<String> getStreamNames() {
+ return listenersByStreamName.keySet();
+ }
+
+
/**
* Gets {@link ListenerAdapter} specified by stream name.
*
}
/**
- * Checks if listener has at least one subscriber. In case it has any, delete
+ * Checks if listener has at least one subscriber. In case it doesn't have any, delete
* listener.
*
* @param listener
package org.opendaylight.controller.sal.streams.websockets;
-import org.opendaylight.controller.sal.streams.listeners.Notificator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
-import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
+import org.opendaylight.controller.sal.streams.listeners.Notificator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* {@link WebSocketServer} is responsible to start and stop web socket server at
* {@link #PORT}.
if (nextEvent.isStartElement()) {
StartElement startElement = (StartElement) nextEvent;
if (startElement.getName().getLocalPart().equals("lf111")) {
- Iterator prefixes = startElement.getNamespaceContext().getPrefixes("augment:augment:module");
+ Iterator<?> prefixes = startElement.getNamespaceContext().getPrefixes("augment:augment:module");
while (prefixes.hasNext() && aaModulePrefix == null) {
String prefix = (String) prefixes.next();
if (nextEvent.isStartElement()) {
StartElement startElement = (StartElement) nextEvent;
if (startElement.getName().getLocalPart().equals("lf111")) {
- Iterator prefixes = startElement.getNamespaceContext().getPrefixes("augment:module:leaf:list");
+ Iterator<?> prefixes = startElement.getNamespaceContext().getPrefixes("augment:module:leaf:list");
while (prefixes.hasNext() && aModuleLfLstPrefix == null) {
String prefix = (String) prefixes.next();
MutableSimpleNode<?> lf111 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111", "augment:augment:module", "2014-01-17"),
lst11, instanceIdentifier,null,null);
-
-
+
+
lst11.getChildren().add(lf111);
lst11.init();
cont1.getChildren().add(lst11);
cont1.init();
-
+
cont.getChildren().add(cont1);
cont.init();
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.UriInfo;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
public class MediaTypesTest extends JerseyTest {
-
+
private static RestconfService restconfService;
private static String jsonData;
private static String xmlData;
-
+
@BeforeClass
public static void init() throws IOException {
restconfService = mock(RestconfService.class);
InputStream xmlStream = RestconfImplTest.class.getResourceAsStream("/parts/ietf-interfaces_interfaces.xml");
xmlData = TestUtils.getDocumentInPrintableForm(TestUtils.loadDocumentFrom(xmlStream));
}
-
+
@Override
protected Application configure() {
/* enable/disable Jersey logs to console */
JsonToCompositeNodeProvider.INSTANCE);
return resourceConfig;
}
-
+
@Test
public void testPostOperationsWithInputDataMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/operations/";
verify(restconfService, times(5)).invokeRpc(eq(uriPath), any(CompositeNode.class));
post(uri, null, MediaType.TEXT_XML, xmlData);
verify(restconfService, times(6)).invokeRpc(eq(uriPath), any(CompositeNode.class));
-
+
// negative tests
post(uri, MediaType.TEXT_PLAIN, MediaType.TEXT_XML, xmlData);
verify(restconfService, times(6)).invokeRpc(eq(uriPath), any(CompositeNode.class));
post(uri, MediaType.TEXT_XML, MediaType.TEXT_PLAIN, xmlData);
verify(restconfService, times(6)).invokeRpc(eq(uriPath), any(CompositeNode.class));
}
-
+
@Test
public void testGetConfigMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/config/";
verify(restconfService, times(4)).readConfigurationData(uriPath);
get(uri, MediaType.TEXT_XML);
verify(restconfService, times(5)).readConfigurationData(uriPath);
-
+
// negative tests
get(uri, MediaType.TEXT_PLAIN);
verify(restconfService, times(5)).readConfigurationData(uriPath);
}
-
+
@Test
public void testGetOperationalMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/operational/";
verify(restconfService, times(4)).readOperationalData(uriPath);
get(uri, MediaType.TEXT_XML);
verify(restconfService, times(5)).readOperationalData(uriPath);
-
+
// negative tests
get(uri, MediaType.TEXT_PLAIN);
verify(restconfService, times(5)).readOperationalData(uriPath);
}
-
+
@Test
public void testPutConfigMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/config/";
put(uri, "fooMediaType", MediaType.TEXT_XML, xmlData);
verify(restconfService, times(6)).updateConfigurationData(eq(uriPath), any(CompositeNode.class));
}
-
+
@Test
public void testPostConfigWithPathMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/config/";
post(uri, "fooMediaType", MediaType.TEXT_XML, xmlData);
verify(restconfService, times(6)).createConfigurationData(eq(uriPath), any(CompositeNode.class));
}
-
+
@Test
public void testPostConfigMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/config/";
post(uri, "fooMediaType", MediaType.TEXT_XML, xmlData);
verify(restconfService, times(6)).createConfigurationData(any(CompositeNode.class));
}
-
+
@Test
public void testDeleteConfigMediaTypes() throws UnsupportedEncodingException {
String uriPrefix = "/config/";
target(uri).request("fooMediaType").delete();
verify(restconfService, times(1)).deleteConfigurationData(uriPath);
}
-
+
private int get(String uri, String acceptMediaType) {
return target(uri).request(acceptMediaType).get().getStatus();
}
-
+
private int put(String uri, String acceptMediaType, String contentTypeMediaType, String data) {
if (acceptMediaType == null) {
return target(uri).request().put(Entity.entity(data, contentTypeMediaType)).getStatus();
}
return target(uri).request(acceptMediaType).put(Entity.entity(data, contentTypeMediaType)).getStatus();
}
-
+
private int post(String uri, String acceptMediaType, String contentTypeMediaType, String data) {
if (acceptMediaType == null) {
if (contentTypeMediaType == null || data == null) {
*/
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.BeforeClass;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class RestGetOperationTest extends JerseyTest {
response = target(uri).request("application/yang.api+xml").get();
validateModulesResponseXml(response);
}
+ // /streams/
+ @Test
+ public void getStreamsTest() throws UnsupportedEncodingException, FileNotFoundException {
+ ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
+
+ String uri = "/streams";
+
+ Response response = target(uri).request("application/yang.api+json").get();
+ String responseBody = response.readEntity(String.class);
+ assertNotNull(responseBody);
+ assertTrue(responseBody.contains("streams"));
+
+ response = target(uri).request("application/yang.api+xml").get();
+ responseBody = response.readEntity(String.class);
+ assertNotNull(responseBody);
+ assertTrue(responseBody.contains("<streams xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\"/>"));
+ }
// /modules/module
@Test
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
-import java.net.URLEncoder;
import java.text.ParseException;
import java.util.Set;
import java.util.concurrent.Future;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import com.google.common.base.Charsets;
-
public class RestPostOperationTest extends JerseyTest {
private static String xmlDataAbsolutePath;
*/
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
import java.io.FileNotFoundException;
import java.util.Set;
-
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class RestconfImplTest {
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutorService;
import org.opendaylight.controller.sal.binding.api.NotificationListener;
import org.opendaylight.controller.sal.binding.api.NotificationService;
import org.opendaylight.controller.sal.restconf.broker.tools.RemoteStreamTools;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.QName;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.SalRemoteService;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.restconf.client.api.RestconfClientContext;
import org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo;
import org.opendaylight.yangtools.yang.binding.Notification;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.SetMultimap;
-
public class NotificationServiceImpl implements NotificationService {
private final SalRemoteService salRemoteService;
private final RestconfClientContext restconfClientContext;
- private final Multimap<Class<? extends Notification>,NotificationListener<? extends Object>> listeners;
- private ExecutorService _executor;
-
public NotificationServiceImpl(RestconfClientContext restconfClienetContext){
this.restconfClientContext = restconfClienetContext;
this.salRemoteService = this.restconfClientContext.getRpcServiceContext(SalRemoteService.class).getRpcService();
-
- HashMultimap<Class<? extends Notification>,NotificationListener<? extends Object>> _create = HashMultimap.<Class<? extends Notification>, NotificationListener<? extends Object>>create();
- SetMultimap<Class<? extends Notification>,NotificationListener<? extends Object>> _synchronizedSetMultimap = Multimaps.<Class<? extends Notification>, NotificationListener<? extends Object>>synchronizedSetMultimap(_create);
- this.listeners = _synchronizedSetMultimap;
-
- }
- public ExecutorService getExecutor() {
- return this._executor;
- }
-
- public void setExecutor(final ExecutorService executor) {
- this._executor = executor;
- }
-
- @Override
- public <T extends Notification> void addNotificationListener(Class<T> notificationType, NotificationListener<T> listener) {
- this.listeners.put(notificationType, listener);
- }
-
- @Override
- public void addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Deprecated method. Use registerNotificationListener instead.");
- throw _unsupportedOperationException;
- }
-
- @Override
- public void removeNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
- UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException(
- "Deprecated method. Use RegisterNotificationListener returned value to close registration.");
- throw _unsupportedOperationException;
}
@Override
- public <T extends Notification> void removeNotificationListener(Class<T> notificationType, NotificationListener<T> listener) {
- this.listeners.remove(notificationType, listener);
- }
-
- @Override
- public <T extends Notification> Registration<NotificationListener<T>> registerNotificationListener(Class<T> notificationType, NotificationListener<T> listener) {
+ public <T extends Notification> ListenerRegistration<NotificationListener<T>> registerNotificationListener(Class<T> notificationType, NotificationListener<T> listener) {
//TODO implementation using sal-remote
List<QName> notifications = new ArrayList<QName>();
notifications.add(new QName(notificationType.toString()));
String notificationStreamName = RemoteStreamTools.createNotificationStream(salRemoteService, notifications);
final Map<String,EventStreamInfo> desiredEventStream = RemoteStreamTools.createEventStream(restconfClientContext, notificationStreamName);
RemoteNotificationListener remoteNotificationListener = new RemoteNotificationListener(listener);
- ListenerRegistration<?> listenerRegistration = restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName))).registerNotificationListener(remoteNotificationListener);
- return new SalNotificationRegistration<T>(listenerRegistration);
+
+ final ListenerRegistration<?> listenerRegistration = restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName)))
+ .registerNotificationListener(remoteNotificationListener);
+
+ return new AbstractListenerRegistration<NotificationListener<T>>(listener) {
+ @Override
+ protected void removeRegistration() {
+ listenerRegistration.close();
+ }
+ };
}
@Override
- public Registration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
+ public ListenerRegistration<org.opendaylight.yangtools.yang.binding.NotificationListener> registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {
//TODO implementation using sal-remote
String notificationStreamName = RemoteStreamTools.createNotificationStream(salRemoteService, null);
final Map<String,EventStreamInfo> desiredEventStream = RemoteStreamTools.createEventStream(restconfClientContext, notificationStreamName);
return restconfClientContext.getEventStreamContext(desiredEventStream.get(desiredEventStream.get(notificationStreamName))).registerNotificationListener(listener);
}
-
- private class SalNotificationRegistration<T extends Notification> implements Registration<NotificationListener<T>>{
- private final Registration<?> registration;
-
- public SalNotificationRegistration(ListenerRegistration<?> listenerRegistration){
- this.registration = listenerRegistration;
- }
-
- @Override
- public NotificationListener<T> getInstance() {
- return this.getInstance();
- }
-
- @Override
- public void close() throws Exception {
- this.registration.close();
- }
- }
-
-
}
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
+
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
return null;
}
- @Override
- public void putRuntimeData(InstanceIdentifier<? extends DataObject> path, DataObject data) {
-
- }
-
@Override
public void putOperationalData(InstanceIdentifier<? extends DataObject> path, DataObject data) {
}
- @Override
- public void removeRuntimeData(InstanceIdentifier<? extends DataObject> path) {
-
- }
-
@Override
public void removeOperationalData(InstanceIdentifier<? extends DataObject> path) {
package org.opendaylight.controller.sample.toaster.provider;
import java.util.Collections;
-
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.opendaylight.controller.config.yang.config.toaster_provider.impl.ToasterProviderRuntimeMXBean;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
-import org.opendaylight.controller.sal.common.util.Futures;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.DisplayString;
import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.MakeToastInput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.util.concurrent.Futures;
+
public class OpendaylightToaster implements ToasterData, ToasterService, ToasterProviderRuntimeMXBean {
private static final Logger log = LoggerFactory.getLogger(OpendaylightToaster.class);
private static final DisplayString toasterManufacturer = new DisplayString("Opendaylight");
private static final DisplayString toasterModelNumber = new DisplayString("Model 1 - Binding Aware");
- private ToasterStatus toasterStatus;
+ private final ToasterStatus toasterStatus;
private NotificationProviderService notificationProvider;
private final ExecutorService executor;
currentTask.cancel(true);
ToastDoneBuilder toastDone = new ToastDoneBuilder();
toastDone.setToastStatus(ToastStatus.Cancelled);
- notificationProvider.notify(toastDone.build());
+ notificationProvider.publish(toastDone.build());
}
public void setNotificationProvider(NotificationProviderService salService) {
ToastDoneBuilder notifyBuilder = new ToastDoneBuilder();
notifyBuilder.setToastStatus(ToastStatus.Done);
- notificationProvider.notify(notifyBuilder.build());
+ notificationProvider.publish(notifyBuilder.build());
log.trace("Toast Done");
logToastInput(toastRequest);
currentTask = null;
package org.opendaylight.controller.netconf.confignetconfconnector.operations;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
-import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
-public abstract class AbstractConfigNetconfOperation extends AbstractNetconfOperation {
+public abstract class AbstractConfigNetconfOperation extends AbstractLastNetconfOperation {
protected final ConfigRegistryClient configRegistryClient;
super(netconfSessionIdForReporting);
this.configRegistryClient = configRegistryClient;
}
-
- @Override
- protected HandlingPriority canHandle(String operationName, String operationNamespace) {
- // TODO check namespace
- return operationName.equals(getOperationName()) ? HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY
- : HandlingPriority.CANNOT_HANDLE;
- }
-
- protected abstract String getOperationName();
-
- @Override
- protected Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
- throws NetconfDocumentedException {
- return handle(document, operationElement);
- }
-
- protected abstract Element handle(Document document, XmlElement operationElement) throws NetconfDocumentedException;
}
package org.opendaylight.controller.netconf.confignetconfconnector.operations;
+import java.util.HashMap;
+import java.util.Map;
+
import org.opendaylight.controller.config.api.ConflictingVersionException;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.util.HashMap;
-import java.util.Map;
-
public class Commit extends AbstractConfigNetconfOperation {
private static final Logger logger = LoggerFactory.getLogger(Commit.class);
}
@Override
- protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
checkXml(xml);
CommitStatus status;
package org.opendaylight.controller.netconf.confignetconfconnector.operations;
+import java.util.HashMap;
+import java.util.Map;
+
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.util.HashMap;
-import java.util.Map;
-
public class DiscardChanges extends AbstractConfigNetconfOperation {
public static final String DISCARD = "discard-changes";
}
@Override
- protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
try {
fromXml(xml);
} catch (final IllegalArgumentException e) {
package org.opendaylight.controller.netconf.confignetconfconnector.operations;
-import com.google.common.base.Preconditions;
+import java.util.HashMap;
+import java.util.Map;
+
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.util.HashMap;
-import java.util.Map;
+import com.google.common.base.Preconditions;
public class Validate extends AbstractConfigNetconfOperation {
}
@Override
- protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
try {
checkXml(xml);
} catch (IllegalStateException e) {
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
public class EditConfig extends AbstractConfigNetconfOperation {
}
@Override
- protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
EditConfigXmlParser.EditConfigExecution editConfigExecution;
Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot);
package org.opendaylight.controller.netconf.confignetconfconnector.operations.get;
-import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.collect.Maps;
public class Get extends AbstractConfigNetconfOperation {
}
@Override
- protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
try {
checkXml(xml);
} catch (final IllegalArgumentException e) {
package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig;
-import com.google.common.base.Optional;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.util.ConfigTransactionClient;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.base.Optional;
public class GetConfig extends AbstractConfigNetconfOperation {
}
@Override
- public Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ public Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
Datastore source;
try {
source = fromXml(xml);
package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import java.util.Map;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
+
import org.opendaylight.controller.config.util.ConfigRegistryClient;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import javax.management.ObjectName;
-import javax.management.openmbean.OpenType;
-import java.util.Map;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
public class RuntimeRpc extends AbstractConfigNetconfOperation {
// Either allow List of Elements to be returned from NetconfOperation or
// pass reference to parent output xml element for netconf operations to
// append result(s) on their own
- Element tempParent = doc.createElementNS(XmlNetconfConstants.RFC4741_TARGET_NAMESPACE, "output");
+ Element tempParent = doc.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, "output");
new ObjectXmlWriter().prepareWritingStrategy(elementName, returnType, doc).writeElement(tempParent, namespace, mappedAttributeOpt.get());
XmlElement xmlElement = XmlElement.fromDomElement(tempParent);
}
@Override
- protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
// TODO exception handling
// TODO check for namespaces and unknown elements
package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import org.opendaylight.controller.config.api.LookupRegistry;
import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
import org.opendaylight.controller.config.yang.store.api.YangStoreException;
import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.yangtools.yang.model.api.Module;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
/**
* Manages life cycle of {@link YangStoreSnapshot}.
return operationProvider.getOperations();
}
- @Override
- public Set<NetconfOperationFilter> getFilters() {
- return Collections.emptySet();
- }
-
private static Set<Capability> setupCapabilities(YangStoreSnapshot yangStoreSnapshot) {
Set<Capability> capabilities = new HashSet<>();
// [RFC6241] 8.3. Candidate Configuration Capability
package org.opendaylight.controller.netconf.confignetconfconnector;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
+
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Ignore;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
public class NetconfMappingTest extends AbstractConfigTest {
YangStoreSnapshot yangStoreSnapshot;
@Mock
NetconfOperationRouter netconfOperationRouter;
+ @Mock
+ NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
private TransactionProvider transactionProvider;
MockitoAnnotations.initMocks(this);
doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap();
doReturn(getModules()).when(this.yangStoreSnapshot).getModules();
+ doNothing().when(netconfOperationServiceSnapshot).close();
this.factory = new NetconfTestImplModuleFactory();
this.factory2 = new DepTestImplModuleFactory();
assertEquals(expectedResult, responseFromCandidate);
edit("netconfMessages/editConfig_none.xml");
- doNothing().when(netconfOperationRouter).close();
closeSession();
- verify(netconfOperationRouter).close();
+ verify(netconfOperationServiceSnapshot).close();
verifyNoMoreInteractions(netconfOperationRouter);
+ verifyNoMoreInteractions(netconfOperationServiceSnapshot);
}
private void checkBigDecimal(Element response) {
private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException,
IOException {
- DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID);
+ DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID, netconfOperationServiceSnapshot);
executeOp(closeOp, "netconfMessages/closeSession.xml");
}
Preconditions.checkState(priority != HandlingPriority.CANNOT_HANDLE);
- final Document response = op.handle(request, netconfOperationRouter);
+ final Document response = op.handle(request, NetconfOperationRouterImpl.EXECUTION_TERMINATION_POINT);
logger.debug("Got response\n{}", XmlUtil.toString(response));
return response.getDocumentElement();
}
public void test() throws Exception {
final XmlElement xml = XmlElement.fromString("<abc></abc>");
final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
- validate.handle(null, xml);
+ validate.handleWithNoSubsequentOperations(null, xml);
}
@Test(expected = NetconfDocumentedException.class)
final XmlElement xml = XmlElement.fromString("<validate xmlns=\""
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 + "\"/>");
final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
- validate.handle(null, xml);
+ validate.handleWithNoSubsequentOperations(null, xml);
}
@Test(expected = NetconfDocumentedException.class)
public void testNoNamespace() throws Exception {
final XmlElement xml = XmlElement.fromString("<validate/>");
final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
- validate.handle(null, xml);
+ validate.handleWithNoSubsequentOperations(null, xml);
}
@Test(expected = NetconfDocumentedException.class)
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0
+ "\"><source><running></running></source></validate>");
final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
- validate.handle(null, xml);
+ validate.handleWithNoSubsequentOperations(null, xml);
}
@Test(expected = NetconfDocumentedException.class)
final TransactionProvider transactionProvider = mock(TransactionProvider.class);
doThrow(IllegalStateException.class).when(transactionProvider).validateTransaction();
final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING);
- validate.handle(null, xml);
+ validate.handleWithNoSubsequentOperations(null, xml);
}
@Test(expected = NetconfDocumentedException.class)
final TransactionProvider transactionProvider = mock(TransactionProvider.class);
doThrow(ValidationException.class).when(transactionProvider).validateTransaction();
final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING);
- validate.handle(null, xml);
+ validate.handleWithNoSubsequentOperations(null, xml);
}
@Test
final Element okElement = XmlUtil.readXmlToElement("<ok/>");
doNothing().when(transactionProvider).validateTransaction();
final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING);
- Element ok = validate.handle(XmlUtil.newDocument(), xml);
+ Element ok = validate.handleWithNoSubsequentOperations(XmlUtil.newDocument(), xml);
assertEquals(XmlUtil.toString(okElement), XmlUtil.toString(ok));
}
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.api.NetconfSessionListener;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionListener.class);
private final SessionMonitoringService monitoringService;
- private final NetconfOperationRouterImpl operationRouter;
+ private final NetconfOperationRouter operationRouter;
- public NetconfServerSessionListener(NetconfOperationRouterImpl operationRouter, SessionMonitoringService monitoringService) {
+ public NetconfServerSessionListener(NetconfOperationRouter operationRouter, SessionMonitoringService monitoringService) {
this.operationRouter = operationRouter;
this.monitoringService = monitoringService;
}
package org.opendaylight.controller.netconf.impl;
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot);
- NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(
+ NetconfOperationRouter operationRouter = NetconfOperationRouterImpl.createOperationRouter(
netconfOperationServiceSnapshot, capabilityProvider,
commitNotifier);
package org.opendaylight.controller.netconf.impl.mapping.operations;
+import java.util.Collections;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
+import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-public class DefaultCloseSession extends AbstractNetconfOperation {
+public class DefaultCloseSession extends AbstractSingletonNetconfOperation {
public static final String CLOSE_SESSION = "close-session";
+ private final AutoCloseable sessionResources;
- public DefaultCloseSession(String netconfSessionIdForReporting) {
+ public DefaultCloseSession(String netconfSessionIdForReporting, AutoCloseable sessionResources) {
super(netconfSessionIdForReporting);
+ this.sessionResources = sessionResources;
}
@Override
- protected HandlingPriority canHandle(String operationName, String netconfOperationNamespace) {
- if (operationName.equals(CLOSE_SESSION) == false)
- return HandlingPriority.CANNOT_HANDLE;
- if (netconfOperationNamespace.equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)
- return HandlingPriority.CANNOT_HANDLE;
-
- return HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
+ protected String getOperationName() {
+ return CLOSE_SESSION;
}
/**
* instances
*/
@Override
- protected Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement)
throws NetconfDocumentedException {
- opRouter.close();
+ try {
+ sessionResources.close();
+ } catch (Exception e) {
+ throw new NetconfDocumentedException("Unable to properly close session "
+ + getNetconfSessionIdForReporting(), NetconfDocumentedException.ErrorType.application,
+ NetconfDocumentedException.ErrorTag.operation_failed,
+ NetconfDocumentedException.ErrorSeverity.error, Collections.singletonMap(
+ NetconfDocumentedException.ErrorSeverity.error.toString(), e.getMessage()));
+ }
return document.createElement(XmlNetconfConstants.OK);
}
}
import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
-public class DefaultCommit implements NetconfOperationFilter {
+public class DefaultCommit extends AbstractNetconfOperation {
private static final Logger logger = LoggerFactory.getLogger(DefaultCommit.class);
private final DefaultCommitNotificationProducer notificationProducer;
private final CapabilityProvider cap;
- private final String netconfSessionIdForReporting;
+ private final NetconfOperationRouter operationRouter;
public DefaultCommit(DefaultCommitNotificationProducer notifier, CapabilityProvider cap,
- String netconfSessionIdForReporting) {
+ String netconfSessionIdForReporting, NetconfOperationRouter netconfOperationRouter) {
+ super(netconfSessionIdForReporting);
this.notificationProducer = notifier;
this.cap = cap;
- this.netconfSessionIdForReporting = netconfSessionIdForReporting;
+ this.operationRouter = netconfOperationRouter;
this.getConfigMessage = loadGetConfigMessage();
}
}
@Override
- public Document doFilter(Document message, NetconfOperationRouter operationRouter,
- NetconfOperationFilterChain filterChain) throws NetconfDocumentedException {
- OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(message);
- if (canHandle(operationNameAndNamespace)) {
- if (isCommitWithoutNotification(message)) {
- message = removePersisterAttributes(message);
- logger.debug("Skipping commit notification");
- // fall back to filter chain
- } else {
- Document innerResult = filterChain.execute(message, operationRouter);
- Element cfgSnapshot = getConfigSnapshot(operationRouter);
- logger.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
- notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
- return innerResult;
- }
- }
- return filterChain.execute(message, operationRouter);
+ protected String getOperationName() {
+ return XmlNetconfConstants.COMMIT;
}
@Override
- public int getSortingOrder() {
- return 0;
+ public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+ Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
+ "Subsequent netconf operation expected by %s", this);
+
+ if (isCommitWithoutNotification(requestMessage)) {
+ logger.debug("Skipping commit notification");
+ } else {
+ // Send commit notification if commit was not issued by persister
+ requestMessage = removePersisterAttributes(requestMessage);
+ Element cfgSnapshot = getConfigSnapshot(operationRouter);
+ logger.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
+ notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
+ }
+
+ return subsequentOperation.execute(requestMessage);
}
@Override
- public int compareTo(NetconfOperationFilter o) {
- return Integer.compare(getSortingOrder(), o.getSortingOrder());
+ protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+ throw new UnsupportedOperationException("Never gets called");
}
- private boolean canHandle(OperationNameAndNamespace operationNameAndNamespace) {
- if (operationNameAndNamespace.getOperationName().equals("commit") == false)
- return false;
- return operationNameAndNamespace.getNamespace().equals(
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ @Override
+ protected HandlingPriority getHandlingPriority() {
+ return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1);
}
private Document removePersisterAttributes(Document message) {
return dataElement.getDomElement();
}
- @Override
- public String toString() {
- return "DefaultCommit{" + netconfSessionIdForReporting + '}';
- }
}
import java.util.Map;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import com.google.common.base.Optional;
import com.google.common.collect.Maps;
-public final class DefaultGetSchema extends AbstractNetconfOperation {
+public final class DefaultGetSchema extends AbstractLastNetconfOperation {
public static final String GET_SCHEMA = "get-schema";
public static final String IDENTIFIER = "identifier";
public static final String VERSION = "version";
}
@Override
- protected HandlingPriority canHandle(String netconfOperationName, String namespace) {
- if (netconfOperationName.equals("get-schema") == false)
- return HandlingPriority.CANNOT_HANDLE;
- if (namespace.equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING) == false)
- return HandlingPriority.CANNOT_HANDLE;
+ protected String getOperationName() {
+ return GET_SCHEMA;
+ }
- return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
+ @Override
+ protected String getOperationNamespace() {
+ return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING;
}
@Override
- protected Element handle(Document document, XmlElement xml, NetconfOperationRouter router)
- throws NetconfDocumentedException {
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
GetSchemaEntry entry;
try {
*/\r
package org.opendaylight.controller.netconf.impl.mapping.operations;\r
\r
-import org.opendaylight.controller.netconf.api.NetconfSession;\r
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
import org.w3c.dom.Document;\r
import org.w3c.dom.Element;\r
\r
-public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+public class DefaultStartExi extends AbstractSingletonNetconfOperation implements DefaultNetconfOperation {\r
\r
public static final String START_EXI = "start-exi";\r
\r
}\r
\r
@Override\r
- protected HandlingPriority canHandle(String operationName,\r
- String netconfOperationNamespace) {\r
- if (operationName.equals(START_EXI) == false)\r
- return HandlingPriority.CANNOT_HANDLE;\r
- if (netconfOperationNamespace\r
- .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
- return HandlingPriority.CANNOT_HANDLE;\r
-\r
- return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+ protected String getOperationName() {\r
+ return START_EXI;\r
}\r
\r
@Override\r
- protected Element handle(Document document, XmlElement operationElement,\r
- NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException {\r
\r
\r
Element getSchemaResult = document\r
*/\r
package org.opendaylight.controller.netconf.impl.mapping.operations;\r
\r
-import org.opendaylight.controller.netconf.api.NetconfSession;\r
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
import org.w3c.dom.Document;\r
import org.w3c.dom.Element;\r
\r
-public class DefaultStopExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+public class DefaultStopExi extends AbstractSingletonNetconfOperation implements DefaultNetconfOperation {\r
\r
public static final String STOP_EXI = "stop-exi";\r
private NetconfSession netconfSession;\r
}\r
\r
@Override\r
- protected HandlingPriority canHandle(String operationName,\r
- String netconfOperationNamespace) {\r
- if (operationName.equals(STOP_EXI) == false)\r
- return HandlingPriority.CANNOT_HANDLE;\r
- if (netconfOperationNamespace\r
- .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
- return HandlingPriority.CANNOT_HANDLE;\r
-\r
- return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+ protected String getOperationName() {\r
+ return STOP_EXI;\r
}\r
\r
@Override\r
- protected Element handle(Document document, XmlElement operationElement,\r
- NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+ protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement)\r
+ throws NetconfDocumentedException {\r
throw new UnsupportedOperationException("Not implemented");\r
/*\r
netconfSession.remove(ExiDecoderHandler.class);\r
import java.util.Collections;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import java.util.TreeSet;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.slf4j.Logger;
private static final Logger logger = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
+ private Set<NetconfOperation> allNetconfOperations;
- private final Set<NetconfOperation> allNetconfOperations;
- private final TreeSet<NetconfOperationFilter> allSortedFilters;
-
- private final CapabilityProvider capabilityProvider;
+ private NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
+ this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
+ }
+ private void initNetconfOperations(Set<NetconfOperation> allOperations) {
+ allNetconfOperations = allOperations;
+ }
- public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
- CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+ /**
+ * Factory method to produce instance of NetconfOperationRouter
+ */
+ public static NetconfOperationRouter createOperationRouter(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
+ CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+ NetconfOperationRouterImpl router = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot);
- this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot);
- this.capabilityProvider = Preconditions.checkNotNull(capabilityProvider);
+ Preconditions.checkNotNull(netconfOperationServiceSnapshot);
+ Preconditions.checkNotNull(capabilityProvider);
final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting();
+
final Set<NetconfOperation> defaultNetconfOperations = Sets.newHashSet();
defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, sessionId));
- defaultNetconfOperations.add(new DefaultCloseSession(sessionId));
+ defaultNetconfOperations.add(new DefaultCloseSession(sessionId, router));
defaultNetconfOperations.add(new DefaultStartExi(sessionId));
defaultNetconfOperations.add(new DefaultStopExi(sessionId));
+ defaultNetconfOperations.add(new DefaultCommit(commitNotifier, capabilityProvider, sessionId, router));
- allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
+ router.initNetconfOperations(getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot));
- DefaultCommit defaultCommit = new DefaultCommit(commitNotifier, capabilityProvider, sessionId);
- Set<NetconfOperationFilter> defaultFilters = Sets.<NetconfOperationFilter> newHashSet(defaultCommit);
- allSortedFilters = getAllNetconfFilters(defaultFilters, netconfOperationServiceSnapshot);
+ return router;
}
private static Set<NetconfOperation> getAllNetconfOperations(Set<NetconfOperation> defaultNetconfOperations,
return Collections.unmodifiableSet(result);
}
- private static TreeSet<NetconfOperationFilter> getAllNetconfFilters(Set<NetconfOperationFilter> defaultFilters,
- NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
- TreeSet<NetconfOperationFilter> result = new TreeSet<>(defaultFilters);
- for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
- final Set<NetconfOperationFilter> filtersFromService = netconfOperationService.getFilters();
- for (NetconfOperationFilter filter : filtersFromService) {
- Preconditions.checkState(result.contains(filter) == false,
- "Filter %s already present, all filters so far: %s", filter, result);
- result.add(filter);
- }
- }
- return result;
- }
-
- public CapabilityProvider getCapabilityProvider() {
- return capabilityProvider;
- }
-
@Override
public synchronized Document onNetconfMessage(Document message,
NetconfSession session) throws NetconfDocumentedException {
- NetconfOperationExecution netconfOperationExecution;
+ Preconditions.checkNotNull(allNetconfOperations, "Operation router was not initialized properly");
+ NetconfOperationExecution netconfOperationExecution;
String messageAsString = XmlUtil.toString(message);
try {
}
}
+ @Override
+ public void close() {
+ netconfOperationServiceSnapshot.close();
+ }
+
private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException {
logger.error(s, e);
NetconfDocumentedException.ErrorSeverity.error, info);
}
- private Document executeOperationWithHighestPriority(Document message, NetconfOperationExecution netconfOperationExecution, String messageAsString) throws NetconfDocumentedException {
- logger.debug("Forwarding netconf message {} to {}", messageAsString,
- netconfOperationExecution.operationWithHighestPriority);
-
- final LinkedList<NetconfOperationFilterChain> chain = new LinkedList<>();
- chain.push(netconfOperationExecution);
-
- for (Iterator<NetconfOperationFilter> it = allSortedFilters.descendingIterator(); it.hasNext();) {
- final NetconfOperationFilter filter = it.next();
- final NetconfOperationFilterChain prevItem = chain.getFirst();
- NetconfOperationFilterChain currentItem = new NetconfOperationFilterChain() {
- @Override
- public Document execute(Document message, NetconfOperationRouter operationRouter)
- throws NetconfDocumentedException {
- logger.trace("Entering {}", filter);
- return filter.doFilter(message, operationRouter, prevItem);
- }
- };
- chain.push(currentItem);
- }
- return chain.getFirst().execute(message, this);
+ private Document executeOperationWithHighestPriority(Document message,
+ NetconfOperationExecution netconfOperationExecution, String messageAsString)
+ throws NetconfDocumentedException {
+ logger.debug("Forwarding netconf message {} to {}", messageAsString, netconfOperationExecution.netconfOperation);
+ return netconfOperationExecution.execute(message);
}
private NetconfOperationExecution getNetconfOperationWithHighestPriority(
Document message, NetconfSession session) {
- TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
+ TreeMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
message, session);
- Preconditions.checkArgument(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
- NetconfOperation.class.getName(), XmlUtil.toString(message));
-
- HandlingPriority highestFoundPriority = sortedPriority.lastKey();
-
- int netconfOperationsWithHighestPriority = sortedPriority.get(highestFoundPriority).size();
-
- Preconditions.checkState(netconfOperationsWithHighestPriority == 1,
- "Multiple %s available to handle message %s", NetconfOperation.class.getName(), message);
+ Preconditions.checkArgument(sortedByPriority.isEmpty() == false,
+ "No %s available to handleWithNoSubsequentOperations message %s", NetconfOperation.class.getName(),
+ XmlUtil.toString(message));
- return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
+ return NetconfOperationExecution.createExecutionChain(sortedByPriority, sortedByPriority.lastKey());
}
- private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
- Document message, NetconfSession session) {
- TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
+ private TreeMap<HandlingPriority, NetconfOperation> getSortedNetconfOperationsWithCanHandle(Document message,
+ NetconfSession session) {
+ TreeMap<HandlingPriority, NetconfOperation> sortedPriority = Maps.newTreeMap();
for (NetconfOperation netconfOperation : allNetconfOperations) {
final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
if (netconfOperation instanceof DefaultNetconfOperation) {
- ((DefaultNetconfOperation) netconfOperation)
- .setNetconfSession(session);
+ ((DefaultNetconfOperation) netconfOperation).setNetconfSession(session);
}
if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
- Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
- netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
- netconfOperations.add(netconfOperation);
+
+ Preconditions.checkState(sortedPriority.containsKey(handlingPriority) == false,
+ "Multiple %s available to handle message %s with priority %s",
+ NetconfOperation.class.getName(), message, handlingPriority);
+ sortedPriority.put(handlingPriority, netconfOperation);
}
}
return sortedPriority;
}
- private Set<NetconfOperation> checkIfNoOperationsOnPriority(
- TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority, HandlingPriority handlingPriority,
- Set<NetconfOperation> netconfOperations) {
- if (netconfOperations == null) {
- netconfOperations = Sets.newHashSet();
- sortedPriority.put(handlingPriority, netconfOperations);
+ public static final NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() {
+ @Override
+ public boolean isExecutionTermination() {
+ return true;
}
- return netconfOperations;
- }
- @Override
- public void close() {
- netconfOperationServiceSnapshot.close();
- }
+ @Override
+ public Document execute(Document requestMessage) throws NetconfDocumentedException {
+ throw new IllegalStateException("This execution represents the termination point in operation execution and cannot be executed itself");
+ }
+ };
+
+ private static class NetconfOperationExecution implements NetconfOperationChainedExecution {
+ private final NetconfOperation netconfOperation;
+ private NetconfOperationChainedExecution subsequentExecution;
- private class NetconfOperationExecution implements NetconfOperationFilterChain {
- private final NetconfOperation operationWithHighestPriority;
+ private NetconfOperationExecution(NetconfOperation netconfOperation, NetconfOperationChainedExecution subsequentExecution) {
+ this.netconfOperation = netconfOperation;
+ this.subsequentExecution = subsequentExecution;
+ }
- public NetconfOperationExecution(TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority,
- HandlingPriority highestFoundPriority) {
- operationWithHighestPriority = sortedPriority.get(highestFoundPriority).iterator().next();
- sortedPriority.remove(highestFoundPriority);
+ @Override
+ public boolean isExecutionTermination() {
+ return false;
}
@Override
- public Document execute(Document message, NetconfOperationRouter router) throws NetconfDocumentedException {
- return operationWithHighestPriority.handle(message, router);
+ public Document execute(Document message) throws NetconfDocumentedException {
+ return netconfOperation.handle(message, subsequentExecution);
+ }
+
+ public static NetconfOperationExecution createExecutionChain(
+ TreeMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
+ NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority);
+ HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority);
+
+ NetconfOperationChainedExecution subsequentExecution = null;
+
+ if (subsequentHandlingPriority != null) {
+ subsequentExecution = createExecutionChain(sortedByPriority, subsequentHandlingPriority);
+ } else {
+ subsequentExecution = EXECUTION_TERMINATION_POINT;
+ }
+
+ return new NetconfOperationExecution(netconfOperation, subsequentExecution);
}
}
return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
+ '}';
}
-
-
-
}
package org.opendaylight.controller.netconf.impl;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.client.NetconfClient;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import javax.management.ObjectName;
-import java.io.DataOutputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
public class ConcurrentClientsTest {
}
@Override
- public Document handle(Document message, NetconfOperationRouter operationRouter)
- throws NetconfDocumentedException {
+ public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
try {
return XmlUtil.readXmlToDocument("<test/>");
} catch (Exception e) {
});
}
- @Override
- public Set<NetconfOperationFilter> getFilters() {
- return Collections.emptySet();
- }
-
@Override
public void close() {
}
package org.opendaylight.controller.netconf.mapping.api;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
public class HandlingPriority implements Comparable<HandlingPriority> {
* @return priority number or Optional.absent otherwise
*/
public Optional<Integer> getPriority() {
- return Optional.of(priority).or(Optional.<Integer> absent());
+ return Optional.fromNullable(priority);
+ }
+
+ public HandlingPriority increasePriority(int priorityIncrease) {
+ Preconditions.checkState(priority!=null, "Unable to increase priority for %s", this);
+ Preconditions.checkArgument(priorityIncrease > 0, "Negative increase");
+ Preconditions.checkArgument(Long.valueOf(priority) + priorityIncrease < Integer.MAX_VALUE,
+ "Resulting priority cannot be higher than %s", Integer.MAX_VALUE);
+ return getHandlingPriority(priority + priorityIncrease);
}
@Override
package org.opendaylight.controller.netconf.mapping.api;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.w3c.dom.Document;
+/**
+ * NetconfOperation handles netconf requests. Multiple operations might be
+ * capable of handling one request at the same time. In such case, these
+ * operations are chained (ordered by HandlingPriority returned by canHandle
+ * method) and executed.
+ *
+ * Operation can be declared as singleton or last in chain (see abstract
+ * implementations in netconf-util). If the operation is not singleton or last,
+ * it is responsible for the execution of subsequent operation and for merging
+ * the results.
+ *
+ */
public interface NetconfOperation {
- HandlingPriority canHandle(Document message);
+ /**
+ * Singleton operations should return
+ * HandlingPriority.HANDLE_WITH_MAX_PRIORITY, last operations
+ * HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.
+ *
+ * @param requestMessage
+ * @return
+ */
+ HandlingPriority canHandle(Document requestMessage);
- Document handle(Document message, NetconfOperationRouter operationRouter) throws NetconfDocumentedException;
+ /**
+ * Execute current netconf operation and trigger execution of subsequent
+ * operations. subsequentOperation parameter will provide information, if
+ * current operation is the termination point in execution. In case of
+ * last/singleton operation, subsequentOperation must indicate termination
+ * point.
+ *
+ * @param requestMessage
+ * @param subsequentOperation
+ * execution of subsequent netconf operation
+ * @return
+ * @throws NetconfDocumentedException
+ */
+ Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+ throws NetconfDocumentedException;
}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.controller.netconf.mapping.api;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.w3c.dom.Document;
+
+/**
+ * Single link in netconf operation execution chain.
+ * Wraps the execution of a single netconf operation.
+ */
+public interface NetconfOperationChainedExecution {
+
+ /**
+ * @return true if this is termination point in operation execution, false
+ * if there is a subsequent operation present that needs to be
+ * executed
+ */
+ boolean isExecutionTermination();
+
+ /**
+ * Do not execute if this is termination point
+ */
+ Document execute(Document requestMessage) throws NetconfDocumentedException;
+}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.mapping.api;
-
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.w3c.dom.Document;
-
-/**
- * Filters wrap each netconf operation, if there is one found. Filters are
- * sorted and applied from the greatest to smallest sorting order.
- */
-public interface NetconfOperationFilter extends Comparable<NetconfOperationFilter> {
-
- Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain)
- throws NetconfDocumentedException;
-
- int getSortingOrder();
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 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.controller.netconf.mapping.api;
-
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.w3c.dom.Document;
-
-public interface NetconfOperationFilterChain {
-
- Document execute(Document message, NetconfOperationRouter operationRouter) throws NetconfDocumentedException;
-
-}
*/
Set<NetconfOperation> getNetconfOperations();
- Set<NetconfOperationFilter> getFilters();
-
/**
* Called when netconf session is destroyed.
*/
*/
package org.opendaylight.controller.netconf.monitoring;
-import com.google.common.collect.Maps;
+import java.util.Map;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.monitoring.xml.JaxBSerializer;
import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.util.Map;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
-public class Get implements NetconfOperationFilter {
+public class Get extends AbstractNetconfOperation {
private static final Logger logger = LoggerFactory.getLogger(Get.class);
private final NetconfMonitoringService netconfMonitor;
public Get(NetconfMonitoringService netconfMonitor) {
+ super(MonitoringConstants.MODULE_NAME);
this.netconfMonitor = netconfMonitor;
}
- @Override
- public Document doFilter(Document message, NetconfOperationRouter operationRouter,
- NetconfOperationFilterChain filterChain) throws NetconfDocumentedException {
- AbstractNetconfOperation.OperationNameAndNamespace operationNameAndNamespace = new AbstractNetconfOperation.OperationNameAndNamespace(
- message);
- if (canHandle(operationNameAndNamespace)) {
- return handle(message, operationRouter, filterChain);
+ private Element getPlaceholder(Document innerResult) {
+ try {
+ XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
+ XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+ return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
+ } catch (RuntimeException e) {
+ throw new IllegalArgumentException(String.format(
+ "Input xml in wrong format, Expecting root element %s with child element %s, but was %s",
+ XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY,
+ XmlUtil.toString(innerResult.getDocumentElement())), e);
}
- return filterChain.execute(message, operationRouter);
}
- private Document handle(Document message, NetconfOperationRouter operationRouter,
- NetconfOperationFilterChain filterChain) throws NetconfDocumentedException {
+ @Override
+ protected String getOperationName() {
+ return XmlNetconfConstants.GET;
+ }
+
+ @Override
+ protected HandlingPriority getHandlingPriority() {
+ return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1);
+ }
+
+ @Override
+ public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+ throws NetconfDocumentedException {
+ Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
+ "Subsequent netconf operation expected by %s", this);
+
try {
- Document innerResult = filterChain.execute(message, operationRouter);
+ Document innerResult = subsequentOperation.execute(requestMessage);
NetconfState netconfMonitoring = new NetconfState(netconfMonitor);
Element monitoringXmlElement = new JaxBSerializer().toXml(netconfMonitoring);
}
}
- private Element getPlaceholder(Document innerResult) {
- try {
- XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
- XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
- return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
- } catch (RuntimeException e) {
- throw new IllegalArgumentException(String.format(
- "Input xml in wrong format, Expecting root element %s with child element %s, but was %s",
- XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY,
- XmlUtil.toString(innerResult.getDocumentElement())), e);
- }
- }
-
- private boolean canHandle(AbstractNetconfOperation.OperationNameAndNamespace operationNameAndNamespace) {
- if (operationNameAndNamespace.getOperationName().equals(XmlNetconfConstants.GET) == false)
- return false;
- return operationNameAndNamespace.getNamespace().equals(
- XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
- }
-
@Override
- public int getSortingOrder() {
- // FIXME filters for different operations cannot have same order
- return 1;
+ protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
+ throws NetconfDocumentedException {
+ throw new UnsupportedOperationException("Never gets called");
}
-
- @Override
- public int compareTo(NetconfOperationFilter o) {
- return Integer.compare(getSortingOrder(), o.getSortingOrder());
- }
-
}
*/
package org.opendaylight.controller.netconf.monitoring.osgi;
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.controller.netconf.mapping.api.Capability;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.controller.netconf.monitoring.Get;
import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
public class NetconfMonitoringOperationService implements NetconfOperationService {
@Override
public Set<NetconfOperation> getNetconfOperations() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<NetconfOperationFilter> getFilters() {
- return Sets.<NetconfOperationFilter>newHashSet(new Get(monitor));
+ return Sets.<NetconfOperation>newHashSet(new Get(monitor));
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2013 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.controller.netconf.util.mapping;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractLastNetconfOperation extends AbstractNetconfOperation {
+
+ protected AbstractLastNetconfOperation(String netconfSessionIdForReporting) {
+ super(netconfSessionIdForReporting);
+ }
+
+ @Override
+ protected Element handle(Document document, XmlElement operationElement,
+ NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+ Preconditions.checkArgument(subsequentOperation.isExecutionTermination(),
+ "No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation);
+
+ return handleWithNoSubsequentOperations(document, operationElement);
+ }
+
+ @Override
+ protected HandlingPriority getHandlingPriority() {
+ return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
+ }
+
+ protected abstract Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException;
+}
import java.util.Map;
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
}
- protected abstract HandlingPriority canHandle(String operationName, String netconfOperationNamespace);
+ protected HandlingPriority canHandle(String operationName, String operationNamespace) {
+ return operationName.equals(getOperationName()) && operationNamespace.equals(getOperationNamespace())
+ ? getHandlingPriority()
+ : HandlingPriority.CANNOT_HANDLE;
+ }
+
+ protected HandlingPriority getHandlingPriority() {
+ return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
+ }
+
+ protected String getOperationNamespace() {
+ return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+ }
+
+ protected abstract String getOperationName();
@Override
- public final Document handle(Document message, NetconfOperationRouter opRouter) throws NetconfDocumentedException {
+ public Document handle(Document requestMessage,
+ NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
- XmlElement requestElement = getRequestElementWithCheck(message);
+ XmlElement requestElement = getRequestElementWithCheck(requestMessage);
Document document = XmlUtil.newDocument();
XmlElement operationElement = requestElement.getOnlyChildElement();
Map<String, Attr> attributes = requestElement.getAttributes();
- Element response = handle(document, operationElement, opRouter);
+ Element response = handle(document, operationElement, subsequentOperation);
Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
XmlNetconfConstants.RPC_REPLY_KEY);
return document;
}
- protected abstract Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
+ protected abstract Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
throws NetconfDocumentedException;
@Override
public String toString() {
- return getClass() + "{" + netconfSessionIdForReporting + '}';
+ final StringBuffer sb = new StringBuffer("AbstractConfigNetconfOperation{");
+ sb.append("name=").append(getOperationName());
+ sb.append(", namespace=").append(getOperationNamespace());
+ sb.append(", session=").append(netconfSessionIdForReporting);
+ sb.append('}');
+ return sb.toString();
}
}
--- /dev/null
+/*
+ * Copyright (c) 2013 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.controller.netconf.util.mapping;
+
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+
+public abstract class AbstractSingletonNetconfOperation extends AbstractLastNetconfOperation {
+
+ protected AbstractSingletonNetconfOperation(String netconfSessionIdForReporting) {
+ super(netconfSessionIdForReporting);
+ }
+
+ @Override
+ protected HandlingPriority getHandlingPriority() {
+ return HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
+ }
+
+}
final XPathFactory xPathfactory = XPathFactory.newInstance();
final XPath xpath = xPathfactory.newXPath();
xpath.setNamespaceContext(new HardcodedNamespaceResolver("netconf",
- XmlNetconfConstants.RFC4741_TARGET_NAMESPACE));
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0));
try {
return xpath.compile(xPath);
} catch (final XPathExpressionException e) {
public static final String PREFIX = "prefix";
//
- //
- public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";
public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0";
-
public static final String URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring";
// TODO where to store namespace of config ?
public static final String URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG = "urn:opendaylight:params:xml:ns:yang:controller:config";
<relativePath>../../../commons/opendaylight</relativePath>
</parent>
<properties>
- <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<enunciate.version>1.26.2</enunciate.version>
</properties>
<scm>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
<relativePath>../../commons/opendaylight</relativePath>
</parent>
<properties>
- <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<enunciate.version>1.26.2</enunciate.version>
</properties>
<scm>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>app-northbound</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>maven-archetype</packaging>
+
+ <name>app-northbound</name>
+
+ <build>
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>2.2</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="app"
+ xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <fileSets>
+ <fileSet filtered="true" packaged="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ <fileSet encoding="UTF-8">
+ <directory>.settings</directory>
+ <includes>
+ <include>**/*.prefs</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>.classpath</include>
+ <include>.project</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</archetype-descriptor>
--- /dev/null
+#set( $dollar = '$' )
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.1-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+
+ <artifactId>${artifactId}</artifactId>
+
+ <groupId>${groupId}</groupId>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package></Export-Package>
+ <Import-Package>org.opendaylight.controller.northbound.commons,
+ com.sun.jersey.spi.container.servlet,
+ com.fasterxml.jackson.annotation,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind,
+ javax.xml.bind.annotation,
+ org.slf4j,
+ org.apache.catalina.filters,
+ com.fasterxml.jackson.jaxrs.base,
+ com.fasterxml.jackson.jaxrs.json,
+ !org.codehaus.enunciate.jaxrs</Import-Package>
+ <Web-ContextPath>/northbound/${artifactId}</Web-ContextPath>
+ <Jaxrs-Resources>,${dollar}{classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
+ </instructions>
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <version>${version}</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+package ${package};
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.SecurityContext;
+
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+
+/**
+ * Northbound REST API
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default.
+ */
+
+@Path("/")
+public class Northbound {
+
+ private String username;
+
+ @Context
+ public void setSecurityContext(SecurityContext context) {
+ if (context != null && context.getUserPrincipal() != null) {
+ username = context.getUserPrincipal().getName();
+ }
+ }
+
+ /**
+ *
+ * Sample REST API call
+ *
+ * @return A response string
+ *
+ * <pre>
+ * Example:
+ *
+ * Request URL:
+ * http://localhost:8080/northbound/${artifactId}/api
+ *
+ * Response body in XML:
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * Sample Northbound API
+ *
+ * Response body in JSON:
+ * Sample Northbound API
+ * </pre>
+ */
+ @Path("/api")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(String.class)
+ @StatusCodes()
+ public String getWidget() {
+ String result = "Sample Northbound API - ${artifactId}";
+ return result;
+ }
+
+}
--- /dev/null
+#set( $symbol_pound = '#' )
+#set( $symbol_dollar = '$' )
+#set( $symbol_escape = '\' )
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>JAXRS${artifactId}</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAXRS${artifactId}</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <filter>
+ <filter-name>CorsFilter</filter-name>
+ <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
+ <init-param>
+ <param-name>cors.allowed.origins</param-name>
+ <param-value>*</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cors.allowed.methods</param-name>
+ <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cors.allowed.headers</param-name>
+ <param-value>Content-Type,X-Requested-With,accept,authorization, origin,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cors.exposed.headers</param-name>
+ <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cors.support.credentials</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cors.preflight.maxage</param-name>
+ <param-value>10</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>CorsFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>${artifactId}</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ <http-method>POST</http-method>
+ <http-method>GET</http-method>
+ <http-method>PUT</http-method>
+ <http-method>PATCH</http-method>
+ <http-method>DELETE</http-method>
+ <http-method>HEAD</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>System-Admin</role-name>
+ <role-name>Network-Admin</role-name>
+ <role-name>Network-Operator</role-name>
+ <role-name>Container-User</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>System-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Operator</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Container-User</role-name>
+ </security-role>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>opendaylight</realm-name>
+ </login-config>
+</web-app>
--- /dev/null
+#Fri Mar 07 21:17:20 CST 2014
+package=it.pkg
+version=0.1-SNAPSHOT
+groupId=archetype.it
+artifactId=basic
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.ContextResolver;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlRootElement;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
+
/**
* Instance of javax.ws.rs.core.Application used to return the classes
* that will be instantiated for JAXRS processing. This hooks onto the
* bundle scanner service to provide JAXB classes to JAX-RS for prorcessing.
*/
-@SuppressWarnings("unchecked")
public class NorthboundApplication extends Application {
public static final String JAXRS_RESOURCES_MANIFEST_NAME = "Jaxrs-Resources";
public static final String JAXRS_EXCLUDES_MANIFEST_NAME = "Jaxrs-Exclude-Types";
}
private static final IBundleScanService lookupBundleScanner(BundleContext ctx) {
- ServiceReference svcRef = ctx.getServiceReference(IBundleScanService.class);
+ ServiceReference<?> svcRef = ctx.getServiceReference(IBundleScanService.class);
if (svcRef == null) {
throw new ServiceException("Unable to lookup IBundleScanService");
}
<relativePath>../../../commons/opendaylight</relativePath>
</parent>
<properties>
- <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<enunciate.version>1.26.2</enunciate.version>
</properties>
<scm>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>
moveToReadyListHi(dst);
}
+ //checking only OF map, since production edge discovery always overwrites any existing edge
+ UpdateType ut = edgeMap.containsKey(dst) ? UpdateType.CHANGED : UpdateType.ADDED;
// notify
- updateEdge(edge, UpdateType.ADDED, props);
+ updateEdge(edge, ut, props);
logger.trace("Add edge {}", edge);
}
return;
}
+
this.discoveryListener.notifyEdge(edge, type, props);
NodeConnector src = edge.getTailNodeConnector(), dst = edge.getHeadNodeConnector();
/**
* The class represents an Edge, the Edge's Property Set and its UpdateType.
+ * If update is on new properties added to an existing edge, appropriate type is CHANGED.
*/
public class TopoEdgeUpdate {
private Edge edge;
*/
public static boolean isMulticastMACAddr(byte[] MACAddress) {
if (MACAddress.length == MACAddrLengthInBytes && !isBroadcastMACAddr(MACAddress)) {
- if (MACAddress[0] % 2 == 1) {
- return true;
- }
+ return (MACAddress[0] & 1) != 0;
}
return false;
}
Assert.assertEquals(32768, NetUtils.getUnsignedShort((short) 0x8000));
Assert.assertEquals(65535, NetUtils.getUnsignedShort((short) 0xffff));
}
+
+ @Test
+ public void testMulticastMACAddr() {
+ byte[] empty = new byte[0];
+ Assert.assertFalse(NetUtils.isUnicastMACAddr(empty));
+ Assert.assertFalse(NetUtils.isMulticastMACAddr(empty));
+
+ byte[] bcast = {
+ (byte)0xff, (byte)0xff, (byte)0xff,
+ (byte)0xff, (byte)0xff, (byte)0xff,
+ };
+ Assert.assertFalse(NetUtils.isUnicastMACAddr(bcast));
+ Assert.assertFalse(NetUtils.isMulticastMACAddr(bcast));
+
+ byte[] firstOctet = {
+ (byte)0x00, (byte)0x20, (byte)0x80, (byte)0xfe,
+ };
+ for (int len = 1; len <= 10; len++) {
+ byte[] ba = new byte[len];
+ boolean valid = (len == 6);
+ for (byte first: firstOctet) {
+ ba[0] = first;
+ Assert.assertFalse(NetUtils.isMulticastMACAddr(ba));
+ Assert.assertEquals(valid, NetUtils.isUnicastMACAddr(ba));
+
+ ba[0] |= (byte)0x01;
+ Assert.assertEquals(valid, NetUtils.isMulticastMACAddr(ba));
+ Assert.assertFalse(NetUtils.isUnicastMACAddr(ba));
+ }
+ }
+ }
}
switch (type) {
case ADDED:
+
+ if (this.edgesDB.containsKey(e)) {
+ // Avoid redundant updates (e.g. cluster switch-over) as notifications trigger expensive tasks
+ log.trace("Skipping redundant edge addition: {}", e);
+ return null;
+ }
+
// Make sure the props are non-null or create a copy
if (props == null) {
props = new HashSet<Property>();
props = new HashSet<Property>(props);
}
- Set<Property> currentProps = this.edgesDB.get(e);
- if (currentProps != null) {
-
- if (currentProps.equals(props)) {
- // Avoid redundant updates as notifications trigger expensive tasks
- log.trace("Skipping redundant edge addition: {}", e);
- return null;
- }
-
- // In case of node switch-over to a different cluster controller,
- // let's retain edge props (e.g. creation time)
- props.addAll(currentProps);
- }
// Ensure that head node connector exists
if (!headNodeConnectorExist(e)) {
case CHANGED:
Set<Property> oldProps = this.edgesDB.get(e);
- // When property changes lets make sure we can change it
+ // When property(s) changes lets make sure we can change it
// all except the creation time stamp because that should
- // be changed only when the edge is destroyed and created
- // again
+ // be set only when the edge is created
TimeStamp timeStamp = null;
for (Property prop : oldProps) {
if (prop instanceof TimeStamp) {
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
for (NodeConnector nodeConnector : nodeConnectorSet) {
String nodeConnectorNumberToStr = nodeConnector.getID().toString();
Name ncName = ((Name) switchManager.getNodeConnectorProp(nodeConnector, Name.NamePropName));
- Config portStatus = ((Config) switchManager.getNodeConnectorProp(nodeConnector,
+ Config portConfig = ((Config) switchManager.getNodeConnectorProp(nodeConnector,
Config.ConfigPropName));
State portState = ((State) switchManager.getNodeConnectorProp(nodeConnector,
State.StatePropName));
String nodeConnectorName = (ncName != null) ? ncName.getValue() : "";
nodeConnectorName += " (" + nodeConnector.getID() + ")";
- if (portStatus != null) {
- if (portStatus.getValue() == Config.ADMIN_UP) {
- if (portState.getValue() == State.EDGE_UP) {
+ if (portConfig != null) {
+ if (portConfig.getValue() == Config.ADMIN_UP) {
+ if (portState != null && portState.getValue() == State.EDGE_UP) {
nodeConnectorName = "<span class='admin-up'>" + nodeConnectorName + "</span>";
- } else if (portState.getValue() == State.EDGE_DOWN) {
+ } else if (portState == null || portState.getValue() == State.EDGE_DOWN) {
nodeConnectorName = "<span class='edge-down'>" + nodeConnectorName + "</span>";
}
- } else if (portStatus.getValue() == Config.ADMIN_DOWN) {
+ } else if (portConfig.getValue() == Config.ADMIN_DOWN) {
nodeConnectorName = "<span class='admin-down'>" + nodeConnectorName + "</span>";
}
}
<properties>
<sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
<nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ <nexus.repository.release>opendaylight.release</nexus.repository.release>
+ <nexus.repository.snapshot>opendaylight.snapshot</nexus.repository.snapshot>
<sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
<siteplugin>3.2</siteplugin>
<projectinfo>2.6</projectinfo>
</properties>
<pluginRepositories>
- <pluginRepository>
+ <pluginRepository>
<id>central2</id>
<name>central2</name>
<url>http://repo2.maven.org/maven2</url>
<!-- OpenDayLight Released artifact -->
<repository>
<id>opendaylight-release</id>
- <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.release}/</url>
</repository>
<!-- OpenDayLight Snapshot artifact -->
<snapshotRepository>
<id>opendaylight-snapshot</id>
- <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/${nexus.repository.snapshot}/</url>
</snapshotRepository>
<!-- Site deployment -->
<site>