<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>commons.logback_settings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.parent</artifactId>
+ <version>1.0.1-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+</project>
<yangtools.binding.version>0.6.0-SNAPSHOT</yangtools.binding.version>
<!--versions for bits of the controller -->
<controller.version>0.4.1-SNAPSHOT</controller.version>
- <config.version>0.2.2-SNAPSHOT</config.version>
- <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+ <config.version>0.2.3-SNAPSHOT</config.version>
+ <netconf.version>0.2.3-SNAPSHOT</netconf.version>
<mdsal.version>1.0-SNAPSHOT</mdsal.version>
<containermanager.version>0.5.1-SNAPSHOT</containermanager.version>
<switchmanager.api.version>0.6.1-SNAPSHOT</switchmanager.api.version>
<java.version.target>1.7</java.version.target>
<!-- enforcer version -->
<enforcer.version>1.3.1</enforcer.version>
+ <exi.version>0.9.2-SNAPSHOT</exi.version>
</properties>
<dependencyManagement>
<artifactId>org.openflow.openflowj</artifactId>
<version>1.0.2</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>exificient</artifactId>
+ <version>${exi.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>com.sun.jersey.jersey-servlet</artifactId>
<artifactId>jolokia-osgi</artifactId>
<version>${jolokia.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>properties-maven-plugin</artifactId>
- <version>${propertymavenplugin.version}</version>
- <executions>
- <execution>
- <goals>
- <goal>set-system-properties</goal>
- </goals>
- <configuration>
- <properties>
- <property>
- <name>logback.configurationFile</name>
- <value>${project.parent.basedir}/logback.xml</value>
- </property>
- </properties>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
- <artifactId>maven-java-formatter-plugin</artifactId>
- <version>0.3.1</version>
- <configuration>
- <compilerSource>1.6</compilerSource>
- <compilerCompliance>1.6</compilerCompliance>
- <compilerTargetPlatform>1.6</compilerTargetPlatform>
- <configFile>${project.parent.basedir}/sun_coding_style.xml</configFile>
- </configuration>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${failsafe.version}</version>
<configuration>
<argLine>${testvm.argLine}</argLine>
+ <systemProperties>
+ <property>
+ <name>logback.configurationFile</name>
+ <value>logback.xml</value>
+ </property>
+ </systemProperties>
</configuration>
<executions>
<execution>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>logback.configurationFile</name>
+ <value>logback.xml</value>
+ </property>
+ </systemProperties>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
</goals>
</execution>
</executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+++ /dev/null
-<configuration scan="true">
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>
- </encoder>
- </appender>
-
- <root level="error">
- <appender-ref ref="STDOUT" />
- </root>
-</configuration>
+++ /dev/null
-<?xml version="1.0"?>\r
-<!DOCTYPE module PUBLIC\r
- "-//Puppy Crawl//DTD Check Configuration 1.2//EN"\r
- "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">\r
-\r
-<module name="Checker">\r
- <module name="FileTabCharacter">\r
- <property name="eachLine" value="true"/>\r
- </module>\r
-\r
- <module name="RegexpSingleline">\r
- <!-- \s matches whitespace character, $ matches end of line. -->\r
- <property name="format" value="\s+$"/>\r
- <property name="message" value="Line has trailing spaces."/>\r
- </module>\r
-\r
-</module>\r
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>config-api</artifactId>
org.opendaylight.controller.config.api.jmx,
org.opendaylight.controller.config.api.jmx.constants,
org.opendaylight.controller.config.api.runtime,
- org.opendaylight.controller.config.stat,
</Export-Package>
</instructions>
</configuration>
import javax.management.ObjectName;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.yangtools.concepts.Identifiable;
/**
* Each new {@link org.opendaylight.controller.config.spi.Module} can receive
*
* @see org.opendaylight.controller.config.spi.Module
*/
-public interface DependencyResolver {
+public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
/**
* To be used during validation phase to validate serice interface of
+++ /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.config.stat;
-
-import org.osgi.framework.BundleContext;
-
-/**
- * Subset of {@link org.osgi.framework.BundleContext}
- */
-public interface ConfigProvider {
- /**
- * Returns the value of the specified property. If the key is not found in
- * the Framework properties, the system properties are then searched. The
- * method returns {@code null} if the property is not found.
- *
- * <p>
- * All bundles must have permission to read properties whose names start
- * with "org.osgi.".
- *
- * @param key
- * The name of the requested property.
- * @return The value of the requested property, or {@code null} if the
- * property is undefined.
- * @throws SecurityException
- * If the caller does not have the appropriate
- * {@code PropertyPermission} to read the property, and the Java
- * Runtime Environment supports permissions.
- */
- String getProperty(String key);
-
- public static class ConfigProviderImpl implements ConfigProvider {
- private final BundleContext context;
-
- public ConfigProviderImpl(BundleContext context) {
- this.context = context;
- }
-
- @Override
- public String getProperty(String key) {
- return context.getProperty(key);
- }
-
- @Override
- public String toString() {
- return "ConfigProviderImpl{" + "context=" + context + '}';
- }
- }
-
-}
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-manager</artifactId>
for (ModuleFactory moduleFactory : toBeAdded) {
Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
for (Module module : defaultModules) {
+ // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
+ DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
try {
- putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null);
+ putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver);
} catch (InstanceAlreadyExistsException e) {
throw new IllegalStateException(e);
}
"Error while copying old configuration from %s to %s",
oldConfigBeanInfo, moduleFactory), e);
}
- putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo);
+ putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver);
}
@Override
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
- moduleFactory, null);
+ moduleFactory, null, dependencyResolver);
}
private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
ModuleIdentifier moduleIdentifier, Module module,
ModuleFactory moduleFactory,
- @Nullable ModuleInternalInfo maybeOldConfigBeanInfo)
+ @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver)
throws InstanceAlreadyExistsException {
+
logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
if (moduleIdentifier.equals(module.getIdentifier())==false) {
throw new IllegalStateException("Incorrect name reported by module. Expected "
+ moduleIdentifier + ", got " + module.getIdentifier());
}
+ if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+ throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
+ + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
+ }
DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
module, moduleIdentifier, transactionIdentifier,
readOnlyAtomicBoolean, transactionsMBeanServer,
maybeOldConfigBeanInfo, transactionModuleJMXRegistration);
dependencyResolverManager.put(moduleInternalTransactionalInfo);
- // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
- dependencyResolverManager.getOrCreate(moduleIdentifier);
return writableON;
}
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import static java.lang.String.format;
-
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.concepts.Identifiable;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.ObjectName;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.lang.String.format;
/**
* Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
* during validation. Tracks dependencies for ordering purposes.
*/
final class DependencyResolverImpl implements DependencyResolver,
- Identifiable<ModuleIdentifier>, Comparable<DependencyResolverImpl> {
+ Comparable<DependencyResolverImpl> {
private final ModulesHolder modulesHolder;
private final ModuleIdentifier name;
private final TransactionStatus transactionStatus;
this.modulesHolder = modulesHolder;
}
- @Deprecated
- public ModuleIdentifier getName() {
- return name;
- }
-
/**
* {@inheritDoc}
*/
int maxDepth = 0;
LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
chainForDetectingCycles);
- chainForDetectingCycles2.add(impl.getName());
+ chainForDetectingCycles2.add(impl.getIdentifier());
for (ModuleIdentifier dependencyName : impl.dependencies) {
DependencyResolverImpl dependentDRI = manager
.getOrCreate(dependencyName);
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* Holds information about modules being created and destroyed within this
* transaction. Observes usage of DependencyResolver within modules to figure
List<ModuleIdentifier> result = new ArrayList<>(
moduleIdentifiersToDependencyResolverMap.size());
for (DependencyResolverImpl dri : getAllSorted()) {
- ModuleIdentifier driName = dri.getName();
+ ModuleIdentifier driName = dri.getIdentifier();
result.add(driName);
}
return result;
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* Represents modules to be committed.
*/
throws InstanceAlreadyExistsException {
if (commitMap.containsKey(moduleIdentifier)) {
throw new InstanceAlreadyExistsException(
- "There is an instance registered with name "
- + moduleIdentifier);
+ "There is an instance registered with name " + moduleIdentifier);
}
}
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import java.util.Map;
-
-import javax.management.InstanceAlreadyExistsException;
-
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.CommitInfo;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.Map;
+
interface TransactionHolder {
CommitInfo toCommitInfo();
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-api</artifactId>
com.google.common.base,
org.w3c.dom,
org.osgi.framework,
- org.opendaylight.controller.config.stat
</Import-Package>
<Export-Package>
org.opendaylight.controller.config.persist.api,
package org.opendaylight.controller.config.persist.api.storage;
import org.opendaylight.controller.config.persist.api.Persister;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
/**
* Plugins for {@link org.opendaylight.controller.config.persist.api.Persister}
*/
public interface StorageAdapter extends Persister {
- void setProperties(ConfigProvider configProvider);
+ void setProperties(BundleContext bundleContext);
}
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-persister-file-adapter</artifactId>
javax.xml.transform.stream,
org.apache.commons.lang3,
org.opendaylight.controller.config.persist.api,
- org.opendaylight.controller.config.stat,
org.opendaylight.controller.config.persist.api.storage,
org.slf4j,
org.w3c.dom,
import com.google.common.io.Files;
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
private File storage;
@Override
- public void setProperties(ConfigProvider configProvider) {
- File storage = extractStorageFileFromProperties(configProvider);
+ public void setProperties(BundleContext bundleContext) {
+ File storage = extractStorageFileFromProperties(bundleContext);
logger.debug("Using file {}", storage.getAbsolutePath());
// Create file if it does not exist
File parentFile = storage.getAbsoluteFile().getParentFile();
numberOfStoredBackups = numberOfBackups;
}
- private static File extractStorageFileFromProperties(ConfigProvider configProvider) {
- String fileStorageProperty = configProvider.getProperty(FILE_STORAGE_PROP);
+ private static File extractStorageFileFromProperties(BundleContext bundleContext) {
+ String fileStorageProperty = bundleContext.getProperty(FILE_STORAGE_PROP);
Preconditions.checkNotNull(fileStorageProperty, "Unable to find " + FILE_STORAGE_PROP
- + " in received properties :" + configProvider);
+ + " in received context :" + bundleContext);
File result = new File(fileStorageProperty);
- String numberOfBAckupsAsString = configProvider.getProperty(NUMBER_OF_BACKUPS);
+ String numberOfBAckupsAsString = bundleContext.getProperty(NUMBER_OF_BACKUPS);
if (numberOfBAckupsAsString != null) {
numberOfStoredBackups = Integer.valueOf(numberOfBAckupsAsString);
} else {
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>config-util</artifactId>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>logback-config</artifactId>
<name>${project.artifactId}</name>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<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">
+
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-subsystem</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>netty-threadgroup-config</artifactId>
+ <description>Configuration Wrapper around netty's event group</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <!--test dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.7</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ </Export-Package>
+ <Import-Package>
+ com.google.common.base,
+ io.netty.channel.nio,
+ org.opendaylight.controller.config.yang.threadpool,
+ io.netty.util.concurrent,
+ org.opendaylight.controller.config.api,
+ org.opendaylight.controller.config.api.annotations,
+ org.opendaylight.controller.config.api.runtime,
+ org.opendaylight.controller.config.spi,
+ org.slf4j,
+ org.osgi.framework
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>NETTY-THREADGROUP-CONFIG Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: nsos-threadpool yang module local name: netty-threadgroup-fixed
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Nov 08 08:31:45 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netty.threadgroup;
+
+import com.google.common.base.Preconditions;
+import io.netty.channel.nio.NioEventLoopGroup;
+
+/**
+*
+*/
+public final class NettyThreadgroupModule extends org.opendaylight.controller.config.yang.netty.threadgroup.AbstractNettyThreadgroupModule
+{
+ public NettyThreadgroupModule(org.opendaylight.controller.config.api.ModuleIdentifier name, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(name, dependencyResolver);
+ }
+
+ public NettyThreadgroupModule(org.opendaylight.controller.config.api.ModuleIdentifier name, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, NettyThreadgroupModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(name, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void validate(){
+ if(getThreadCount()!=null) {
+ Preconditions.checkArgument(getThreadCount() > 0, "Thread count cannot be < 0");
+ }
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ return getThreadCount()==null ? new NioEventLoopGroupCloseable() : new NioEventLoopGroupCloseable(getThreadCount());
+ }
+
+
+ private class NioEventLoopGroupCloseable extends NioEventLoopGroup implements AutoCloseable {
+
+
+ public NioEventLoopGroupCloseable(int threadCount) {
+ super(threadCount);
+ }
+
+ public NioEventLoopGroupCloseable() {
+ super();
+ }
+
+ @Override
+ public void close() throws Exception {
+ shutdownGracefully();
+ }
+ }
+}
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: nsos-threadpool yang module local name: netty-threadgroup-fixed
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Nov 08 08:31:45 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netty.threadgroup;
+
+/**
+*
+*/
+public class NettyThreadgroupModuleFactory extends org.opendaylight.controller.config.yang.netty.threadgroup.AbstractNettyThreadgroupModuleFactory
+{
+
+
+}
--- /dev/null
+// vi: set smarttab et sw=4 tabstop=4:
+module nsos-threadpool {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup";
+ prefix "netty-t";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import threadpool { prefix th; revision-date 2013-04-09; }
+
+ organization "Cisco Systems, Inc.";
+
+ contact "Robert Varga <rovarga@cisco.com>";
+
+ description
+ "This module contains the base YANG definitions for NS-OS
+ thread-related services.
+
+ Copyright (c)2013 Cisco Systems, Inc. All rights reserved.";
+
+ revision "2013-11-07" {
+ description
+ "Initial revision";
+ }
+
+ identity netty-threadgroup-fixed {
+ base config:module-type;
+ config:provided-service th:netty-threadgroup;
+ config:java-name-prefix NettyThreadgroup;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case netty-threadgroup-fixed {
+ when "/config:modules/config:module/config:type = 'netty-threadgroup-fixed'";
+
+ leaf thread-count {
+ type uint16;
+
+ description "Number of threads to be used by NioEventLoopGroup. This attribute is optional and default value will be 2* Number of CPUs";
+ }
+
+ // TODO add optional thread factory dependency
+
+ }
+ }
+
+ augment "/config:modules/config:module/config:state" {
+ case netty-threadgroup-fixed {
+ when "/config:modules/config:module/config:type = 'netty-threadgroup-fixed'";
+ }
+ }
+
+
+}
--- /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.config.yang.netty.threadgroup;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
+public class NettyThreadgroupModuleTest extends AbstractConfigTest {
+
+ private NettyThreadgroupModuleFactory factory;
+ private final String instanceName = "netty1";
+
+ @Before
+ public void setUp() {
+ factory = new NettyThreadgroupModuleFactory();
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ }
+
+ @Test
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ createInstance(transaction, instanceName, 2);
+ createInstance(transaction, instanceName + 2, null);
+ transaction.validateConfig();
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(2, factory.getImplementationName());
+ assertStatus(status, 2, 0, 0);
+ }
+
+ @Test
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createInstance(transaction, instanceName, null);
+
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ assertBeanCount(1, factory.getImplementationName());
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 0, 0, 1);
+ }
+
+ @Test
+ public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException,
+ ValidationException, InstanceNotFoundException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createInstance(transaction, instanceName, null);
+
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ assertBeanCount(1, factory.getImplementationName());
+ NettyThreadgroupModuleMXBean mxBean = transaction.newMBeanProxy(
+ transaction.lookupConfigBean(AbstractNettyThreadgroupModuleFactory.NAME, instanceName),
+ NettyThreadgroupModuleMXBean.class);
+ mxBean.setThreadCount(1);
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 0, 1, 0);
+ }
+
+ private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, Integer threads)
+ throws InstanceAlreadyExistsException {
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+ NettyThreadgroupModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, NettyThreadgroupModuleMXBean.class);
+ mxBean.setThreadCount(threads);
+ return nameCreated;
+ }
+}
</parent>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<artifactId>config-subsystem</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<module>logback-config</module>
<module>threadpool-config-api</module>
<module>threadpool-config-impl</module>
+ <module>netty-threadgroup-config</module>
</modules>
<profiles>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>threadpool-config-api</artifactId>
<maven>3.0.4</maven>
</prerequisites>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>config-api</artifactId>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport</artifactId>
+ </dependency>
+ </dependencies>
<build>
<plugins>
<Import-Package>
org.opendaylight.controller.config.api.*,
com.google.common.eventbus,
+ io.netty.channel,
</Import-Package>
<Export-Package>
org.opendaylight.controller.config.threadpool,
thread-related services.
Copyright (c)2013 Cisco Systems, Inc. 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
config:java-class "org.opendaylight.controller.config.threadpool.ScheduledThreadPool";
}
+
+ identity netty-threadgroup {
+ description
+ "Configuration wrapper around netty's threadgroup";
+
+ base "config:service-type";
+ config:java-class "io.netty.channel.EventLoopGroup";
+ }
+
+
}
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>threadpool-config-impl</artifactId>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+
+ <!--test dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
</plugins>
</build>
-</project>
\ No newline at end of file
+</project>
--- /dev/null
+package org.opendaylight.controller.config.threadpool.async;\r
+\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.ClassBasedModuleFactory;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.threadpool.scheduled.TestingScheduledThreadPoolModule;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.AsyncEventBusModuleMXBean;\r
+\r
+public class AsyncEventBusConfigBeanTest extends AbstractConfigTest {\r
+\r
+ private AsyncEventBusModuleFactory factory;\r
+ private final String instanceName = "async1";\r
+ private final String poolImplName = "fixed1";\r
+\r
+ @Before\r
+ public void setUp() {\r
+\r
+ ClassBasedModuleFactory scheduledThreadPoolConfigFactory = createClassBasedCBF(\r
+ TestingScheduledThreadPoolModule.class, poolImplName);\r
+\r
+ factory = new AsyncEventBusModuleFactory();\r
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,\r
+ scheduledThreadPoolConfigFactory));\r
+ }\r
+\r
+ @Test\r
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createAsynced(transaction, instanceName, transaction.createModule(poolImplName, "pool-test"));\r
+ transaction.validateConfig();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 2, 0, 0);\r
+ }\r
+\r
+ @Test\r
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+ ValidationException {\r
+\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createAsynced(transaction, instanceName, transaction.createModule(poolImplName, "pool-test"));\r
+\r
+ transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 0, 0, 2);\r
+\r
+ }\r
+\r
+ @Test\r
+ public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException,\r
+ InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ ObjectName poolCB = transaction.createModule(poolImplName, "pool-test");\r
+ createAsynced(transaction, instanceName, poolCB);\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ try {\r
+ createAsynced(transaction, instanceName, poolCB);\r
+ fail();\r
+ } catch (InstanceAlreadyExistsException e) {\r
+ assertThat(\r
+ e.getMessage(),\r
+ containsString("There is an instance registered with name ModuleIdentifier{factoryName='async-eventbus', instanceName='async1'}"));\r
+ }\r
+ }\r
+\r
+ private ObjectName createAsynced(ConfigTransactionJMXClient transaction, String instanceName, ObjectName threadPool)\r
+ throws InstanceAlreadyExistsException {\r
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+ AsyncEventBusModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, AsyncEventBusModuleMXBean.class);\r
+ mxBean.setThreadpool(threadPool);\r
+ return nameCreated;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.eventbus;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleFactory;
+
+public class SyncEventBusConfigBeanTest extends AbstractConfigTest {
+
+ private EventBusModuleFactory factory;
+ private final String instanceName = "sync1";
+
+ @Before
+ public void setUp() {
+
+ factory = new EventBusModuleFactory();
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ }
+
+ @Test
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+ ConflictingVersionException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ createSynced(transaction, instanceName);
+ transaction.validateConfig();
+ CommitStatus status = transaction.commit();
+
+ assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());
+ assertEquals(1, status.getNewInstances().size());
+ assertEquals(0, status.getRecreatedInstances().size());
+ assertEquals(0, status.getReusedInstances().size());
+ // TODO test dead event collector
+ }
+
+ @Test
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+ ValidationException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createSynced(transaction, instanceName);
+
+ transaction.commit();
+
+ assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());
+
+ transaction = configRegistryClient.createTransaction();
+ CommitStatus status = transaction.commit();
+
+ assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());
+ assertEquals(0, status.getNewInstances().size());
+ assertEquals(0, status.getRecreatedInstances().size());
+ assertEquals(1, status.getReusedInstances().size());
+
+ }
+
+ @Test
+ public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ try {
+ createSynced(transaction, instanceName);
+ transaction.commit();
+ } catch (InstanceAlreadyExistsException e1) {
+ fail();
+ }
+
+ transaction = configRegistryClient.createTransaction();
+ try {
+ createSynced(transaction, instanceName);
+ fail();
+ } catch (InstanceAlreadyExistsException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("There is an instance registered with name ModuleIdentifier{factoryName='eventbus', instanceName='sync1'}"));
+ }
+ }
+
+ private ObjectName createSynced(ConfigTransactionJMXClient transaction, String instanceName)
+ throws InstanceAlreadyExistsException {
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+ return nameCreated;
+ }
+}
--- /dev/null
+package org.opendaylight.controller.config.threadpool.eventbus;\r
+\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.manager.impl.AbstractMockedModule;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.CloseableEventBus;\r
+import org.opendaylight.controller.config.yang.threadpool.EventBusServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.EventBusModuleMXBean;\r
+\r
+public class TestingEventBusModule extends AbstractMockedModule implements Module, EventBusServiceInterface,\r
+ EventBusModuleMXBean {\r
+\r
+ public TestingEventBusModule(DynamicMBeanWithInstance old, ModuleIdentifier id) {\r
+ super(old, id);\r
+ }\r
+\r
+ @Override\r
+ protected AutoCloseable prepareMockedInstance() throws Exception {\r
+ CloseableEventBus bus = mock(CloseableEventBus.class);\r
+ doNothing().when(bus).close();\r
+ return bus;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.fixed;\r
+\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FixedThreadPoolModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FixedThreadPoolModuleMXBean;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class FixedThreadPoolConfigBeanTest extends AbstractConfigTest {\r
+\r
+ private FixedThreadPoolModuleFactory factory;\r
+ private final String nameInstance = "fixedInstance";\r
+\r
+ @Before\r
+ public void setUp() {\r
+ factory = new FixedThreadPoolModuleFactory();\r
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,\r
+ new NamingThreadFactoryModuleFactory()));\r
+ }\r
+\r
+ @Test\r
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createFixed(transaction, nameInstance, 2);\r
+\r
+ transaction.validateConfig();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 2, 0, 0);\r
+ }\r
+\r
+ @Test\r
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+ ValidationException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createFixed(transaction, nameInstance, 4);\r
+\r
+ transaction.validateConfig();\r
+ transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 0, 0, 2);\r
+ }\r
+\r
+ @Test\r
+ public void testNegative() throws ConflictingVersionException, ValidationException, InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createFixed(transaction, nameInstance, 5);\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ try {\r
+ createFixed(transaction, nameInstance, 0);\r
+ fail();\r
+ } catch (InstanceAlreadyExistsException e) {\r
+ assertThat(\r
+ e.getMessage(),\r
+ containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadpool-fixed', instanceName='fixedInstance'}"));\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testDestroy() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException,\r
+ InstanceNotFoundException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createFixed(transaction, nameInstance, 1);\r
+\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ transaction.destroyConfigBean(factory.getImplementationName(), nameInstance);\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(0, factory.getImplementationName());\r
+ assertStatus(status, 0, 0, 1);\r
+ }\r
+\r
+ @Test\r
+ public void testValidationException() throws InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createFixed(transaction, nameInstance, -1);\r
+ try {\r
+ transaction.validateConfig();\r
+ fail();\r
+ } catch (ValidationException e) {\r
+ assertThat(e.getMessage(), containsString("MaxThreadCount must be greater than zero"));\r
+ }\r
+ }\r
+\r
+ private ObjectName createFixed(ConfigTransactionJMXClient transaction, String name, int numberOfThreads)\r
+ throws InstanceAlreadyExistsException {\r
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), name);\r
+ FixedThreadPoolModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, FixedThreadPoolModuleMXBean.class);\r
+ mxBean.setMaxThreadCount(numberOfThreads);\r
+\r
+ ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, "naming");\r
+ NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,\r
+ NamingThreadFactoryModuleMXBean.class);\r
+ namingThreadFactoryModuleMXBean.setNamePrefix("prefix");\r
+\r
+ mxBean.setThreadFactory(threadFactoryON);\r
+\r
+ return nameCreated;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.fixed;\r
+\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.util.concurrent.ExecutorService;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.manager.impl.AbstractMockedModule;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.FixedThreadPoolWrapper;\r
+import org.opendaylight.controller.config.yang.threadpool.ThreadPoolServiceInterface;\r
+\r
+public class TestingFixedThreadPoolModule extends AbstractMockedModule implements ThreadPoolServiceInterface, Module {\r
+\r
+ public TestingFixedThreadPoolModule(DynamicMBeanWithInstance old, ModuleIdentifier id) {\r
+ super(old, id);\r
+ }\r
+\r
+ @Override\r
+ protected AutoCloseable prepareMockedInstance() throws Exception {\r
+ FixedThreadPoolWrapper pool = mock(FixedThreadPoolWrapper.class);\r
+ doNothing().when(pool).close();\r
+ doReturn(mock(ExecutorService.class)).when(pool).getExecutor();\r
+ return pool;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.flexible;\r
+\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FlexibleThreadPoolModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.FlexibleThreadPoolModuleMXBean;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class FlexibleThreadPoolConfigBeanTest extends AbstractConfigTest {\r
+\r
+ private FlexibleThreadPoolModuleFactory flexibleFactory;\r
+ private final String instanceName = "flexible1";\r
+ private final String threadFactoryName = "threadFactoryName";\r
+\r
+ @Before\r
+ public void setUp() {\r
+\r
+ flexibleFactory = new FlexibleThreadPoolModuleFactory();\r
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(flexibleFactory,\r
+ new NamingThreadFactoryModuleFactory()));\r
+ }\r
+\r
+ @Test\r
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createFlexible(transaction, instanceName, threadFactoryName, 1, 20, 20);\r
+ transaction.validateConfig();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, flexibleFactory.getImplementationName());\r
+ assertStatus(status, 2, 0, 0);\r
+ }\r
+\r
+ @Test\r
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+ ValidationException {\r
+\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createFlexible(transaction, instanceName, threadFactoryName, 1, 20, 10);\r
+\r
+ transaction.commit();\r
+\r
+ assertBeanCount(1, flexibleFactory.getImplementationName());\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, flexibleFactory.getImplementationName());\r
+ assertStatus(status, 0, 0, 2);\r
+\r
+ }\r
+\r
+ @Test\r
+ public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ try {\r
+ createFlexible(transaction, instanceName, threadFactoryName, 1, 1, 2);\r
+ transaction.commit();\r
+ } catch (InstanceAlreadyExistsException e1) {\r
+ fail();\r
+ }\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ try {\r
+ createFlexible(transaction, instanceName, "threadFactoryName1", 2, 2, 2);\r
+ fail();\r
+ } catch (InstanceAlreadyExistsException e) {\r
+ assertThat(\r
+ e.getMessage(),\r
+ containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadpool-flexible', instanceName='flexible1'}"));\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testValidationException() throws InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createFlexible(transaction, instanceName, threadFactoryName, 0, 10, 10);\r
+\r
+ try {\r
+ transaction.validateConfig();\r
+ fail();\r
+ } catch (ValidationException e) {\r
+ assertThat(e.getMessage(), containsString("MinThreadCount must be greater than zero"));\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testValidationException2() throws InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createFlexible(transaction, instanceName, threadFactoryName, 0, 0, 10);\r
+\r
+ try {\r
+ transaction.validateConfig();\r
+ fail();\r
+ } catch (ValidationException e) {\r
+ assertThat(e.getMessage(), containsString("KeepAliveMillis must be greater than zero"));\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testValidationException3() throws InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createFlexible(transaction, instanceName, threadFactoryName, 10, 50, 0);\r
+\r
+ try {\r
+ transaction.validateConfig();\r
+ fail();\r
+ } catch (ValidationException e) {\r
+ assertThat(e.getMessage(), containsString("MaxThreadCount must be greater than zero"));\r
+ }\r
+ }\r
+\r
+ private ObjectName createFlexible(ConfigTransactionJMXClient transaction, String instanceName,\r
+ String threadFactoryName, int minThreadCount, long keepAliveMillis, int maxThreadCount)\r
+ throws InstanceAlreadyExistsException {\r
+\r
+ ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, threadFactoryName);\r
+ NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,\r
+ NamingThreadFactoryModuleMXBean.class);\r
+ namingThreadFactoryModuleMXBean.setNamePrefix("prefix");\r
+\r
+ ObjectName flexibleON = transaction.createModule(flexibleFactory.getImplementationName(), instanceName);\r
+ FlexibleThreadPoolModuleMXBean mxBean = transaction.newMBeanProxy(flexibleON,\r
+ FlexibleThreadPoolModuleMXBean.class);\r
+ mxBean.setKeepAliveMillis(keepAliveMillis);\r
+ mxBean.setMaxThreadCount(maxThreadCount);\r
+ mxBean.setMinThreadCount(minThreadCount);\r
+ mxBean.setThreadFactory(threadFactoryON);\r
+ return flexibleON;\r
+ }\r
+\r
+ @Test\r
+ public void testReconfigurationInstance() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException, InstanceNotFoundException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createFlexible(transaction, instanceName, threadFactoryName, 2, 2, 2);\r
+\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ ObjectName databaseNew = transaction.lookupConfigBean(flexibleFactory.getImplementationName(), instanceName);\r
+ FlexibleThreadPoolModuleMXBean proxy = transaction.newMXBeanProxy(databaseNew,\r
+ FlexibleThreadPoolModuleMXBean.class);\r
+ proxy.setMaxThreadCount(99);\r
+\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, flexibleFactory.getImplementationName());\r
+ assertStatus(status, 0, 1, 1);\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.naming;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.ThreadFactoryServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class NamingThreadPoolFactoryConfigBeanTest extends AbstractConfigTest {\r
+\r
+ private NamingThreadFactoryModuleFactory factory;\r
+ private final String instanceName = "named";\r
+\r
+ @Before\r
+ public void setUp() {\r
+\r
+ factory = new NamingThreadFactoryModuleFactory();\r
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));\r
+ }\r
+\r
+ @Test\r
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createNamed(transaction, instanceName, "prefixes");\r
+ transaction.validateConfig();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());\r
+ assertEquals(1, status.getNewInstances().size());\r
+ assertEquals(0, status.getRecreatedInstances().size());\r
+ assertEquals(0, status.getReusedInstances().size());\r
+ }\r
+\r
+ @Test\r
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+ ValidationException {\r
+\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createNamed(transaction, instanceName, "prefixes");\r
+\r
+ transaction.commit();\r
+\r
+ assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertEquals(1, configRegistry.lookupConfigBeans(factory.getImplementationName()).size());\r
+ assertEquals(0, status.getNewInstances().size());\r
+ assertEquals(0, status.getRecreatedInstances().size());\r
+ assertEquals(1, status.getReusedInstances().size());\r
+\r
+ }\r
+\r
+ @Test\r
+ public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException,\r
+ InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createNamed(transaction, instanceName, "prefixes");\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ try {\r
+ createNamed(transaction, instanceName, "prefixes1");\r
+ fail();\r
+ } catch (InstanceAlreadyExistsException e) {\r
+ assertThat(\r
+ e.getMessage(),\r
+ containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadfactory-naming', instanceName='named'}"));\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testValidationException() throws InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+ transaction.newMXBeanProxy(nameCreated, ThreadFactoryServiceInterface.class);\r
+ try {\r
+ transaction.validateConfig();\r
+ fail();\r
+ } catch (ValidationException e) {\r
+ assertTrue(e.getFailedValidations().containsKey(factory.getImplementationName()));\r
+ assertEquals(1, e.getFailedValidations().get(factory.getImplementationName()).keySet().size());\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testReconfigurationInstance() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException, InstanceNotFoundException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createNamed(transaction, instanceName, "pref");\r
+\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ ObjectName databaseNew = transaction.lookupConfigBean(factory.getImplementationName(), instanceName);\r
+ NamingThreadFactoryModuleMXBean proxy = transaction.newMXBeanProxy(databaseNew,\r
+ NamingThreadFactoryModuleMXBean.class);\r
+ proxy.setNamePrefix("pref1");\r
+\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 0, 1, 0);\r
+ }\r
+\r
+ private ObjectName createNamed(ConfigTransactionJMXClient transaction, String instanceName, String prefixes)\r
+ throws InstanceAlreadyExistsException {\r
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+ NamingThreadFactoryModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,\r
+ NamingThreadFactoryModuleMXBean.class);\r
+ mxBean.setNamePrefix(prefixes);\r
+ return nameCreated;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.naming;\r
+\r
+import static org.mockito.Matchers.any;\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.io.Closeable;\r
+import java.io.IOException;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.NamingThreadPoolFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.ThreadFactoryServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+\r
+public class TestingNamingThreadPoolFactoryModule implements Module, ThreadFactoryServiceInterface,\r
+ NamingThreadFactoryModuleMXBean {\r
+\r
+ private final NamingThreadPoolFactory fact;\r
+\r
+ public TestingNamingThreadPoolFactoryModule() throws IOException {\r
+ fact = mock(NamingThreadPoolFactory.class);\r
+ Thread thread = mock(Thread.class);\r
+ doNothing().when(thread).start();\r
+ doReturn(thread).when(fact).newThread(any(Runnable.class));\r
+ doNothing().when(fact).close();\r
+ }\r
+\r
+ public TestingNamingThreadPoolFactoryModule(DynamicMBeanWithInstance old) {\r
+ fact = (NamingThreadPoolFactory) old.getInstance();\r
+ }\r
+\r
+ @Override\r
+ public ModuleIdentifier getIdentifier() {\r
+ return new ModuleIdentifier(TestingNamingThreadPoolFactoryModule.class.getCanonicalName(), "mock");\r
+ }\r
+\r
+ @Override\r
+ public String getNamePrefix() {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void setNamePrefix(String arg) {\r
+ throw new UnsupportedOperationException();\r
+ }\r
+\r
+ @Override\r
+ public void validate() {\r
+ }\r
+\r
+ @Override\r
+ public Closeable getInstance() {\r
+ return fact;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.scheduled;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.fail;\r
+import static org.junit.matchers.JUnitMatchers.containsString;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.InstanceNotFoundException;\r
+import javax.management.ObjectName;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.config.api.ConflictingVersionException;\r
+import org.opendaylight.controller.config.api.ValidationException;\r
+import org.opendaylight.controller.config.api.jmx.CommitStatus;\r
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;\r
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;\r
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.ScheduledThreadPoolModuleFactory;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.ScheduledThreadPoolModuleMXBean;\r
+\r
+public class ScheduledThreadPoolConfigBeanTest extends AbstractConfigTest {\r
+\r
+ private ScheduledThreadPoolModuleFactory factory;\r
+ private final String instanceName = "scheduled1";\r
+\r
+ @Before\r
+ public void setUp() {\r
+\r
+ factory = new ScheduledThreadPoolModuleFactory();\r
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,\r
+ new NamingThreadFactoryModuleFactory()));\r
+ }\r
+\r
+ @Test\r
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+\r
+ createScheduled(transaction, instanceName, 1);\r
+ transaction.validateConfig();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 2, 0, 0);\r
+ }\r
+\r
+ @Test\r
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,\r
+ ValidationException {\r
+\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createScheduled(transaction, instanceName, 1);\r
+\r
+ transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 0, 0, 2);\r
+ }\r
+\r
+ @Test\r
+ public void testReconfigurationInstance() throws InstanceAlreadyExistsException, ValidationException,\r
+ ConflictingVersionException, InstanceNotFoundException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createScheduled(transaction, instanceName, 1);\r
+\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ ObjectName databaseNew = transaction.lookupConfigBean(factory.getImplementationName(), instanceName);\r
+ ScheduledThreadPoolModuleMXBean proxy = transaction.newMXBeanProxy(databaseNew,\r
+ ScheduledThreadPoolModuleMXBean.class);\r
+ proxy.setMaxThreadCount(99);\r
+\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(1, factory.getImplementationName());\r
+ assertStatus(status, 0, 1, 1);\r
+ }\r
+\r
+ @Test\r
+ public void testDestroy() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException,\r
+ InstanceNotFoundException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createScheduled(transaction, instanceName, 1);\r
+\r
+ transaction.commit();\r
+\r
+ transaction = configRegistryClient.createTransaction();\r
+ transaction.destroyConfigBean(factory.getImplementationName(), instanceName);\r
+ CommitStatus status = transaction.commit();\r
+\r
+ assertBeanCount(0, factory.getImplementationName());\r
+ assertStatus(status, 0, 0, 1);\r
+ }\r
+\r
+ @Test\r
+ public void testInstanceAlreadyExistsException() throws ConflictingVersionException, ValidationException,\r
+ InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createScheduled(transaction, instanceName, 1);\r
+ transaction.commit();\r
+ transaction = configRegistryClient.createTransaction();\r
+ try {\r
+ createScheduled(transaction, instanceName, 2);\r
+ fail();\r
+ } catch (InstanceAlreadyExistsException e) {\r
+ assertThat(\r
+ e.getMessage(),\r
+ containsString("There is an instance registered with name ModuleIdentifier{factoryName='threadpool-scheduled', instanceName='scheduled1'}"));\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testValidationException() throws InstanceAlreadyExistsException {\r
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();\r
+ createScheduled(transaction, instanceName, 0);\r
+\r
+ try {\r
+ transaction.validateConfig();\r
+ fail();\r
+ } catch (ValidationException e) {\r
+ assertTrue(e.getFailedValidations().containsKey(factory.getImplementationName()));\r
+ assertEquals(1, e.getFailedValidations().get(factory.getImplementationName()).keySet().size());\r
+ }\r
+ }\r
+\r
+ private ObjectName createScheduled(ConfigTransactionJMXClient transaction, String instanceName, int maxThreadCount)\r
+ throws InstanceAlreadyExistsException {\r
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);\r
+ ScheduledThreadPoolModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated,\r
+ ScheduledThreadPoolModuleMXBean.class);\r
+ mxBean.setMaxThreadCount(maxThreadCount);\r
+\r
+ ObjectName threadFactoryON = transaction.createModule(NamingThreadFactoryModuleFactory.NAME, "naming");\r
+ NamingThreadFactoryModuleMXBean namingThreadFactoryModuleMXBean = transaction.newMXBeanProxy(threadFactoryON,\r
+ NamingThreadFactoryModuleMXBean.class);\r
+ namingThreadFactoryModuleMXBean.setNamePrefix("prefix");\r
+\r
+ mxBean.setThreadFactory(threadFactoryON);\r
+\r
+ return nameCreated;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.config.threadpool.scheduled;\r
+\r
+import static org.mockito.Matchers.any;\r
+import static org.mockito.Matchers.anyBoolean;\r
+import static org.mockito.Matchers.anyLong;\r
+import static org.mockito.Mockito.doNothing;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.util.concurrent.ScheduledExecutorService;\r
+import java.util.concurrent.ScheduledFuture;\r
+import java.util.concurrent.TimeUnit;\r
+\r
+import javax.management.ObjectName;\r
+\r
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;\r
+import org.opendaylight.controller.config.api.ModuleIdentifier;\r
+import org.opendaylight.controller.config.manager.impl.AbstractMockedModule;\r
+import org.opendaylight.controller.config.spi.Module;\r
+import org.opendaylight.controller.config.threadpool.util.ScheduledThreadPoolWrapper;\r
+import org.opendaylight.controller.config.yang.threadpool.ScheduledThreadPoolServiceInterface;\r
+import org.opendaylight.controller.config.yang.threadpool.impl.ScheduledThreadPoolModuleMXBean;\r
+\r
+import com.google.common.util.concurrent.ListenableFutureTask;\r
+\r
+public class TestingScheduledThreadPoolModule extends AbstractMockedModule implements\r
+ ScheduledThreadPoolServiceInterface, Module, ScheduledThreadPoolModuleMXBean {\r
+\r
+ public TestingScheduledThreadPoolModule(DynamicMBeanWithInstance old, ModuleIdentifier id) {\r
+ super(old, id);\r
+ }\r
+\r
+ @Override\r
+ protected AutoCloseable prepareMockedInstance() throws Exception {\r
+ ScheduledThreadPoolWrapper instance = mock(ScheduledThreadPoolWrapper.class);\r
+ ScheduledExecutorService ses = mock(ScheduledExecutorService.class);\r
+ {// mockFuture\r
+ ScheduledFuture<?> future = mock(ScheduledFuture.class);\r
+ doReturn(false).when(future).cancel(anyBoolean());\r
+ try {\r
+ doReturn(mock(Object.class)).when(future).get();\r
+ } catch (Exception e) {\r
+ throw new RuntimeException(e);\r
+ }\r
+ doReturn(future).when(ses).schedule(any(Runnable.class), any(Long.class), any(TimeUnit.class));\r
+ doReturn(future).when(ses).scheduleWithFixedDelay(any(Runnable.class), anyLong(), anyLong(),\r
+ any(TimeUnit.class));\r
+\r
+ }\r
+ doNothing().when(ses).execute(any(Runnable.class));\r
+ doNothing().when(ses).execute(any(ListenableFutureTask.class));\r
+ doReturn(ses).when(instance).getExecutor();\r
+ doNothing().when(instance).close();\r
+\r
+ doReturn(1).when(instance).getMaxThreadCount();\r
+ return instance;\r
+ }\r
+\r
+ @Override\r
+ public ObjectName getThreadFactory() {\r
+ return any(ObjectName.class);\r
+ }\r
+\r
+ @Override\r
+ public void setThreadFactory(ObjectName threadFactory) {\r
+ }\r
+\r
+ @Override\r
+ public Integer getMaxThreadCount() {\r
+ return 1;\r
+ }\r
+\r
+ @Override\r
+ public void setMaxThreadCount(Integer maxThreadCount) {\r
+ }\r
+\r
+}\r
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>yang-jmx-generator-it</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>yang-jmx-generator-plugin</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>yang-jmx-generator</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>yang-store-api</artifactId>
<parent>
<artifactId>config-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>yang-store-impl</artifactId>
<parent>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-subsystem</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>yang-test</artifactId>
<artifactId>model-flow-management</artifactId>
<version>${mdsal.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>inventory-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-persister-impl</artifactId>
<version>${netconf.version}</version>
</dependency>
-
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>exificient</artifactId>
+ <version>${exi.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicemix.bundles</groupId>
+ <artifactId>org.apache.servicemix.bundles.xerces</artifactId>
+ <version>2.11.0_1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.birt.runtime.3_7_1</groupId>
+ <artifactId>org.apache.xml.resolver</artifactId>
+ <version>1.2.0</version>
+ </dependency>
<!-- toaster example I'm pretty sure we should trim -->
-
<dependency>
<groupId>org.opendaylight.controller.samples</groupId>
<artifactId>sample-toaster</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>binding-generator-util</artifactId>
+ <artifactId>binding-generator-spi</artifactId>
<version>${yangtools.binding.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>binding-model-api</artifactId>
+ <artifactId>binding-generator-api</artifactId>
<version>${yangtools.binding.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>binding-generator-spi</artifactId>
+ <artifactId>binding-generator-impl</artifactId>
+ <version>${yangtools.binding.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-generator-util</artifactId>
+ <version>${yangtools.binding.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-model-api</artifactId>
<version>${yangtools.binding.version}</version>
</dependency>
<dependency>
</dependency>
</dependencies>
</profile>
+ <profile>
+ <id>integrationtests</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.8</version>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sanitytest</artifactId>
+ <version>${controller.version}</version>
+ <type>jar</type>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <id>sanity-test</id>
+ <phase>package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>${java.home}/bin/java</executable>
+ <arguments>
+ <argument>-cp</argument>
+ <argument>./target/dependency/*</argument>
+ <argument>org.opendaylight.controller.distribution.Sanity</argument>
+ </arguments>
+ <environmentVariables>
+ <JAVA_HOME>
+ ${java.home}
+ </JAVA_HOME>
+ </environmentVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
<artifactId>distribution.opendaylight</artifactId>
</execution>
</executions>
</plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <version>2.8</version>
- <executions>
- <execution>
- <id>copy</id>
- <phase>package</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sanitytest</artifactId>
- <version>${controller.version}</version>
- <type>jar</type>
- </artifactItem>
- </artifactItems>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <version>1.2.1</version>
- <executions>
- <execution>
- <id>sanity-test</id>
- <phase>package</phase>
- <goals>
- <goal>exec</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <executable>${java.home}/bin/java</executable>
- <arguments>
- <argument>-cp</argument>
- <argument>./target/dependency/*</argument>
- <argument>org.opendaylight.controller.distribution.Sanity</argument>
- </arguments>
- <environmentVariables>
- <JAVA_HOME>
- ${java.home}
- </JAVA_HOME>
- </environmentVariables>
- </configuration>
- </plugin>
</plugins>
</build>
</project>
<Import-Package>
org.opendaylight.controller.sal.binding.api,
org.opendaylight.controller.sal.binding.api.data,
- org.opendaylight.controller.md.sal.common.api.data,
- org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow,
+ org.opendaylight.controller.md.sal.common.api.data,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket,
org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+ org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction,
+ org.opendaylight.controller.switchmanager,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024,
org.opendaylight.yangtools.concepts,
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819,
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819,
package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.NotificationService;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FRMConsumerImpl extends AbstractBindingAwareProvider {
+public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{
protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
private static ProviderContext p_session;
private static DataBrokerService dataBrokerService;
private GroupConsumerImpl groupImplRef;
private static DataProviderService dataProviderService;
+ private static IClusterContainerServices clusterContainerService = null;
+ private static ISwitchManager switchManager;
+ private static IContainer container;
+
@Override
public void onSessionInitiated(ProviderContext session) {
FRMConsumerImpl.p_session = session;
+ if (!getDependentModule()) {
+ logger.error("Unable to fetch handlers for dependent modules");
+ System.out.println("Unable to fetch handlers for dependent modules");
+ return;
+ }
+
if (null != session) {
notificationService = session.getSALService(NotificationService.class);
if (null != dataProviderService) {
flowImplRef = new FlowConsumerImpl();
- groupImplRef = new GroupConsumerImpl();
+ // groupImplRef = new GroupConsumerImpl();
+ registerWithOSGIConsole();
}
else {
logger.error("Data Provider Service is down or NULL. " +
System.out.println("Consumer session is NULL. Please check if provider is registered");
}
+ }
+
+ public static IClusterContainerServices getClusterContainerService() {
+ return clusterContainerService;
+ }
+
+ public static void setClusterContainerService(
+ IClusterContainerServices clusterContainerService) {
+ FRMConsumerImpl.clusterContainerService = clusterContainerService;
+ }
+
+ public static ISwitchManager getSwitchManager() {
+ return switchManager;
+ }
+
+ public static void setSwitchManager(ISwitchManager switchManager) {
+ FRMConsumerImpl.switchManager = switchManager;
+ }
+
+ public static IContainer getContainer() {
+ return container;
}
- public static DataProviderService getDataProviderService() {
+ public static void setContainer(IContainer container) {
+ FRMConsumerImpl.container = container;
+ }
+
+ private void registerWithOSGIConsole() {
+ BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ bundleContext.registerService(CommandProvider.class.getName(), this, null);
+ }
+
+ private boolean getDependentModule() {
+ do {
+ clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this);
+ try {
+ Thread.sleep(4);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while(clusterContainerService == null);
+
+ do {
+
+
+ container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while (container == null);
+
+ do {
+ switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this);
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while(null == switchManager);
+ return true;
+ }
+
+
+
+ public static DataProviderService getDataProviderService() {
return dataProviderService;
}
public FlowConsumerImpl getFlowImplRef() {
- return flowImplRef;
+ return flowImplRef;
}
public GroupConsumerImpl getGroupImplRef() {
- return groupImplRef;
+ return groupImplRef;
}
public static ProviderContext getProviderSession() {
public static DataBrokerService getDataBrokerService() {
return dataBrokerService;
}
+
+ /*
+ * OSGI COMMANDS
+ */
+ @Override
+ public String getHelp() {
+ StringBuffer help = new StringBuffer();
+ return help.toString();
+ }
}
--- /dev/null
+package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions;
+
+public class FRMUtil {
+ private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+ public enum operation {ADD, DELETE, UPDATE, GET};
+
+
+ public static boolean isNameValid(String name) {
+
+ // Name validation
+ if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
+ return false;
+ }
+ return true;
+
+ }
+
+ public static boolean areActionsValid(Actions actions) {
+ // List<Action> actionList;
+ // Action actionRef;
+ // if (null != actions && null != actions.getAction()) {
+ // actionList = actions.getAction();
+
+
+
+
+ // }
+
+ return true;
+ }
+}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
}
listener = new FlowDataListener();
+
if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) {
logger.error("Failed to listen on flow data modifcation events");
System.out.println("Consumer SAL Service is down or NULL.");
System.out.println("Consumer SAL Service is down or NULL.");
return;
}
- addFlowTest();
+ //addFlowTest();
System.out.println("-------------------------------------------------------------------");
allocateCaches();
commitHandler = new FlowDataCommitHandler();
private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
AddFlowInputBuilder input = new AddFlowInputBuilder();
+ List<Instruction> inst = (dataObject).getInstructions().getInstruction();
input.setNode((dataObject).getNode());
input.setPriority((dataObject).getPriority());
input.setMatch((dataObject).getMatch());
input.setCookie((dataObject).getCookie());
- input.setAction((dataObject).getAction());
+ input.setInstructions((dataObject).getInstructions());
+ dataObject.getMatch().getLayer3Match()
+ for (int i=0;i<inst.size();i++) {
+ System.out.println("i = "+ i + inst.get(i).getInstruction().toString());
+ System.out.println("i = "+ i + inst.get(i).toString());
+ }
+
+ System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
// We send flow to the sounthbound plugin
flowService.addFlow(input.build());
private void commitToPlugin(internalTransaction transaction) {
for(Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+ System.out.println("Coming add cc in FlowDatacommitHandler");
addFlow(entry.getKey(),entry.getValue());
}
- for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+ for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.updates.entrySet()) {
+ System.out.println("Coming update cc in FlowDatacommitHandler");
// updateFlow(entry.getKey(),entry.getValue());
}
Flow original = originalSwView.get(key);
if (original != null) {
// It is update for us
+ System.out.println("Coming update in FlowDatacommitHandler");
updates.put(key, flow);
} else {
// It is addition for us
+ System.out.println("Coming add in FlowDatacommitHandler");
additions.put(key, flow);
}
}
for (DataObject dataObject : additions) {
if (dataObject instanceof NodeFlow) {
NodeRef nodeOne = createNodeRef("foo:node:1");
- // validating the dataObject here
+ // validating the dataObject here
AddFlowInputBuilder input = new AddFlowInputBuilder();
input.setNode(((NodeFlow) dataObject).getNode());
input.setNode(nodeOne);
return new NodeRef(path);
}
- /* private void loadFlowData() {
- DataModification modification = (DataModification) dataservice.beginTransaction();
- String id = "abc";
- FlowKey key = new FlowKey(id, new NodeRef());
- InstanceIdentifier<?> path1;
- FlowBuilder flow = new FlowBuilder();
- flow.setKey(key);
- path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance();
- DataObject cls = (DataObject) modification.readConfigurationData(path);
- modification.putConfigurationData(path, flow.build());
- modification.commit();
- }*/
}
package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
public class GroupConsumerImpl {
- public GroupConsumerImpl() {
-
+
+ protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
+ private GroupEventListener groupEventListener = new GroupEventListener();
+ private Registration<NotificationListener> groupListener;
+ private SalGroupService groupService;
+ private GroupDataCommitHandler commitHandler;
+
+ private ConcurrentMap<GroupKey, Group> originalSwGroupView;
+ private ConcurrentMap<GroupKey, Group> installedSwGroupView;
+
+ private ConcurrentMap<Node, List<Group>> nodeGroups;
+ private ConcurrentMap<GroupKey, Group> inactiveGroups;
+
+ private IClusterContainerServices clusterGroupContainerService = null;
+ private ISwitchManager switchGroupManager;
+ private IContainer container;
+
+ public GroupConsumerImpl() {
+ InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).toInstance();
+ groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
+
+ clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
+ switchGroupManager = FRMConsumerImpl.getSwitchManager();
+ container = FRMConsumerImpl.getContainer();
+
+ if (!(cacheStartup())) {
+ logger.error("Unanle to allocate/retrieve group cache");
+ System.out.println("Unable to allocate/retrieve group cache");
+ }
+
+ if (null == groupService) {
+ logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
+ System.out.println("Consumer SAL Group Service is down or NULL.");
+ return;
+ }
+
+ // For switch events
+ groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
+
+ if (null == groupListener) {
+ logger.error("Listener to listen on group data modifcation events");
+ System.out.println("Listener to listen on group data modifcation events.");
+ return;
+ }
+
+ commitHandler = new GroupDataCommitHandler();
+ FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
}
+
+ private boolean allocateGroupCaches() {
+ if (this.clusterGroupContainerService == null) {
+ logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache");
+ return false;
+ }
+
+ try {
+ clusterGroupContainerService.createCache("frm.originalSwGroupView",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ clusterGroupContainerService.createCache("frm.installedSwGroupView",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ clusterGroupContainerService.createCache("frm.inactiveGroups",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ clusterGroupContainerService.createCache("frm.nodeGroups",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+//TODO for cluster mode
+ /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
+
+ clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
+
+ } catch (CacheConfigException cce) {
+ logger.error("Group CacheConfigException");
+ return false;
+
+ } catch (CacheExistException cce) {
+ logger.error(" Group CacheExistException");
+ }
+
+ return true;
+ }
+
+ private void nonClusterGroupObjectCreate() {
+ originalSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+ installedSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+ nodeGroups = new ConcurrentHashMap<Node, List<Group>>();
+ inactiveGroups = new ConcurrentHashMap<GroupKey, Group>();
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private boolean retrieveGroupCaches() {
+ ConcurrentMap<?, ?> map;
+
+ if (this.clusterGroupContainerService == null) {
+ logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache");
+ nonClusterGroupObjectCreate();
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.originalSwGroupView");
+ if (map != null) {
+ originalSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+ } else {
+ logger.error("Retrieval of cache(originalSwGroupView) failed");
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.installedSwGroupView");
+ if (map != null) {
+ installedSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+ } else {
+ logger.error("Retrieval of cache(installedSwGroupView) failed");
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.inactiveGroups");
+ if (map != null) {
+ inactiveGroups = (ConcurrentMap<GroupKey, Group>) map;
+ } else {
+ logger.error("Retrieval of cache(inactiveGroups) failed");
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.nodeGroups");
+ if (map != null) {
+ nodeGroups = (ConcurrentMap<Node, List<Group>>) map;
+ } else {
+ logger.error("Retrieval of cache(nodeGroup) failed");
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean cacheStartup() {
+ if (allocateGroupCaches()) {
+ if (retrieveGroupCaches()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Status validateGroup(Group group, FRMUtil.operation operation) {
+ String containerName;
+ String groupName;
+ Iterator<Bucket> bucketIterator;
+ boolean returnResult;
+ Buckets groupBuckets;
+
+ if (null != group) {
+ containerName = group.getContainerName();
+
+ if (null == containerName) {
+ containerName = GlobalConstants.DEFAULT.toString();
+ }
+ else if (!FRMUtil.isNameValid(containerName)) {
+ logger.error("Container Name is invalid %s" + containerName);
+ return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
+ }
+
+ groupName = group.getGroupName();
+ if (!FRMUtil.isNameValid(groupName)) {
+ logger.error("Group Name is invalid %s" + groupName);
+ return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
+ }
+
+ returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
+
+ if (FRMUtil.operation.ADD == operation && returnResult) {
+ logger.error("Record with same Group Name exists");
+ return new Status(StatusCode.BADREQUEST, "Group record exists");
+ }
+ else if (!returnResult) {
+ logger.error("Group record does not exist");
+ return new Status(StatusCode.BADREQUEST, "Group record does not exist");
+ }
+
+ if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() &&
+ group.getGroupType().getIntValue() <= GroupType.GroupFf.getIntValue())) {
+ logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
+ return new Status(StatusCode.BADREQUEST, "Invalid Group type");
+ }
+
+ groupBuckets = group.getBuckets();
+
+ if (null != groupBuckets && null != groupBuckets.getBucket()) {
+ bucketIterator = groupBuckets.getBucket().iterator();
+
+ while (bucketIterator.hasNext()) {
+ if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) {
+ logger.error("Error in action bucket");
+ return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
+ }
+ }
+ }
+ }
+
+ return new Status(StatusCode.SUCCESS);
+
+ }
+
+ private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
+ if (! originalSwGroupView.containsKey(key)) {
+ return false;
+ }
+
+ for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
+ if (entry.getValue().getGroupName().equals(groupName)) {
+ if (entry.getValue().getContainerName().equals(containerName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Update Group entries to the southbound plugin/inventory and our internal database
+ *
+ * @param path
+ * @param dataObject
+ */
+ private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
+ GroupKey groupKey = groupUpdateDataObject.getKey();
+ Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
+
+ if (!groupOperationStatus.isSuccess()) {
+ logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
+ return groupOperationStatus;
+ }
+
+ originalSwGroupView.remove(groupKey);
+ originalSwGroupView.put(groupKey, groupUpdateDataObject);
+
+ if (groupUpdateDataObject.isInstall()) {
+ UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+ //TODO how to get original group and modified group.
+
+ if (installedSwGroupView.containsKey(groupKey)) {
+ installedSwGroupView.remove(groupKey);
+ }
+
+ installedSwGroupView.put(groupKey, groupUpdateDataObject);
+ groupService.updateGroup(groupData.build());
+ }
+
+ return groupOperationStatus;
+ }
+
+ /**
+ * Adds Group to the southbound plugin and our internal database
+ *
+ * @param path
+ * @param dataObject
+ */
+ private Status addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
+ GroupKey groupKey = groupAddDataObject.getKey();
+ Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+
+ if (!groupOperationStatus.isSuccess()) {
+ logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
+ return groupOperationStatus;
+ }
+ validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+ originalSwGroupView.put(groupKey, groupAddDataObject);
+
+ if (groupAddDataObject.isInstall()) {
+ AddGroupInputBuilder groupData = new AddGroupInputBuilder();
+ groupData.setBuckets(groupAddDataObject.getBuckets());
+ groupData.setContainerName(groupAddDataObject.getContainerName());
+ groupData.setGroupId(groupAddDataObject.getGroupId());
+ groupData.setGroupType(groupAddDataObject.getGroupType());
+ groupData.setNode(groupAddDataObject.getNode());
+ installedSwGroupView.put(groupKey, groupAddDataObject);
+ groupService.addGroup(groupData.build());
+ }
+
+ return groupOperationStatus;
+ }
+
+ private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
+ for(Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+
+ if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+ return Rpcs.getRpcResult(false, null, null);
+ }
+ }
+ for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+
+ if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+ return Rpcs.getRpcResult(false, null, null);
+ }
+ }
+
+ for(InstanceIdentifier<?> removal : transaction.removals) {
+ // removeFlow(removal);
+ }
+
+ return Rpcs.getRpcResult(true, null, null);
+ }
+
+ private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+ // We should verify transaction
+ System.out.println("Coming in FlowDatacommitHandler");
+ internalTransaction transaction = new internalTransaction(modification);
+ transaction.prepareUpdate();
+ return transaction;
+ }
+ }
+
+ private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+
+ private final DataModification<InstanceIdentifier<?>, DataObject> modification;
+
+ @Override
+ public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
+ return modification;
+ }
+
+ public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+ this.modification = modification;
+ }
+
+ Map<InstanceIdentifier<?>, Group> additions = new HashMap<>();
+ Map<InstanceIdentifier<?>, Group> updates = new HashMap<>();
+ Set<InstanceIdentifier<?>> removals = new HashSet<>();
+
+ /**
+ * We create a plan which flows will be added, which will be updated and
+ * which will be removed based on our internal state.
+ *
+ */
+ void prepareUpdate() {
+
+ Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
+ for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+ if (entry.getValue() instanceof Group) {
+ Group group = (Group) entry.getValue();
+ preparePutEntry(entry.getKey(), group);
+ }
+
+ }
+
+ removals = modification.getRemovedConfigurationData();
+ }
+
+ private void preparePutEntry(InstanceIdentifier<?> key, Group group) {
+
+ Group original = originalSwGroupView.get(key);
+ if (original != null) {
+ // It is update for us
+
+ updates.put(key, group);
+ } else {
+ // It is addition for us
+
+ additions.put(key, group);
+ }
+ }
+
+ /**
+ * We are OK to go with execution of plan
+ *
+ */
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+
+ RpcResult<Void> rpcStatus = commitToPlugin(this);
+ // We return true if internal transaction is successful.
+ // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+ return rpcStatus;
+ }
+
+ /**
+ *
+ * We should rollback our preparation
+ *
+ */
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ // NOOP - we did not modified any internal state during
+ // requestCommit phase
+ // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+ return Rpcs.getRpcResult(true, null, null);
+
+ }
+
+ }
+
+
+ final class GroupEventListener implements SalGroupListener {
+
+ List<GroupAdded> addedGroups = new ArrayList<>();
+ List<GroupRemoved> removedGroups = new ArrayList<>();
+ List<GroupUpdated> updatedGroups = new ArrayList<>();
+
+
+ @Override
+ public void onGroupAdded(GroupAdded notification) {
+ System.out.println("added Group..........................");
+ addedGroups.add(notification);
+ }
+
+ @Override
+ public void onGroupRemoved(GroupRemoved notification) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onGroupUpdated(GroupUpdated notification) {
+ // TODO Auto-generated method stub
+
+ }
+ }
}
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
+++ /dev/null
-<configuration scan="true">\r
-\r
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
- <encoder>\r
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
- </pattern>\r
- </encoder>\r
- </appender>\r
-\r
- <root level="error">\r
- <appender-ref ref="STDOUT" />\r
- </root>\r
-</configuration>\r
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
+++ /dev/null
-<configuration scan="true">\r
-\r
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
- <encoder>\r
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
- </pattern>\r
- </encoder>\r
- </appender>\r
-\r
- <root level="error">\r
- <appender-ref ref="STDOUT" />\r
- </root>\r
-</configuration>\r
</plugins>
</build>
<dependencies>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-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>sal</artifactId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>equinoxSDK381</groupId>
<artifactId>org.eclipse.osgi</artifactId>
--- /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.datastore;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface ClusteredDataStore extends DataReader<InstanceIdentifier<? extends Object>, Object>, DataCommitHandler<InstanceIdentifier<? extends Object>,Object> {
+}
package org.opendaylight.controller.datastore.internal;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.datastore.ClusteredDataStore;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Set;
+
public class Activator extends ComponentActivatorAbstractBase {
protected static final Logger logger = LoggerFactory
.getLogger(Activator.class);
+ @Override
+ protected Object[] getGlobalImplementations(){
+ logger.debug("Calling getGlobalImplementations to return:", ClusteredDataStoreManager.class);
+ return new Object[] {
+ ClusteredDataStoreManager.class
+ };
+ }
+
+
+ @Override
+ protected void configureGlobalInstance(Component c, Object imp){
+ if (imp.equals(ClusteredDataStoreManager.class)) {
+ Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+
+ c.setInterface(new String[] { ClusteredDataStore.class.getName() }, props);
+ logger.debug("configureGlobalInstance adding dependency:", IClusterGlobalServices.class);
+
+ c.add(createServiceDependency().setService(
+ IClusterGlobalServices.class).setCallbacks(
+ "setClusterGlobalServices",
+ "unsetClusterGlobalServices").setRequired(true));
+
+ }
+ }
+
}
+++ /dev/null
-package org.opendaylight.controller.datastore.internal;
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class ClusteredDataStore implements DataReader<InstanceIdentifier<? extends Object>, Object>, DataCommitHandler<InstanceIdentifier<? extends Object>,Object> {
- @Override
- public DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> requestCommit(DataModification<InstanceIdentifier<? extends Object>, Object> modification) {
- return null;
- }
-
- @Override
- public Object readOperationalData(InstanceIdentifier<? extends Object> path) {
- return null;
- }
-
- @Override
- public Object readConfigurationData(InstanceIdentifier<? extends Object> path) {
- return null;
- }
-}
--- /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.datastore.internal;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.datastore.ClusteredDataStore;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * The ClusteredDataStoreImpl stores global data to be shared across a controller cluster. It uses Clustering Services.
+ */
+public class ClusteredDataStoreImpl implements ClusteredDataStore {
+
+
+ public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache";
+ public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache";
+
+ private ConcurrentMap operationalDataCache;
+ private ConcurrentMap configurationDataCache;
+
+ public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheExistException, CacheConfigException {
+ Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null");
+
+ operationalDataCache = clusterGlobalServices.createCache(OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ if(operationalDataCache == null){
+ Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null");
+ }
+
+ configurationDataCache = clusterGlobalServices.createCache(CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ if(configurationDataCache == null){
+ Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null");
+ }
+
+ }
+
+ @Override
+ public DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> requestCommit(DataModification<InstanceIdentifier<? extends Object>, Object> modification) {
+ return new ClusteredDataStoreTransaction(modification);
+ }
+
+ @Override
+ public Object readOperationalData(InstanceIdentifier<? extends Object> path) {
+ Preconditions.checkNotNull(path, "path cannot be null");
+ return operationalDataCache.get(path);
+ }
+
+ @Override
+ public Object readConfigurationData(InstanceIdentifier<? extends Object> path) {
+ Preconditions.checkNotNull(path, "path cannot be null");
+ return configurationDataCache.get(path);
+ }
+
+ private RpcResult<Void> finish(final ClusteredDataStoreTransaction transaction) {
+ final DataModification<InstanceIdentifier<? extends Object>,Object> modification = transaction.getModification();
+
+ this.configurationDataCache.putAll(modification.getUpdatedConfigurationData());
+ this.operationalDataCache.putAll(modification.getUpdatedOperationalData());
+
+ for (final InstanceIdentifier<? extends Object> removal : modification.getRemovedConfigurationData()) {
+ this.configurationDataCache.remove(removal);
+ }
+
+ for (final InstanceIdentifier<? extends Object> removal : modification.getRemovedOperationalData()) {
+ this.operationalDataCache.remove(removal );
+ }
+
+ Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
+ return Rpcs.<Void>getRpcResult(true, null, _emptySet);
+ }
+
+ private RpcResult<Void> rollback(final ClusteredDataStoreTransaction transaction) {
+ Set<RpcError> _emptySet = Collections.<RpcError>emptySet();
+ return Rpcs.<Void>getRpcResult(true, null, _emptySet);
+ }
+
+ private class ClusteredDataStoreTransaction implements DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> {
+ private final DataModification<InstanceIdentifier<? extends Object>,Object> modification;
+
+ public ClusteredDataStoreTransaction(DataModification<InstanceIdentifier<? extends Object>,Object> modification){
+ Preconditions.checkNotNull(modification, "modification cannot be null");
+
+ this.modification = modification;
+ }
+
+ @Override
+ public DataModification<InstanceIdentifier<? extends Object>, Object> getModification() {
+ return this.modification;
+ }
+
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+ return ClusteredDataStoreImpl.this.finish(this);
+ }
+
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ return ClusteredDataStoreImpl.this.rollback(this);
+ }
+ }
+}
--- /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.datastore.internal;
+
+import com.google.common.base.Preconditions;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.datastore.ClusteredDataStore;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClusteredDataStoreManager implements ClusteredDataStore {
+
+ private ClusteredDataStoreImpl clusteredDataStore = null;
+ private IClusterGlobalServices clusterGlobalServices = null;
+
+ @Override
+ public DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> requestCommit(DataModification<InstanceIdentifier<? extends Object>, Object> modification) {
+ Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
+ return clusteredDataStore.requestCommit(modification);
+ }
+
+ @Override
+ public Object readOperationalData(InstanceIdentifier<? extends Object> path) {
+ Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
+ return clusteredDataStore.readOperationalData(path);
+ }
+
+ @Override
+ public Object readConfigurationData(InstanceIdentifier<? extends Object> path) {
+ Preconditions.checkState(clusteredDataStore != null, "clusteredDataStore cannot be null");
+ return clusteredDataStore.readConfigurationData(path);
+ }
+
+
+ public void setClusterGlobalServices(IClusterGlobalServices clusterGlobalServices){
+ this.clusterGlobalServices = clusterGlobalServices;
+ }
+
+ public void unsetClusterGlobalServices(IClusterGlobalServices clusterGlobalServices){
+ this.clusterGlobalServices = null;
+ this.clusteredDataStore = null;
+ }
+
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ try {
+ //Adding creation of the clustered data store in its own method to make the method unit testable
+ clusteredDataStore = createClusteredDataStore(c);
+ } catch (CacheExistException e) {
+ throw new IllegalStateException("could not construct clusteredDataStore");
+ } catch (CacheConfigException e) {
+ throw new IllegalStateException("could not construct clusteredDataStore");
+ }
+ }
+ protected ClusteredDataStoreImpl createClusteredDataStore(Component c) throws CacheExistException,CacheConfigException{
+ return new ClusteredDataStoreImpl(clusterGlobalServices);
+ }
+}
+
+/*
+ * 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.datastore.internal;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ServiceDependency;
+
+import org.junit.BeforeClass;
import org.junit.Test;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ActivatorTest {
+ private static ServiceDependency serviceDependency;
+
+ @BeforeClass
+ public static void initialize(){
+ serviceDependency = mock(ServiceDependency.class);
+ }
+
+ private class ActivatorTestImpl extends Activator{
+ protected ServiceDependency createServiceDependency() {
+ return ActivatorTest.serviceDependency;
+ }
+ }
+
@Test
public void construct(){
assertNotNull(new Activator());
}
+
+ @Test
+ public void construct_OnInvokeOfGlobalImpl_ShouldReturnNotNullObject(){
+ Activator activator = new Activator();
+
+ assertNotNull(activator.getGlobalImplementations());
+ assertEquals(ClusteredDataStoreManager.class,activator.getGlobalImplementations()[0]);
+ }
+
+ @Test
+ public void construct_OnInvokeOfConfigGlobalInstance_ShouldNotThrowAnyExceptions(){
+ Activator activator = new ActivatorTestImpl();
+
+ Component c = mock(Component.class);
+ Object clusterDataStoreMgr = ClusteredDataStoreManager.class;
+
+ when(serviceDependency.setService(IClusterGlobalServices.class)).thenReturn(serviceDependency);
+ when(serviceDependency.setCallbacks("setClusterGlobalServices",
+ "unsetClusterGlobalServices")).thenReturn(serviceDependency);
+ when(serviceDependency.setRequired(true)).thenReturn(serviceDependency);
+
+
+ activator.configureGlobalInstance(c, clusterDataStoreMgr);
+
+
+ }
+
}
--- /dev/null
+package org.opendaylight.controller.datastore.internal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ClusteredDataStoreImplTest {
+ @Before
+ public void setUp(){
+
+ }
+
+ @Test
+ public void constructor_WhenPassedANullClusteringServices_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+ try {
+ new ClusteredDataStoreImpl(null);
+ } catch(NullPointerException npe){
+ assertEquals("clusterGlobalServices cannot be null", npe.getMessage());
+ }
+ }
+
+ @Test
+ public void constructor_WhenClusteringServicesReturnsANullOperationalDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+ try {
+ new ClusteredDataStoreImpl(mock(IClusterGlobalServices.class));
+ } catch(NullPointerException npe){
+ assertEquals("operationalDataCache cannot be null", npe.getMessage());
+ }
+ }
+
+ @Test
+ public void constructor_WhenClusteringServicesReturnsANullOConfigurationDataCache_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+ // Confused about the following line?
+ // See this http://stackoverflow.com/questions/10952629/a-strange-generics-edge-case-with-mockito-when-and-generic-type-inference
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+
+ try {
+ new ClusteredDataStoreImpl(mockClusterGlobalServices);
+ } catch(NullPointerException npe){
+ assertEquals("configurationDataCache cannot be null", npe.getMessage());
+ }
+ }
+
+ @Test
+ public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ new ClusteredDataStoreImpl(mockClusterGlobalServices);
+ }
+
+
+ @Test
+ public void readOperationalData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ try {
+ store.readOperationalData(null);
+ } catch(NullPointerException npe){
+ assertEquals("path cannot be null", npe.getMessage());
+ }
+ }
+
+ @Test
+ public void readOperationalData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
+ InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ assertNull(store.readOperationalData(path));
+ }
+
+ @Test
+ public void readOperationalData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
+ InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
+
+ Object valueObject = mock(Object.class);
+
+ when(mockOperationalDataCache.get(path)).thenReturn(valueObject);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ assertEquals(valueObject, store.readOperationalData(path));
+ }
+
+
+
+ @Test
+ public void readConfigurationData_WhenPassedANullPath_ShouldThrowANullPointerException() throws CacheExistException, CacheConfigException {
+
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ try {
+ store.readConfigurationData(null);
+ } catch(NullPointerException npe){
+ assertEquals("path cannot be null", npe.getMessage());
+ }
+ }
+
+
+ @Test
+ public void readConfigurationData_WhenPassedAKeyThatDoesNotExistInTheCache_ShouldReturnNull() throws CacheExistException, CacheConfigException {
+ InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ assertNull(store.readConfigurationData(path));
+ }
+
+ @Test
+ public void readConfigurationData_WhenPassedAKeyThatDoesExistInTheCache_ShouldReturnTheValueObject() throws CacheExistException, CacheConfigException {
+ InstanceIdentifier path = InstanceIdentifier.builder().toInstance();
+
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
+
+ Object valueObject = mock(Object.class);
+
+ when(mockConfigurationDataCache.get(path)).thenReturn(valueObject);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
+
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ assertEquals(valueObject, store.readConfigurationData(path));
+ }
+
+
+ @Test
+ public void requestCommit_ShouldReturnADataTransaction() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ assertNotNull(store.requestCommit(mock(DataModification.class)));
+
+
+ }
+
+ @Test
+ public void finishingADataTransaction_ShouldUpdateTheUnderlyingCache() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+ ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
+ ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ DataModification mockModification = mock(DataModification.class);
+
+ Map configurationData = mock(Map.class);
+ Map operationalData = mock(Map.class);
+
+ when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
+ when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
+
+ DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> transaction = store.requestCommit(mockModification);
+
+ transaction.finish();
+
+ verify(mockConfigurationDataCache).putAll(mockModification.getUpdatedConfigurationData());
+ verify(mockOperationalDataCache).putAll(mockModification.getUpdatedOperationalData());
+ }
+
+
+ @Test
+ public void rollingBackADataTransaction_ShouldDoNothing() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+ ConcurrentMap mockConfigurationDataCache = mock(ConcurrentMap.class);
+ ConcurrentMap mockOperationalDataCache = mock(ConcurrentMap.class);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockOperationalDataCache);
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mockConfigurationDataCache);
+
+ ClusteredDataStoreImpl store = new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ DataModification mockModification = mock(DataModification.class);
+
+ Map configurationData = mock(Map.class);
+ Map operationalData = mock(Map.class);
+
+ when(mockModification.getUpdatedConfigurationData()).thenReturn(configurationData);
+ when(mockModification.getUpdatedOperationalData()).thenReturn(operationalData);
+
+ DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> transaction = store.requestCommit(mockModification);
+
+ transaction.rollback();
+
+ verify(mockConfigurationDataCache, never()).putAll(mockModification.getUpdatedConfigurationData());
+ verify(mockOperationalDataCache, never()).putAll(mockModification.getUpdatedOperationalData());
+
+ }
+
+
+ private IClusterGlobalServices createClusterGlobalServices() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL))).thenReturn(mock(ConcurrentMap.class));
+
+ return mockClusterGlobalServices;
+ }
+}
--- /dev/null
+package org.opendaylight.controller.datastore.internal;
+
+import org.apache.felix.dm.Component;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+public class ClusteredDataStoreManagerTest {
+
+ private static ClusteredDataStoreManager clusteredDSMgr = null;
+ private IClusterGlobalServices icClusterGlbServices = mock(IClusterGlobalServices.class);
+
+ @BeforeClass
+ public static void construct(){
+ clusteredDSMgr = new ClusteredDataStoreManager();
+ assertNotNull(clusteredDSMgr);
+ }
+
+ @Test
+ public void construct_OnSetClusterGlobalServices_AssertNoException(){
+ icClusterGlbServices = mock(IClusterGlobalServices.class);
+
+ clusteredDSMgr.setClusterGlobalServices(icClusterGlbServices);
+ }
+
+ @Test
+ public void construct_OnUnSetClusterGlobalServices_AssertNoException(){
+ IClusterGlobalServices icClusterGlbServices = mock(IClusterGlobalServices.class);
+
+ clusteredDSMgr.unsetClusterGlobalServices(icClusterGlbServices);
+ }
+
+ @Test
+ public void construct_init_AssertNoException() throws CacheExistException,CacheConfigException{
+ ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
+
+ ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+ doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+ Component c = mock(Component.class);
+
+ clusteredDSManager.init(c);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void construct_init_AssertCacheExistException() throws CacheExistException,CacheConfigException{
+ ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+ doThrow(CacheExistException.class).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+ Component c = mock(Component.class);
+
+ clusteredDSManager.init(c);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void construct_init_AssertCacheConfigException() throws CacheExistException,CacheConfigException{
+ ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+ doThrow(CacheConfigException.class).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+ Component c = mock(Component.class);
+
+ clusteredDSManager.init(c);
+ }
+
+ @Test
+ public void construct_readOperationalData_AssertNoException() throws CacheExistException,CacheConfigException{
+ ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
+
+ ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+ doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+ Component c = mock(Component.class);
+
+ clusteredDSManager.init(c);
+
+ Object o = mock(Object.class);
+
+ when(clusteredDSImpl.readOperationalData(any(InstanceIdentifier.class))).thenReturn(o);
+ assertEquals(o,clusteredDSManager.readOperationalData(any(InstanceIdentifier.class)));
+ }
+
+
+ @Test
+ public void construct_readConfigurationData_AssertNoException() throws CacheExistException,CacheConfigException{
+ ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
+
+ ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+ doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+ Component c = mock(Component.class);
+
+ clusteredDSManager.init(c);
+ Object o = mock(Object.class);
+
+ when(clusteredDSImpl.readConfigurationData(any(InstanceIdentifier.class))).thenReturn(o);
+ assertEquals(o,clusteredDSManager.readConfigurationData(any(InstanceIdentifier.class)));
+ }
+
+ @Test
+ public void construct_requestCommit_AssertNoException() throws CacheExistException,CacheConfigException{
+ ClusteredDataStoreImpl clusteredDSImpl = mock(ClusteredDataStoreImpl.class);
+
+ ClusteredDataStoreManager clusteredDSManager = spy(new ClusteredDataStoreManager());
+ doReturn(clusteredDSImpl).when(clusteredDSManager).createClusteredDataStore(any(Component.class));
+ Component c = mock(Component.class);
+
+ clusteredDSManager.init(c);
+ DataCommitTransaction dataCommitTransaction = mock(DataCommitTransaction.class);
+
+ when(clusteredDSImpl.requestCommit(any(DataModification.class))).thenReturn(dataCommitTransaction);
+ assertEquals(dataCommitTransaction,clusteredDSManager.requestCommit(any(DataModification.class)));
+ }
+}
+++ /dev/null
-package org.opendaylight.controller.datastore.internal;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertNotNull;
-
-public class ClusteredDataStoreTest {
- @Test
- public void construct(){
- assertNotNull(new ClusteredDataStore());
- }
-}
type string;
}
+ leaf barrier {
+ type boolean;
+ }
+
container buckets {
list bucket {
key "order";
type meter-id;
}
+ leaf install {
+ type boolean;
+ }
+ leaf meter-name {
+ type string;
+ }
+
+ leaf container-name {
+ type string;
+ }
+
container meter-band-headers {
list meter-band-header {
key "order";
}
typedef port-state {
- type enumeration {
- enum link-down;
- enum blocked;
- enum live;
+ type enumeration {
+ enum link-down;
+ enum blocked;
+ enum live;
}
}
uses common-port;
leaf mask {
- type uint32;
+ type port-config;
description "Bitmap of OFPPC-* flags to be changed";
}
leaf port-name {
type string;
- }
+ }
+
+ leaf barrier {
+ type boolean;
+ }
}
}
}
}
grouping meter-entry {
-
leaf node {
type inv:node-ref;
}
-
uses meter:meter;
}
--- /dev/null
+module flow-capable-transaction {
+ namespace "urn:opendaylight:flow:transaction";
+ prefix type;
+
+ import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+
+ revision "2013-11-03" {
+ description "Initial revision";
+ }
+
+ typedef transaction-id {
+ type uint64;
+ }
+
+ grouping transaction-aware {
+ leaf transaction-id {
+ type transaction-id;
+ }
+ }
+
+ rpc get-next-transaction-id {
+ input {
+ leaf node {
+ ext:context-reference "inv:node-context";
+ type inv:node-ref;
+ }
+ }
+ output {
+ uses transaction-aware;
+ }
+ }
+
+ // Barier request?
+ rpc finish-transaction {
+ input {
+ leaf node {
+ ext:context-reference "inv:node-context";
+ type inv:node-ref;
+ }
+ leaf transaction-id {
+ type transaction-id;
+ }
+ }
+ }
+}
\ No newline at end of file
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;}
+ import flow-capable-transaction {prefix tr;}
revision "2013-09-18" {
description "Initial revision of group service";
}
grouping node-group {
- uses "inv:node-context-ref";
-
+ uses "inv:node-context-ref";
uses group-type:group;
}
rpc add-group {
input {
uses node-group;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc remove-group {
input {
uses group-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc update-group {
input {
uses group-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
import yang-ext {prefix ext; revision-date "2013-07-09";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";}
+ import flow-capable-transaction {prefix tr;}
revision "2013-09-18" {
description "Initial revision of meter service";
rpc add-meter {
input {
uses node-meter;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc remove-meter {
input {
uses node-meter;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc update-meter {
input {
uses meter-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
--- /dev/null
+module sal-port {
+ namespace "urn:opendaylight:port:service";
+ prefix port;
+
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+ import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+ import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+
+ revision "2013-11-07" {
+ description "Initial revision of port service";
+ }
+
+ grouping node-port {
+ uses "inv:node-context-ref";
+
+ uses port-type:ofp-port-mod;
+ }
+
+ /** Base configuration structure **/
+ grouping port-update {
+ uses "inv:node-context-ref";
+
+ container original-port {
+ uses port-type:ofp-port-mod;
+ }
+ container updated-port {
+ uses port-type:ofp-port-mod;
+ }
+ }
+
+ rpc update-port {
+ input {
+ uses port-update;
+ }
+ }
+
+ rpc get-port {
+ output {
+ uses port-type:flow-capable-port;
+ }
+ }
+
+ notification port-removed {
+ uses node-port;
+ }
+}
\ No newline at end of file
import yang-ext {prefix ext; revision-date "2013-07-09";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
+ import flow-capable-transaction {prefix tr;}
revision "2013-10-26" {
description "Initial revision of table service";
- }
+ }
/** Base configuration structure **/
grouping table-update {
+ uses "inv:node-context-ref";
container original-table {
uses table-type:table-features;
}
rpc update-table {
input {
- leaf node {
- ext:context-reference "inv:node-context";
- type inv:node-ref;
- }
uses table-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
}
\ No newline at end of file
<module>compatibility</module>
<module>sal-zeromq-connector</module>
- <module>test</module>
</modules>
<modules>
<module>sal-binding-it</module>
<module>clustered-data-store/integrationtest</module>
+ <module>test</module>
</modules>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
- <!--This plugin's configuration is used to store Eclipse
- m2e settings only. It has no influence on the Maven build itself. -->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.jacoco</groupId>
- <artifactId>jacoco-maven-plugin</artifactId>
- <versionRange>[0.0,)</versionRange>
- <goals>
- <goal>prepare-agent</goal>
- <goal>pre-test</goal>
- <goal>post-test</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <ignore />
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
- <groupId>
- org.opendaylight.yangtools
- </groupId>
- <artifactId>
- yang-maven-plugin
- </artifactId>
- <versionRange>
- [0.5,)
- </versionRange>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore/>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>scala-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
<goals>
- <goal>
- generate-sources
- </goal>
+ <goal>compile</goal>
+ <goal>testCompile</goal>
</goals>
</pluginExecutionFilter>
<action>
- <ignore></ignore>
+ <ignore/>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.jacoco</groupId>
- <artifactId>
- jacoco-maven-plugin
- </artifactId>
- <versionRange>
- [0.5.3.201107060350,)
- </versionRange>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
<goals>
<goal>prepare-agent</goal>
</goals>
</pluginExecutionFilter>
<action>
- <ignore></ignore>
+ <ignore/>
</action>
</pluginExecution>
</pluginExecutions>
<build>
<plugins>
+
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-maven-plugin</artifactId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-jmx-generator-plugin</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
+
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>${osgi.core.version}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>javassist</artifactId>
<version>3.17.1-GA</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>binding-generator-impl</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <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-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.standalone</artifactId>
+ <version>2.4.3</version>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-model-util</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.*
import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
import java.util.HashSet
-import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker
import java.util.Set
import org.opendaylight.yangtools.yang.binding.BaseIdentity
import com.google.common.collect.Multimap
import com.google.common.collect.HashMultimap
-import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.*
+import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.*
import java.util.concurrent.Executors
import java.util.Collections
import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.controller.sal.binding.impl.connect.dom.ConnectorActivator
class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable {
private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl)
ServiceRegistration<DataBrokerService> dataConsumerRegistration
- private HashMapDataStore store = new HashMapDataStore();
+ ConnectorActivator connectorActivator
+
public new(BundleContext bundleContext) {
_brokerBundleContext = bundleContext;
notifyConsumerRegistration = brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties)
dataProviderRegistration = brokerBundleContext.registerService(DataProviderService, dataBroker, brokerProperties)
dataConsumerRegistration = brokerBundleContext.registerService(DataBrokerService, dataBroker, brokerProperties)
-
-
- getDataBroker().registerDataReader(root, store);
- getDataBroker().registerCommitHandler(root, store)
-
+
+ connectorActivator = new ConnectorActivator(dataBroker,brokerBundleContext);
+ connectorActivator.start();
log.info("MD-SAL: Binding Aware Broker Started");
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
+import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+
+public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier<? extends DataObject>, DataObject, DataChangeListener> implements
+ DataProviderService {
+
+ public DataBrokerImpl() {
+ setDataReadRouter(new BindingAwareDataReaderRouter());
+ }
+
+ @Override
+ public DataTransactionImpl beginTransaction() {
+ return new DataTransactionImpl(this);
+ }
+
+ @Override
+ public <T extends DataRoot> T getData(DataStoreIdentifier store, Class<T> rootType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public <T extends DataRoot> T getData(DataStoreIdentifier store, T filter) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, T filter) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public RpcResult<DataRoot> editCandidateData(DataStoreIdentifier store, DataRoot changeSet) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> commit(DataStoreIdentifier store) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public DataObject getData(InstanceIdentifier<? extends DataObject> data) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public DataObject getConfigurationData(InstanceIdentifier<?> data) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void registerChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener changeListener) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void unregisterChangeListener(InstanceIdentifier<? extends DataObject> path,
+ DataChangeListener changeListener) {
+ // TODO Auto-generated method stub
+
+ }
+
+
+}
\ No newline at end of file
+++ /dev/null
-package org.opendaylight.controller.sal.binding.impl
-
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.controller.sal.binding.api.data.DataChangeListener
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import com.google.common.collect.Multimap
-import static com.google.common.base.Preconditions.*;
-import java.util.List
-import com.google.common.collect.HashMultimap
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Callable
-import org.opendaylight.yangtools.yang.common.RpcResult
-import org.opendaylight.controller.sal.common.util.Rpcs
-import java.util.Collections
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
-import java.util.ArrayList
-import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter
-import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
-import java.util.Arrays
-
-class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService {
-
- @Property
- var ExecutorService executor;
-
- val dataReadRouter = new BindingAwareDataReaderRouter;
-
- Multimap<InstanceIdentifier, DataChangeListenerRegistration> listeners = HashMultimap.create();
- Multimap<InstanceIdentifier, DataCommitHandlerRegistration> commitHandlers = HashMultimap.create();
-
- override beginTransaction() {
- return new DataTransactionImpl(this);
- }
-
- override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
- return dataReadRouter.readConfigurationData(path);
- }
-
- override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
- return dataReadRouter.readOperationalData(path);
- }
-
- override registerCommitHandler(InstanceIdentifier<? extends DataObject> path,
- DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
- val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
- commitHandlers.put(path,registration)
- return registration;
- }
-
- override registerDataChangeListener(InstanceIdentifier<? extends DataObject> path, DataChangeListener listener) {
- val reg = new DataChangeListenerRegistration(path, listener, this);
- listeners.put(path, reg);
- return reg;
- }
-
- override registerDataReader(InstanceIdentifier<? extends DataObject> path,DataReader<InstanceIdentifier<? extends DataObject>,DataObject> reader) {
-
- val confReg = dataReadRouter.registerConfigurationReader(path,reader);
- val dataReg = dataReadRouter.registerOperationalReader(path,reader);
-
- return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
- }
-
- protected def removeListener(DataChangeListenerRegistration registration) {
- listeners.remove(registration.path, registration);
- }
-
- protected def removeCommitHandler(DataCommitHandlerRegistration registration) {
- commitHandlers.remove(registration.path, registration);
- }
-
- protected def getActiveCommitHandlers() {
- return commitHandlers.entries.map[ value.instance].toSet
- }
-
- protected def commit(DataTransactionImpl transaction) {
- checkNotNull(transaction);
- transaction.changeStatus(TransactionStatus.SUBMITED);
- val task = new TwoPhaseCommit(transaction, this);
- return executor.submit(task);
- }
-
-}
-
-package class DataChangeListenerRegistration extends AbstractObjectRegistration<DataChangeListener> implements ListenerRegistration<DataChangeListener> {
-
- DataBrokerImpl dataBroker;
-
- @Property
- val InstanceIdentifier<?> path;
-
- new(InstanceIdentifier<?> path, DataChangeListener instance, DataBrokerImpl broker) {
- super(instance)
- dataBroker = broker;
- _path = path;
- }
-
- override protected removeRegistration() {
- dataBroker.removeListener(this);
- dataBroker = null;
- }
-
-}
-
-package class DataCommitHandlerRegistration //
-extends AbstractObjectRegistration<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> {
-
- DataBrokerImpl dataBroker;
-
- @Property
- val InstanceIdentifier<?> path;
-
- new(InstanceIdentifier<?> path, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> instance,
- DataBrokerImpl broker) {
- super(instance)
- dataBroker = broker;
- _path = path;
- }
-
- override protected removeRegistration() {
- dataBroker.removeCommitHandler(this);
- dataBroker = null;
- }
-
-}
-
-package class TwoPhaseCommit implements Callable<RpcResult<TransactionStatus>> {
-
- val DataTransactionImpl transaction;
- val DataBrokerImpl dataBroker;
-
- new(DataTransactionImpl transaction, DataBrokerImpl broker) {
- this.transaction = transaction;
- this.dataBroker = broker;
- }
-
- override call() throws Exception {
-
- val Iterable<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> commitHandlers = dataBroker.activeCommitHandlers;
-
- // requesting commits
- val List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> handlerTransactions = new ArrayList();
- try {
- for (handler : commitHandlers) {
- handlerTransactions.add(handler.requestCommit(transaction));
- }
- } catch (Exception e) {
- return rollback(handlerTransactions,e);
- }
- val List<RpcResult<Void>> results = new ArrayList();
- try {
- for (subtransaction : handlerTransactions) {
- results.add(subtransaction.finish());
- }
- } catch (Exception e) {
- return rollback(handlerTransactions,e);
- }
-
- return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
- }
-
- def rollback(List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> transactions,Exception e) {
- for (transaction : transactions) {
- transaction.rollback()
- }
- // FIXME return encoutered error.
- return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
- }
-}
package org.opendaylight.controller.sal.binding.impl;
-import java.util.concurrent.Future;
-
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
-import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public class DataTransactionImpl extends AbstractDataModification<InstanceIdentifier<? extends DataObject>, DataObject>
- implements DataModificationTransaction {
-
- private final Object identifier;
-
- private TransactionStatus status;
- private ListenerRegistry<DataTransactionListener> listeners;
-
- final DataBrokerImpl broker;
+public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentifier<? extends DataObject>, DataObject>
+ implements DataModificationTransaction {
+ private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
+
+
+
public DataTransactionImpl(DataBrokerImpl dataBroker) {
super(dataBroker);
- identifier = new Object();
- broker = dataBroker;
- status = TransactionStatus.NEW;
- listeners = new ListenerRegistry<>();
- }
-
- @Override
- public Future<RpcResult<TransactionStatus>> commit() {
- return broker.commit(this);
- }
-
- @Override
- public DataObject readConfigurationData(
- org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject> path) {
- return broker.readConfigurationData(path);
- }
-
- @Override
- public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
- return broker.readOperationalData(path);
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((broker == null) ? 0 : broker.hashCode());
- result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- DataTransactionImpl other = (DataTransactionImpl) obj;
- if (broker == null) {
- if (other.broker != null)
- return false;
- } else if (!broker.equals(other.broker))
- return false;
- if (identifier == null) {
- if (other.identifier != null)
- return false;
- } else if (!identifier.equals(other.identifier))
- return false;
- return true;
- }
-
- @Override
- public TransactionStatus getStatus() {
- return status;
- }
-
- @Override
- public Object getIdentifier() {
- return identifier;
}
@Override
return listeners.register(listener);
}
- public void changeStatus(TransactionStatus status) {
- this.status = status;
- Iterable<ListenerRegistration<DataTransactionListener>> listenersToNotify = listeners.getListeners();
- for (ListenerRegistration<DataTransactionListener> listenerRegistration : listenersToNotify) {
+ protected void onStatusChange(TransactionStatus status) {
+ for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
listenerRegistration.getInstance().onStatusUpdated(this, status);
}
}
-}
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.base.Preconditions;
+
+public class BindingIndependentDataServiceConnector implements //
+ RuntimeDataProvider, //
+ DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
+
+ private BindingIndependentMappingService mappingService;
+
+ private DataBrokerService biDataService;
+
+ private DataProviderService baDataService;
+
+ @Override
+ public DataObject readOperationalData(InstanceIdentifier<? extends DataObject> path) {
+ // TODO Auto-generated method stub
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+ CompositeNode result = biDataService.readOperationalData(biPath);
+ return mappingService.dataObjectFromDataDom(path, result);
+ }
+
+ @Override
+ public DataObject readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path);
+ CompositeNode result = biDataService.readConfigurationData(biPath);
+ return mappingService.dataObjectFromDataDom(path, result);
+ }
+
+ @Override
+ public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> requestCommit(
+ DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+
+ DataModificationTransaction translated = translateTransaction(modification);
+ return new WrappedTransaction(translated, modification);
+ }
+
+ private DataModificationTransaction translateTransaction(
+ DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
+ DataModificationTransaction target = biDataService.beginTransaction();
+ for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
+ .entrySet()) {
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+ .toDataDom(entry);
+ target.putConfigurationData(biEntry.getKey(), biEntry.getValue());
+ }
+ for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedOperationalData()
+ .entrySet()) {
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
+ .toDataDom(entry);
+ target.putOperationalData(biEntry.getKey(), biEntry.getValue());
+ }
+ for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+ target.removeConfigurationData(biEntry);
+ }
+ for(InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+ target.removeOperationalData(biEntry);
+ }
+ return target;
+ }
+
+ private class WrappedTransaction implements
+ DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+ private DataModificationTransaction backing;
+ private DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
+
+ public WrappedTransaction(DataModificationTransaction backing,
+ DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
+ this.backing = backing;
+ this.modification = modification;
+ }
+
+ @Override
+ public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
+ return modification;
+ }
+
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+ Future<RpcResult<TransactionStatus>> result = backing.commit();
+ try {
+ RpcResult<TransactionStatus> biresult = result.get();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("", e);
+ } catch (ExecutionException e) {
+ throw new IllegalStateException("", e);
+ }
+ return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+ }
+
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ // backing.cancel();
+ return Rpcs.<Void> getRpcResult(true, null, Collections.<RpcError> emptySet());
+ }
+
+ }
+
+ public DataBrokerService getBiDataService() {
+ return biDataService;
+ }
+
+ public void setBiDataService(DataBrokerService biDataService) {
+ this.biDataService = biDataService;
+ }
+
+ public DataProviderService getBaDataService() {
+ return baDataService;
+ }
+
+ public void setBaDataService(DataProviderService baDataService) {
+ this.baDataService = baDataService;
+ }
+
+ public void start() {
+ baDataService.registerDataReader(ROOT, this);
+ baDataService.registerCommitHandler(ROOT, this);
+ }
+
+ public void setMappingService(BindingIndependentMappingService mappingService) {
+ this.mappingService = mappingService;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Map.Entry;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface BindingIndependentMappingService {
+
+ CompositeNode toDataDom(DataObject data);
+
+ Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry);
+
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier<? extends DataObject> path);
+
+ DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result);
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class BindingIndependentRpcConnector {
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext
+import java.util.List
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil
+import org.opendaylight.yangtools.binding.generator.util.Types
+import java.util.HashMap
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataContainer
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import java.util.Collections
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import com.google.common.collect.FluentIterable
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
+
+class BindingMapping {
+
+ val Map<Type, GeneratedTypeBuilder> typeToDefinition = new HashMap();
+ val Map<Type, SchemaNode> typeToSchemaNode = new HashMap();
+
+ def QName getSchemaNode(Class<?> cls) {
+ val ref = Types.typeForClass(cls);
+ return typeToSchemaNode.get(ref)?.QName;
+ }
+
+ def void updateBinding(SchemaContext schemaContext, ModuleContext moduleBindingContext) {
+ updateBindingFor(moduleBindingContext.childNodes, schemaContext);
+
+ }
+
+ def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+ InstanceIdentifier<? extends DataObject> obj) {
+ val pathArguments = obj.path;
+ var Class<? extends DataObject> parent;
+ val dataDomArgs = new ArrayList<PathArgument>();
+ for (pathArgument : pathArguments) {
+ dataDomArgs.add(pathArgument.toDataDomPathArgument(parent));
+ parent = pathArgument.type;
+ }
+
+ return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs);
+ }
+
+
+
+ def DataObject dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> identifier, CompositeNode node) {
+ if (node == null) {
+ return null;
+ }
+ val targetClass = identifier.targetType;
+ val classLoader = targetClass.classLoader;
+ val ref = Types.typeForClass(targetClass);
+ val targetType = typeToDefinition.get(ref);
+ val targetSchema = typeToSchemaNode.get(ref);
+ return node.toDataObject(classLoader, targetType.toInstance, targetSchema);
+
+ }
+
+ def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class<? extends DataObject> parent) {
+ val Class rawType = argument.type;
+ val ref = Types.typeForClass(rawType);
+ val schemaType = typeToSchemaNode.get(ref);
+ val qname = schemaType.QName
+
+ val Object key = argument.key;
+ val predicates = key.toPredicates(schemaType as ListSchemaNode);
+
+ return new NodeIdentifierWithPredicates(qname, predicates);
+ }
+
+ def dispatch PathArgument toDataDomPathArgument(Item<?> argument, Class<? extends DataObject> parent) {
+ val ref = Types.typeForClass(argument.type);
+ val qname = typeToSchemaNode.get(ref).QName
+ return new NodeIdentifier(qname);
+ }
+
+ def Map<QName, Object> toPredicates(Object identifier, ListSchemaNode node) {
+ val keyDefinitions = node.keyDefinition;
+ val map = new HashMap<QName, Object>();
+ for (keydef : keyDefinitions) {
+ val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode;
+ val value = identifier.getSimpleValue(keydef, keyNode.type);
+ map.put(keydef, value.value);
+ }
+ return map;
+ }
+
+ def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+ for (entry : map.entrySet) {
+ val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
+ typeToDefinition.put(entry.value, entry.value);
+ typeToSchemaNode.put(entry.value, schemaNode)
+ }
+ }
+
+ def CompositeNode toCompositeNode(DataContainer data) {
+ val type = data.implementedInterface;
+ val typeRef = Types.typeForClass(type);
+ val schemaNode = typeToSchemaNode.get(typeRef);
+ val generatedType = typeToDefinition.get(typeRef);
+
+ return data.toDataDom(schemaNode, generatedType);
+ }
+
+ private def dispatch CompositeNode toDataDom(DataContainer data, ContainerSchemaNode node,
+ GeneratedTypeBuilder builder) {
+ val subnodes = data.toDataDomComponents(node);
+ return new CompositeNodeTOImpl(node.QName, null, subnodes);
+ }
+
+ private def dispatch CompositeNode toDataDom(DataContainer data, NotificationDefinition node,
+ GeneratedTypeBuilder builder) {
+ val subnodes = data.toDataDomComponents(node);
+ return new CompositeNodeTOImpl(node.QName, null, subnodes);
+ }
+
+ private def dispatch CompositeNode toDataDom(DataContainer data, ListSchemaNode node,
+ GeneratedTypeBuilder builder) {
+ val subnodes = data.toDataDomComponents(node);
+ return new CompositeNodeTOImpl(node.QName, null, subnodes);
+ }
+
+ private def List<Node<?>> toDataDomComponents(DataContainer data, DataNodeContainer node) {
+ val subnodes = new ArrayList<Node<?>>();
+ for (childNode : node.childNodes) {
+ val value = childNode.dataDomFromParent(data);
+ if (value !== null) {
+ subnodes.addAll(value);
+ }
+ }
+ return subnodes;
+ }
+
+ private def List<Node<?>> dataDomFromParent(DataSchemaNode node, DataContainer container) {
+ if (node.augmenting) {
+ return Collections.emptyList();
+ }
+ return dataDomFromParentImpl(node, container);
+ }
+
+ private def dispatch List<Node<?>> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) {
+ val value = container.getSimpleValue(node.QName, node.type);
+ if (value !== null) {
+ return Collections.<Node<?>>singletonList(value);
+ }
+ return Collections.emptyList();
+ }
+
+ private def dispatch List<Node<?>> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) {
+ val values = container.getSimpleValues(node);
+ if (values !== null) {
+ //val it = new ArrayList<Node<?>>();
+ //for (value : values) {
+ //}
+
+ }
+ return Collections.emptyList();
+ }
+
+ def getSimpleValues(DataContainer container, LeafListSchemaNode node) {
+ return Collections.emptyList();
+ }
+
+ private def dispatch List<Node<?>> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) {
+ val qname = node.QName;
+ val values = container.<List>getValue(qname, List) as List<? extends DataContainer>;
+ if (values === null) {
+ return Collections.emptyList;
+ }
+ val it = new ArrayList<Node<?>>();
+ for (value : values) {
+ add(value.toCompositeNode());
+ }
+
+ return it;
+ }
+
+ private def dispatch List<Node<?>> dataDomFromParentImpl(ChoiceNode node, DataContainer container) {
+ }
+
+ private def dispatch List<Node<?>> serializeValueImpl(List<?> list, GeneratedTypeBuilder builder,
+ ListSchemaNode node) {
+ val it = new ArrayList<Node<?>>();
+ for (value : list) {
+
+ val serVal = value.serializeValueImpl(builder, node);
+ if (serVal !== null) {
+ addAll(serVal);
+ }
+ }
+ return it;
+ }
+
+ private def dispatch Node<?> getSimpleValue(Object container, QName name, ExtendedType type) {
+ getSimpleValue(container, name, type.baseType);
+ }
+
+ private def dispatch Node<?> getSimpleValue(Object container, QName name, StringTypeDefinition type) {
+ val value = container.getValue(name, String);
+ if(value === null) return null;
+ return new SimpleNodeTOImpl(name, null, value);
+ }
+
+ private def dispatch Node<?> getSimpleValue(Object container, QName name, TypeDefinition<?> type) {
+ val value = container.getValue(name, Object);
+ if(value === null) return null;
+ return new SimpleNodeTOImpl(name, null, value);
+ }
+
+ private def dispatch Node<?> getSimpleValue(Object container, QName name, BooleanTypeDefinition type) {
+ val value = container.getValue(name, Boolean);
+ if(value === null) return null;
+ return new SimpleNodeTOImpl(name, null, value);
+ }
+
+ private def dispatch Node<?> getSimpleValue(Object container, QName name, BinaryTypeDefinition type) {
+ val Object value = container.getValue(name, Object); //Constants.BYTES_CLASS);
+ if(value === null) return null;
+ return new SimpleNodeTOImpl(name, null, value);
+ }
+
+ private def <T> T getValue(Object object, QName node, Class<T> type) {
+ val methodName = BindingGeneratorImpl.getterMethodName(node.localName, Types.typeForClass(type));
+ var clz = object.class;
+ if (object instanceof DataContainer) {
+ clz = (object as DataContainer).implementedInterface;
+ }
+ val method = clz.getMethod(methodName);
+ if (method === null) {
+ return null;
+ }
+ val value = method.invoke(object);
+ if (value === null) {
+ return null;
+ }
+ if (type.isAssignableFrom(value.class)) {
+ return value as T;
+ }
+ return value.getEncapsulatedValue(type);
+ }
+
+ private def <T> T getEncapsulatedValue(Object value, Class<T> type) {
+ val method = value.class.getMethod("getValue");
+ if (method !== null && type.isAssignableFrom(method.returnType)) {
+ return method.invoke(value) as T;
+ }
+ return null;
+ }
+
+ private def dispatch List<Node<?>> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder,
+ SchemaNode node) {
+ return Collections.<Node<?>>singletonList(data.toDataDom(node, builder));
+ }
+
+ private def dispatch List<Node<?>> serializeValueImpl(Object object, GeneratedTypeBuilder builder,
+ SchemaNode node) {
+ }
+
+ def DataObject toDataObject(CompositeNode node, ClassLoader loader, GeneratedType type, SchemaNode schema) {
+
+ // Nasty reflection hack (for now)
+ val builderClass = loader.loadClass(type.builderFQN);
+ val builder = builderClass.newInstance;
+ val buildMethod = builderClass.getMethod("build");
+
+ node.fillDataObject(builder, loader, type, schema);
+
+ return buildMethod.invoke(builder) as DataObject;
+ }
+
+ def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+ ListSchemaNode schema) {
+
+ if (schema.keyDefinition !== null && !schema.keyDefinition.empty) {
+
+ val value = node.keyToBindingKey(loader, type, schema);
+ builder.setProperty("key", value);
+ }
+ }
+
+ def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type,
+ ContainerSchemaNode schema) {
+ }
+
+
+ def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) {
+ val keyClass = loader.loadClass(type.keyFQN);
+ val constructor = keyClass.constructors.get(0);
+ val keyType = type.keyTypeProperties;
+ val args = new ArrayList();
+ for (key : schema.keyDefinition) {
+ val keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName));
+ val domKeyValue = node.getFirstSimpleByName(key);
+ val keyValue = domKeyValue.deserializeSimpleValue(loader, keyProperty.returnType,
+ schema.getDataChildByName(key));
+ args.add(keyValue);
+ }
+ return ClassLoaderUtils.construct(constructor, args);
+ }
+
+ def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+ LeafSchemaNode node2) {
+ deserializeSimpleValueImpl(node, loader, type, node2.type);
+ }
+
+ def dispatch Object deserializeSimpleValue(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+ LeafListSchemaNode node2) {
+ deserializeSimpleValueImpl(node, loader, type, node2.type);
+ }
+
+ def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+ ExtendedType definition) {
+ deserializeSimpleValueImpl(node, loader, type, definition.baseType);
+ }
+
+ def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+ StringTypeDefinition definition) {
+ if (type instanceof GeneratedTransferObject) {
+ val cls = loader.getClassForType(type);
+ val const = cls.getConstructor(String);
+ val str = String.valueOf(node.value);
+ return const.newInstance(str);
+ }
+ return node.value;
+ }
+
+ def Class<?> getClassForType(ClassLoader loader, Type type) {
+ loader.loadClass(type.fullyQualifiedName);
+ }
+
+ def dispatch Object deserializeSimpleValueImpl(SimpleNode<? extends Object> node, ClassLoader loader, Type type,
+ TypeDefinition definition) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ def Map<String, GeneratedProperty> getKeyTypeProperties(GeneratedType type) {
+ val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"]
+ val key = method.returnType as GeneratedTransferObject;
+ val ret = new HashMap<String, GeneratedProperty>();
+ for (prop : key.properties) {
+ ret.put(prop.name, prop);
+ }
+ return ret;
+ }
+
+ def void setProperty(Object object, String property, Object value) {
+ val cls = object.class;
+ val valMethod = cls.getMethod("set" + property.toFirstUpper, value.class);
+ if (valMethod != null)
+ valMethod.invoke(object, value);
+ }
+
+ def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder'''
+
+ def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key'''
+
+}
+
+@Data
+class PropertyCapture {
+
+ @Property
+ val Type returnType;
+ @Property
+ val String name;
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class ConnectorActivator implements Provider, ServiceTrackerCustomizer<Broker, Broker> {
+
+ BindingIndependentDataServiceConnector dataConnector;
+ BindingIndependentMappingService mappingService;
+
+ private final DataProviderService baDataService;
+ private BundleContext context;
+
+ private ServiceTracker<Broker, Broker> brokerTracker;
+
+ public ConnectorActivator(DataProviderService dataService, BundleContext context) {
+ baDataService = dataService;
+ this.context = context;
+ brokerTracker = new ServiceTracker<>(context, Broker.class, this);
+ }
+
+ @Override
+ public Collection<ProviderFunctionality> getProviderFunctionality() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+
+ MappingServiceImpl mappingImpl = new MappingServiceImpl();
+ mappingImpl.setSchemaService(session.getService(SchemaService.class));
+ mappingImpl.start();
+
+ mappingService = mappingImpl;
+ dataConnector = new BindingIndependentDataServiceConnector();
+ dataConnector.setBaDataService(baDataService);
+ dataConnector.setBiDataService(session.getService(DataBrokerService.class));
+ dataConnector.setMappingService(mappingService);
+ dataConnector.start();
+ }
+
+ @Override
+ public Broker addingService(ServiceReference<Broker> reference) {
+ Broker br= context.getService(reference);
+ br.registerProvider(this, context);
+ return br;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Broker> reference, Broker service) {
+ // NOOP
+ }
+
+ @Override
+ public void removedService(ServiceReference<Broker> reference, Broker service) {
+ // NOOP
+ }
+
+ public void start() {
+ brokerTracker.open();
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom;
+
+public class Constants {
+ public static final Class<byte[]> BYTES_CLASS = byte[].class;
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.impl.connect.dom
+
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.util.Collections
+import java.util.Map.Entry
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
+import java.util.AbstractMap.SimpleEntry
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+
+class MappingServiceImpl implements SchemaServiceListener, BindingIndependentMappingService {
+
+ var extension BindingMapping mapping = new BindingMapping;
+
+ @Property
+ BindingGeneratorImpl binding;
+
+ @Property
+ SchemaService schemaService;
+
+ override onGlobalContextUpdated(SchemaContext arg0) {
+ recreateBindingContext(arg0);
+ }
+
+ def recreateBindingContext(SchemaContext schemaContext) {
+ val newBinding = new BindingGeneratorImpl();
+ newBinding.generateTypes(schemaContext);
+ val newMapping = new BindingMapping();
+ for (entry : newBinding.moduleContexts.entrySet) {
+ val module = entry.key;
+ val context = entry.value;
+
+ newMapping.updateBinding(schemaContext, context);
+ }
+ mapping = newMapping
+ }
+
+ override CompositeNode toDataDom(DataObject data) {
+ mapping.toCompositeNode(data);
+ }
+
+ override Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> toDataDom(
+ Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry) {
+ val key = mapping.toDataDom(entry.key);
+ val data = mapping.toCompositeNode(entry.value);
+ return new SimpleEntry(key, data);
+ }
+
+ override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(
+ InstanceIdentifier<? extends DataObject> path) {
+ return mapping.toDataDom(path);
+ }
+
+ override dataObjectFromDataDom(InstanceIdentifier<? extends DataObject> path, CompositeNode result) {
+ return mapping.dataObjectFromDataDom(path,result);
+ }
+
+ public def void start() {
+ schemaService.registerSchemaServiceListener(this);
+ recreateBindingContext(schemaService.globalContext);
+ }
+}
-package org.opendaylight.controller.sal.binding.impl.osgi;
+package org.opendaylight.controller.sal.binding.impl.util;
import java.util.concurrent.Callable;
+
import static com.google.common.base.Preconditions.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
public class ClassLoaderUtils {
public static <V> V withClassLoader(ClassLoader cls,Callable<V> function) throws Exception {
throw new Exception(e);
}
}
+
+ public static Object construct(Constructor<? extends Object> constructor, ArrayList<Object> objects) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ Object[] initargs = objects.toArray(new Object[]{});
+ return constructor.newInstance(initargs);
+ }
}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class BrokerIntegrationTest {
+
+ DataBrokerService biDataService;
+ DataProviderService baDataService;
+ private MappingServiceImpl mappingServiceImpl;
+ private MappingServiceImpl mappingService;
+ private DataBrokerImpl baDataImpl;
+ private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+ private ListeningExecutorService executor;
+ private BindingIndependentDataServiceConnector connectorServiceImpl;
+ private HashMapDataStore dataStore;
+
+
+ @Before
+ public void setUp() {
+ executor = MoreExecutors.sameThreadExecutor();
+ baDataImpl = new DataBrokerImpl();
+ baDataService = baDataImpl;
+ baDataImpl.setExecutor(executor);
+
+ biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+ biDataService = biDataImpl;
+ biDataImpl.setExecutor(executor);
+
+ dataStore = new HashMapDataStore();
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance();
+ biDataImpl.registerConfigurationReader(treeRoot, dataStore);
+ biDataImpl.registerOperationalReader(treeRoot, dataStore);
+ biDataImpl.registerCommitHandler(treeRoot, dataStore);
+
+ mappingServiceImpl = new MappingServiceImpl();
+ mappingService = mappingServiceImpl;
+
+
+ connectorServiceImpl = new BindingIndependentDataServiceConnector();
+ connectorServiceImpl.setBaDataService(baDataService);
+ connectorServiceImpl.setBiDataService(biDataService);
+ connectorServiceImpl.setMappingService(mappingServiceImpl);
+ connectorServiceImpl.start();
+
+ String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+ "node-inventory.yang" };
+
+ mappingService.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles));
+ }
+
+ @Test
+ public void simpleModifyOperation() throws Exception {
+
+ DataModificationTransaction transaction = baDataService.beginTransaction();
+ assertNotNull(transaction);
+
+ NodeRef node1 = createNodeRef("0");
+ DataObject node = baDataService.readConfigurationData(node1.getValue());
+ assertNull(node);
+ Node nodeData1 = createNode("0");
+
+ transaction.putConfigurationData(node1.getValue(), nodeData1);
+ Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
+ assertNotNull(commitResult);
+
+ RpcResult<TransactionStatus> result = commitResult.get();
+
+ assertNotNull(result);
+ assertNotNull(result.getResult());
+ assertEquals(TransactionStatus.COMMITED, result.getResult());
+
+ Node readedData = (Node) baDataService.readConfigurationData(node1.getValue());
+ assertNotNull(readedData);
+ assertEquals(nodeData1.getKey(), readedData.getKey());
+
+
+ DataModificationTransaction transaction2 = baDataService.beginTransaction();
+ assertNotNull(transaction);
+
+ transaction2.removeConfigurationData(node1.getValue());
+
+ Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
+ assertNotNull(commitResult2);
+
+ RpcResult<TransactionStatus> result2 = commitResult2.get();
+
+ assertNotNull(result2);
+ assertNotNull(result2.getResult());
+ assertEquals(TransactionStatus.COMMITED, result2.getResult());
+
+ DataObject readedData2 = baDataService.readConfigurationData(node1.getValue());
+ assertNull(readedData2);
+ }
+
+ private static NodeRef createNodeRef(String string) {
+ NodeKey key = new NodeKey(new NodeId(string));
+ InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
+ .toInstance();
+ return new NodeRef(path);
+ }
+
+ private static Node createNode(String string) {
+ NodeBuilder ret = new NodeBuilder();
+ ret.setId(new NodeId(string));
+ ret.setKey(new NodeKey(ret.getId()));
+ return ret.build();
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.connect.dom;
+
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class MappingServiceTest {
+
+ private static final QName NODES = QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes");
+ private static final QName NODE = QName.create(NODES,"node");
+ private static final QName ID = QName.create(NODES,"id");
+
+ BindingIndependentMappingService service;
+ private MappingServiceImpl impl;
+
+ @Before
+ public void setUp() {
+ impl = new MappingServiceImpl();
+ service = impl;
+ }
+
+ @Test
+ public void baDataToBiData() throws Exception {
+
+ String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+ "node-inventory.yang" };
+
+ SchemaContext ctx = getContext(yangFiles);
+
+ impl.onGlobalContextUpdated(ctx);
+
+ NodesBuilder nodes = new NodesBuilder();
+
+ List<Node> nodeList = new ArrayList<>();
+ nodeList.add(createChildNode("foo"));
+ nodeList.add(createChildNode("bar"));
+
+ nodes.setNode(nodeList);
+ Nodes nodesTO = nodes.build();
+ CompositeNode xmlNodes = service.toDataDom(nodesTO);
+ assertNotNull(xmlNodes);
+ List<CompositeNode> invNodes = xmlNodes.getCompositesByName(NODE);
+ assertNotNull(invNodes);
+ assertEquals(2, invNodes.size());
+ }
+
+ @Test
+ public void instanceIdentifierTest() throws Exception {
+
+ String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
+ "node-inventory.yang" };
+ SchemaContext ctx = getContext(yangFiles);
+ impl.onGlobalContextUpdated(ctx);
+
+ NodeKey nodeKey = new NodeKey(new NodeId("foo"));
+ InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).child(Node.class, nodeKey).toInstance();
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier result = service.toDataDom(path);
+ assertNotNull(result);
+ assertEquals(2, result.getPath().size());
+ }
+
+ public static SchemaContext getContext(String[] yangFiles) {
+
+ ClassLoader loader = MappingServiceTest.class.getClassLoader();
+
+ List<InputStream> streams = new ArrayList<>();
+ for (String string : yangFiles) {
+ InputStream stream = loader.getResourceAsStream("META-INF/yang/" + string);
+ streams.add(stream);
+
+ }
+ YangParserImpl parser = new YangParserImpl();
+
+ Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+ return parser.resolveSchemaContext(modules);
+ }
+
+ private Node createChildNode(String id) {
+ NodeBuilder node = new NodeBuilder();
+ NodeId nodeId = new NodeId(id);
+
+ node.setId(nodeId);
+ node.setKey(new NodeKey(nodeId));
+
+ FlowCapableNodeBuilder aug = new FlowCapableNodeBuilder();
+ aug.setManufacturer(id);
+ node.addAugmentation(FlowCapableNode.class, aug.build());
+
+ return node.build();
+ }
+
+}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-jmx-generator-plugin</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-manager</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+ <version>4.0</version>
+ </dependency>
</dependencies>
</project>
mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), //
mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), //
+ mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
mavenBundle("com.google.guava", "guava").versionAsInProject(), //
mavenBundle(YANGTOOLS + ".thirdparty", "xtend-lib-osgi").versionAsInProject() //
);
mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
mavenBundle("org.javassist", "javassist").versionAsInProject(), //
- mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject() //
- );
+ mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+
+ mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+
+
+ mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+
+
+ mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+ mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+ mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+
+ mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject() //
+ );
}
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.util.PathUtils;
import org.osgi.framework.BundleContext;
@RunWith(PaxExam.class)
public Option[] config() {
return options(systemProperty("osgi.console").value("2401"), mavenBundle("org.slf4j", "slf4j-api")
.versionAsInProject(), //
+ systemProperty("logback.configurationFile").value(
+ "file:" + PathUtils.getBaseDir()
+ + "/src/test/resources/logback.xml"),
mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import com.google.inject.Inject;
+
public class DataServiceTest extends AbstractTest {
protected DataBrokerService consumerDataService;
+
+
+ @Inject
+ Broker broker2;
@Before
public void setUp() throws Exception {
assertNotNull(result.getResult());
assertEquals(TransactionStatus.COMMITED, result.getResult());
- DataObject readedData = consumerDataService.readConfigurationData(node1.getValue());
+ Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
assertNotNull(readedData);
- assertEquals(nodeData1, readedData);
+ assertEquals(nodeData1.getKey(), readedData.getKey());
DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
private static Node createNode(String string) {
NodeBuilder ret = new NodeBuilder();
- ret.setId(new NodeId(string));
+ NodeId id = new NodeId(string);
+ ret.setKey(new NodeKey(id));
+ ret.setId(id);
return ret.build();
}
}
<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>sal-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <artifactId>sal-common-impl</artifactId>
- <packaging>bundle</packaging>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
+ 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>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-common-impl</artifactId>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-api</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.lib</artifactId>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-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>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.lib</artifactId>
+ </dependency>
+ </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>
- org.opendaylight.controller.md.sal.common.impl,
- org.opendaylight.controller.md.sal.common.impl.*
- </Export-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.controller.md.sal.common.impl,
+ org.opendaylight.controller.md.sal.common.impl.*
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
</project>
package org.opendaylight.controller.md.sal.common.impl;
+import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
+
import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
-import org.opendaylight.yangtools.concepts.Path;
-
-import static org.opendaylight.controller.md.sal.common.api.TransactionStatus.NEW;
public abstract class AbstractDataModification<P /* extends Path<P> */, D> implements DataModification<P, D> {
@Override
public final void putRuntimeData(P path, D data) {
- putRuntimeData(path, data);
+ putOperationalData(path, data);
}
@Override
@Override
public D readOperationalData(P path) {
FluentIterable<D> dataBits = FluentIterable //
- .from(getReaders(configReaders, path)).transform(operationalRead(path));
+ .from(getReaders(operationalReaders, path)).transform(operationalRead(path));
return merge(path,dataBits);
}
return new Function<DataReader<P, D>, D>() {
@Override
public D apply(DataReader<P, D> input) {
- return input.readConfigurationData(path);
+ return input.readOperationalData(path);
}
};
}
--- /dev/null
+package org.opendaylight.controller.md.sal.common.impl.service
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration
+import org.opendaylight.yangtools.concepts.ListenerRegistration
+import com.google.common.collect.Multimap
+import static com.google.common.base.Preconditions.*;
+import java.util.List
+import com.google.common.collect.HashMultimap
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Callable
+import org.opendaylight.yangtools.yang.common.RpcResult
+import java.util.Collections
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
+import java.util.ArrayList
+import org.opendaylight.yangtools.concepts.CompositeObjectRegistration
+import java.util.Arrays
+import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
+import org.opendaylight.controller.md.sal.common.api.data.DataModificationTransactionFactory
+import org.opendaylight.controller.md.sal.common.api.data.DataChangePublisher
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener
+import org.opendaylight.controller.sal.common.util.Rpcs
+import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification
+import java.util.concurrent.Future
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.concepts.Path
+import org.slf4j.LoggerFactory
+
+abstract class AbstractDataBroker<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> implements
+DataModificationTransactionFactory<P, D>, //
+DataReader<P, D>, //
+DataChangePublisher<P, D, DCL>, //
+DataProvisionService<P,D> {
+
+ @Property
+ var ExecutorService executor;
+
+ @Property
+ var AbstractDataReadRouter<P,D> dataReadRouter;
+
+ Multimap<P, DataChangeListenerRegistration<P,D,DCL>> listeners = HashMultimap.create();
+ Multimap<P, DataCommitHandlerRegistration<P,D>> commitHandlers = HashMultimap.create();
+
+
+ public new() {
+
+ }
+
+ override final readConfigurationData(P path) {
+ return dataReadRouter.readConfigurationData(path);
+ }
+
+ override final readOperationalData(P path) {
+ return dataReadRouter.readOperationalData(path);
+ }
+
+ override final registerCommitHandler(P path,
+ DataCommitHandler<P, D> commitHandler) {
+ val registration = new DataCommitHandlerRegistration(path,commitHandler,this);
+ commitHandlers.put(path,registration)
+ return registration;
+ }
+
+ override final def registerDataChangeListener(P path, DCL listener) {
+ val reg = new DataChangeListenerRegistration(path, listener, this);
+ listeners.put(path, reg);
+ return reg;
+ }
+
+ final def registerDataReader(P path,DataReader<P,D> reader) {
+
+ val confReg = dataReadRouter.registerConfigurationReader(path,reader);
+ val dataReg = dataReadRouter.registerOperationalReader(path,reader);
+
+ return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg));
+ }
+
+ protected final def removeListener(DataChangeListenerRegistration<P,D,DCL> registration) {
+ listeners.remove(registration.path, registration);
+ }
+
+ protected final def removeCommitHandler(DataCommitHandlerRegistration<P,D> registration) {
+ commitHandlers.remove(registration.path, registration);
+ }
+
+ protected final def getActiveCommitHandlers() {
+ return commitHandlers.entries.map[ value.instance].toSet
+ }
+
+ package final def Future<RpcResult<TransactionStatus>> commit(AbstractDataTransaction<P,D> transaction) {
+ checkNotNull(transaction);
+ transaction.changeStatus(TransactionStatus.SUBMITED);
+ val task = new TwoPhaseCommit(transaction, this);
+ return executor.submit(task);
+ }
+
+}
+
+package class DataChangeListenerRegistration<P extends Path<P>,D,DCL extends DataChangeListener<P,D>> extends AbstractObjectRegistration<DCL> implements ListenerRegistration<DCL> {
+
+ AbstractDataBroker<P,D,DCL> dataBroker;
+
+ @Property
+ val P path;
+
+ new(P path, DCL instance, AbstractDataBroker<P,D,DCL> broker) {
+ super(instance)
+ dataBroker = broker;
+ _path = path;
+ }
+
+ override protected removeRegistration() {
+ dataBroker.removeListener(this);
+ dataBroker = null;
+ }
+
+}
+
+package class DataCommitHandlerRegistration<P extends Path<P>,D>
+extends AbstractObjectRegistration<DataCommitHandler<P, D>> {
+
+ AbstractDataBroker<P,D,?> dataBroker;
+
+ @Property
+ val P path;
+
+ new(P path, DataCommitHandler<P, D> instance,
+ AbstractDataBroker<P,D,?> broker) {
+ super(instance)
+ dataBroker = broker;
+ _path = path;
+ }
+
+ override protected removeRegistration() {
+ dataBroker.removeCommitHandler(this);
+ dataBroker = null;
+ }
+
+}
+
+package class TwoPhaseCommit<P extends Path<P>,D> implements Callable<RpcResult<TransactionStatus>> {
+
+ private static val log = LoggerFactory.getLogger(TwoPhaseCommit);
+
+ val AbstractDataTransaction<P,D> transaction;
+ val AbstractDataBroker<P,D,?> dataBroker;
+
+ new(AbstractDataTransaction<P,D> transaction, AbstractDataBroker<P,D,?> broker) {
+ this.transaction = transaction;
+ this.dataBroker = broker;
+ }
+
+ override call() throws Exception {
+
+ val Iterable<DataCommitHandler<P, D>> commitHandlers = dataBroker.activeCommitHandlers;
+
+ // requesting commits
+ val List<DataCommitTransaction<P, D>> handlerTransactions = new ArrayList();
+ try {
+ for (handler : commitHandlers) {
+ handlerTransactions.add(handler.requestCommit(transaction));
+ }
+ } catch (Exception e) {
+ log.error("Request Commit failded",e);
+ return rollback(handlerTransactions,e);
+ }
+ val List<RpcResult<Void>> results = new ArrayList();
+ try {
+ for (subtransaction : handlerTransactions) {
+ results.add(subtransaction.finish());
+ }
+ } catch (Exception e) {
+ log.error("Finish Commit failed",e);
+ return rollback(handlerTransactions,e);
+ }
+
+ return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet());
+ }
+
+ def rollback(List<DataCommitTransaction<P, D>> transactions,Exception e) {
+ for (transaction : transactions) {
+ transaction.rollback()
+ }
+ // FIXME return encountered error.
+ return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet());
+ }
+}
+
+public abstract class AbstractDataTransaction<P extends Path<P>, D> extends AbstractDataModification<P, D> {
+
+ @Property
+ private val Object identifier;
+
+
+ var TransactionStatus status;
+
+
+ var AbstractDataBroker<P, D, ?> broker;
+
+ protected new (AbstractDataBroker<P,D,?> dataBroker) {
+ super(dataBroker);
+ _identifier = new Object();
+ broker = dataBroker;
+ status = TransactionStatus.NEW;
+ //listeners = new ListenerRegistry<>();
+ }
+
+ override commit() {
+ return broker.commit(this);
+ }
+
+ override readConfigurationData(P path) {
+ return broker.readConfigurationData(path);
+ }
+
+ override readOperationalData(P path) {
+ return broker.readOperationalData(path);
+ }
+
+ override hashCode() {
+ return identifier.hashCode;
+ }
+
+ override equals(Object obj) {
+ if (this === obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ val other = (obj as AbstractDataTransaction<P,D>) ;
+ if (broker == null) {
+ if (other.broker != null)
+ return false;
+ } else if (!broker.equals(other.broker))
+ return false;
+ if (identifier == null) {
+ if (other.identifier != null)
+ return false;
+ } else if (!identifier.equals(other.identifier))
+ return false;
+ return true;
+ }
+
+ override TransactionStatus getStatus() {
+ return status;
+ }
+
+
+ protected abstract def void onStatusChange(TransactionStatus status);
+
+ public def changeStatus(TransactionStatus status) {
+ this.status = status;
+ onStatusChange(status);
+ }
+
+}
package org.opendaylight.controller.sal.core.api.model;
import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
* @return
*/
SchemaContext getGlobalContext();
+
+ ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener);
}
--- /dev/null
+package org.opendaylight.controller.sal.core.api.model;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface SchemaServiceListener extends EventListener {
+
+
+ void onGlobalContextUpdated(SchemaContext context);
+
+}
package org.opendaylight.controller.sal.core.api.mount;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
-public interface MountProvisionInstance extends MountInstance, NotificationPublishService, RpcProvisionRegistry {
+public interface MountProvisionInstance extends //
+ MountInstance,//
+ NotificationPublishService, //
+ RpcProvisionRegistry,//
+ DataProviderService {
}
*/
package org.opendaylight.controller.sal.core.api.mount;
+import org.opendaylight.controller.sal.core.api.BrokerService;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-public interface MountService {
+public interface MountService extends BrokerService {
MountInstance getMountPoint(InstanceIdentifier path);
}
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-parent</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>sal-broker-impl</artifactId>\r
- <packaging>bundle</packaging>\r
- <scm>\r
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
- </scm>\r
-\r
- <dependencies>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-core-api</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-common-util</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-common-impl</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-common-impl</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-core-spi</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.slf4j</groupId>\r
- <artifactId>slf4j-api</artifactId>\r
- </dependency>\r
- <dependency>\r
- <groupId>com.google.guava</groupId>\r
- <artifactId>guava</artifactId>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.eclipse.xtend</groupId>\r
- <artifactId>org.eclipse.xtend.lib</artifactId>\r
- </dependency>\r
- </dependencies>\r
-\r
- <build>\r
- <plugins>\r
- <plugin>\r
- <groupId>org.apache.felix</groupId>\r
- <artifactId>maven-bundle-plugin</artifactId>\r
- <extensions>true</extensions>\r
- <configuration>\r
- <instructions>\r
- <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
- <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
- <Private-Package>\r
- org.opendaylight.controller.sal.dom.broker.*\r
- </Private-Package>\r
- </instructions>\r
- </configuration>\r
- </plugin>\r
- <plugin>\r
- <groupId>org.eclipse.xtend</groupId>\r
- <artifactId>xtend-maven-plugin</artifactId>\r
- </plugin>\r
- </plugins>\r
- </build>\r
-</project>\r
+<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>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-broker-impl</artifactId>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+ <dependencies>
+ <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.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-spi</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>
+ <Private-Package>
+ org.opendaylight.controller.sal.dom.broker.*
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
import java.util.Hashtable;
import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.core.api.mount.MountService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
public class BrokerActivator implements BundleActivator {
+ private static final InstanceIdentifier ROOT = InstanceIdentifier.builder().toInstance();
BrokerImpl broker;
private ServiceRegistration<Broker> brokerReg;
-
+ private ServiceRegistration<SchemaService> schemaReg;
+ private ServiceRegistration<DataBrokerService> dataReg;
+ private ServiceRegistration<DataProviderService> dataProviderReg;
+ private SchemaServiceImpl schemaService;
+ private DataBrokerImpl dataService;
+ private MountPointManagerImpl mountService;
+ private ServiceRegistration<MountService> mountReg;
+ private ServiceRegistration<MountProvisionService> mountProviderReg;
+ private HashMapDataStore hashMapStore;
+
@Override
public void start(BundleContext context) throws Exception {
+ Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
broker = new BrokerImpl();
broker.setBundleContext(context);
- brokerReg = context.registerService(Broker.class, broker, new Hashtable<String,String>());
+
+
+ schemaService = new SchemaServiceImpl();
+ schemaService.setContext(context);
+ schemaService.setParser(new YangParserImpl());
+ schemaService.start();
+ schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String, String>());
+
+ dataService = new DataBrokerImpl();
+ dataService.setExecutor(broker.getExecutor());
+
+ dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties);
+ dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties);
+
+ hashMapStore = new HashMapDataStore();
+
+ dataService.registerConfigurationReader(ROOT, hashMapStore);
+ dataService.registerCommitHandler(ROOT, hashMapStore);
+ dataService.registerOperationalReader(ROOT, hashMapStore);
+
+ mountService = new MountPointManagerImpl();
+ mountService.setDataBroker(dataService);
+
+ mountReg = context.registerService(MountService.class, mountService, emptyProperties);
+ mountProviderReg = context.registerService(MountProvisionService.class, mountService, emptyProperties);
+
+ brokerReg = context.registerService(Broker.class, broker, emptyProperties);
}
@Override
public void stop(BundleContext context) throws Exception {
- if(brokerReg != null) {
+ if (brokerReg != null) {
brokerReg.unregister();
}
}
private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
new HashSet<ProviderContextImpl>());
- private val Set<BrokerModule> modules = Collections.synchronizedSet(new HashSet<BrokerModule>());
- private val Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections.
- synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
// Implementation specific
@Property
private var ExecutorService executor = Executors.newFixedThreadPool(5);
@Property
private var BundleContext bundleContext;
-
+
@Property
private var RpcRouter router;
return session;
}
- public def addModule(BrokerModule module) {
- log.info("Registering broker module " + module);
- if(modules.contains(module)) {
- log.error("Module already registered");
- throw new IllegalArgumentException("Module already exists.");
- }
-
- val provServices = module.getProvidedServices();
- for (Class<? extends BrokerService> serviceType : provServices) {
- log.info(" Registering session service implementation: " + serviceType.getCanonicalName());
- serviceProviders.put(serviceType, module);
- }
- }
-
- public def <T extends BrokerService> T serviceFor(Class<T> service, ConsumerContextImpl session) {
- val prov = serviceProviders.get(service);
- if(prov == null) {
- log.warn("Service " + service.toString() + " is not supported");
- return null;
- }
- return prov.getServiceForSession(service, session);
- }
-
protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
return result;
// Validation
private def void checkPredicates(Provider prov) {
- if(prov == null)
+ if (prov == null)
throw new IllegalArgumentException("Provider should not be null.");
for (ProviderContextImpl session : providerSessions) {
- if(prov.equals(session.getProvider()))
+ if (prov.equals(session.getProvider()))
throw new IllegalStateException("Provider already registered");
}
}
private def void checkPredicates(Consumer cons) {
- if(cons == null)
+ if (cons == null)
throw new IllegalArgumentException("Consumer should not be null.");
for (ConsumerContextImpl session : sessions) {
- if(cons.equals(session.getConsumer()))
+ if (cons.equals(session.getConsumer()))
throw new IllegalStateException("Consumer already registered");
}
}
package org.opendaylight.controller.sal.dom.broker
-import java.util.Collections
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import java.util.HashMap
import org.opendaylight.controller.sal.core.api.BrokerService
import org.opendaylight.controller.sal.core.api.Consumer
import org.osgi.framework.BundleContext
import org.opendaylight.yangtools.yang.common.QName
import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
+import com.google.common.collect.ClassToInstanceMap
+import com.google.common.collect.MutableClassToInstanceMap
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
class ConsumerContextImpl implements ConsumerSession {
@Property
private var BrokerImpl broker;
- private val instantiatedServices = Collections.synchronizedMap(
- new HashMap<Class<? extends BrokerService>, BrokerService>());
+ private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
private boolean closed = false;
private BundleContext context;
}
override <T extends BrokerService> T getService(Class<T> service) {
- val potential = instantiatedServices.get(service);
- if(potential != null) {
- val ret = potential as T;
- return ret;
+ val localProxy = instantiatedServices.getInstance(service);
+ if(localProxy != null) {
+ return localProxy;
}
- val ret = broker.serviceFor(service, this);
+ val serviceRef = context.getServiceReference(service);
+ if(serviceRef == null) {
+ return null;
+ }
+ val serviceImpl = context.getService(serviceRef);
+
+
+ val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
if(ret != null) {
- instantiatedServices.put(service, ret);
+ instantiatedServices.putInstance(service, ret);
}
return ret;
}
val toStop = instantiatedServices.values();
this.closed = true;
for (BrokerService brokerService : toStop) {
- //brokerService.closeSession();
+ if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
+ (brokerService as AutoCloseable).close();
+ }
}
broker.consumerSessionClosed(this);
}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier, CompositeNode, DataChangeListener> implements
+ DataProviderService {
+
+ public DataBrokerImpl() {
+ setDataReadRouter(new DataReaderRouter());
+ }
+
+ @Override
+ public DataTransactionImpl beginTransaction() {
+ return new DataTransactionImpl(this);
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+ InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+ return getDataReadRouter().registerConfigurationReader(path, reader);
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+ InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+ return getDataReadRouter().registerOperationalReader(path, reader);
+ }
+
+ @Deprecated
+ @Override
+ public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Deprecated
+ @Override
+ public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Deprecated
+ @Override
+ public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Deprecated
+ @Override
+ public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
\ No newline at end of file
+++ /dev/null
-package org.opendaylight.controller.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-
-class DataConsumerServiceImpl implements DataBrokerService {
-
- override beginTransaction() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override readConfigurationData(InstanceIdentifier path) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override readOperationalData(InstanceIdentifier path) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DataTransactionImpl extends AbstractDataTransaction<InstanceIdentifier, CompositeNode>
+ implements DataModificationTransaction {
+ private final ListenerRegistry<DataTransactionListener> listeners = new ListenerRegistry<DataTransactionListener>();
+
+
+
+ public DataTransactionImpl(DataBrokerImpl dataBroker) {
+ super(dataBroker);
+ }
+
+ @Override
+ public ListenerRegistration<DataTransactionListener> registerListener(DataTransactionListener listener) {
+ return listeners.register(listener);
+ }
+
+ protected void onStatusChange(TransactionStatus status) {
+ for (ListenerRegistration<DataTransactionListener> listenerRegistration : listeners) {
+ listenerRegistration.getInstance().onStatusUpdated(this, status);
+ }
+ }
+}
\ No newline at end of file
package org.opendaylight.controller.sal.dom.broker;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
public class MountPointImpl implements MountProvisionInstance {
- final RpcRouter rpcs;
- final DataReaderRouter dataReader;
- final NotificationRouter notificationRouter;
+ private final RpcRouter rpcs;
+ private final DataReaderRouter dataReader;
+ private final NotificationRouter notificationRouter;
+ private final DataReader<InstanceIdentifier,CompositeNode> readWrapper;
+
+
+ private final InstanceIdentifier mountPath;
public MountPointImpl(InstanceIdentifier path) {
+ this.mountPath = path;
rpcs = new RpcRouterImpl("");
dataReader = new DataReaderRouter();
notificationRouter = new NotificationRouterImpl();
+ readWrapper = new ReadWrapper();
+ }
+
+ public InstanceIdentifier getMountPath() {
+ return mountPath;
+ }
+
+ public DataReader<InstanceIdentifier, CompositeNode> getReadWrapper() {
+ return readWrapper;
}
@Override
@Override
public void sendNotification(CompositeNode notification) {
publish(notification);
+ }
+
+ @Override
+ public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+ InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @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
+ }
+ @Override
+ public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+ // NOOP
+ }
+
+ class ReadWrapper implements DataReader<InstanceIdentifier, CompositeNode> {
+
+
+ private InstanceIdentifier shortenPath(InstanceIdentifier path) {
+ InstanceIdentifier ret = null;
+ if(mountPath.contains(path)) {
+ List<PathArgument> newArgs = path.getPath().subList(mountPath.getPath().size(), path.getPath().size());
+ ret = new InstanceIdentifier(newArgs);
+ }
+ return ret;
+ }
+
+ @Override
+ public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ InstanceIdentifier newPath = shortenPath(path);
+ if(newPath == null) {
+ return null;
+ }
+ return MountPointImpl.this.readConfigurationData(newPath);
+ }
+ @Override
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ InstanceIdentifier newPath = shortenPath(path);
+ if(newPath == null) {
+ return null;
+ }
+ return MountPointImpl.this.readOperationalData(newPath);
+ }
}
}
import java.util.concurrent.ConcurrentMap
import java.util.concurrent.ConcurrentHashMap
import static com.google.common.base.Preconditions.*;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
class MountPointManagerImpl implements MountProvisionService {
+ @Property
+ DataProviderService dataBroker;
+
ConcurrentMap<InstanceIdentifier,MountPointImpl> mounts = new ConcurrentHashMap();
override createMountPoint(InstanceIdentifier path) {
checkState(!mounts.containsKey(path),"Mount already created");
val mount = new MountPointImpl(path);
+ registerMountPoint(mount);
mounts.put(path,mount);
+ return mount;
+ }
+
+ def registerMountPoint(MountPointImpl impl) {
+ dataBroker?.registerConfigurationReader(impl.mountPath,impl.readWrapper);
+ dataBroker?.registerOperationalReader(impl.mountPath,impl.readWrapper);
+
}
override getMountPoint(InstanceIdentifier path) {
mounts.get(path);
}
-
-
}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.Checksum;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.*;
+
+public class SchemaServiceImpl implements SchemaService, AutoCloseable {
+ private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
+
+ private ListenerRegistry<SchemaServiceListener> listeners;
+ private YangModelParser parser;
+
+ private BundleContext context;
+ private BundleScanner scanner = new BundleScanner();
+
+ /**
+ * Map of currently problematic yang files that should get fixed eventually
+ * after all events are received.
+ */
+ private final Multimap<Bundle, URL> inconsistentBundlesToYangURLs = HashMultimap.create();
+ private final Multimap<Bundle, URL> consistentBundlesToYangURLs = HashMultimap.create();
+ private BundleTracker<Object> bundleTracker;
+ private final YangStoreCache cache = new YangStoreCache();
+
+ public ListenerRegistry<SchemaServiceListener> getListeners() {
+ return listeners;
+ }
+
+ public void setListeners(ListenerRegistry<SchemaServiceListener> listeners) {
+ this.listeners = listeners;
+ }
+
+ public YangModelParser getParser() {
+ return parser;
+ }
+
+ public void setParser(YangModelParser parser) {
+ this.parser = parser;
+ }
+
+ public BundleContext getContext() {
+ return context;
+ }
+
+ public void setContext(BundleContext context) {
+ this.context = context;
+ }
+
+ public void start() {
+ checkState(parser != null);
+ checkState(context != null);
+ if (listeners == null) {
+ listeners = new ListenerRegistry<>();
+ }
+
+ bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
+ bundleTracker.open();
+ }
+
+ public SchemaContext getGlobalContext() {
+ return getSchemaContextSnapshot();
+ }
+
+ public synchronized SchemaContext getSchemaContextSnapshot() {
+ Optional<SchemaContext> yangStoreOpt = cache.getCachedSchemaContext(consistentBundlesToYangURLs);
+ if (yangStoreOpt.isPresent()) {
+ return yangStoreOpt.get();
+ }
+ SchemaContext snapshot = createSnapshot(parser, consistentBundlesToYangURLs);
+ updateCache(snapshot);
+ return snapshot;
+ }
+
+ @Override
+ public void addModule(Module module) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SchemaContext getSessionContext() {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeModule(Module module) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+ return listeners.register(listener);
+ }
+
+ @Override
+ public void close() throws Exception {
+ bundleTracker.close();
+ // FIXME: Add listeners.close();
+
+ }
+
+ private synchronized boolean tryToUpdateState(Collection<URL> changedURLs, Multimap<Bundle, URL> proposedNewState,
+ boolean adding) {
+ Preconditions.checkArgument(changedURLs.size() > 0, "No change can occur when no URLs are changed");
+
+ try {
+ // consistent state
+ // merge into
+ SchemaContext snapshot = createSnapshot(parser, proposedNewState);
+ consistentBundlesToYangURLs.clear();
+ consistentBundlesToYangURLs.putAll(proposedNewState);
+ inconsistentBundlesToYangURLs.clear();
+ // update cache
+ updateCache(snapshot);
+ logger.info("SchemaService updated to new consistent state");
+ logger.trace("SchemaService updated to new consistent state containing {}", consistentBundlesToYangURLs);
+
+ // notifyListeners(changedURLs, adding);
+ return true;
+ } catch (Exception e) {
+ // inconsistent state
+ logger.debug(
+ "SchemaService is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+ consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, e.toString());
+ return false;
+ }
+ }
+
+ private static Collection<InputStream> fromUrlsToInputStreams(Multimap<Bundle, URL> multimap) {
+ return Collections2.transform(multimap.values(), new Function<URL, InputStream>() {
+
+ @Override
+ public InputStream apply(URL url) {
+ try {
+ return url.openStream();
+ } catch (IOException e) {
+ logger.warn("Unable to open stream from {}", url);
+ throw new IllegalStateException("Unable to open stream from " + url, e);
+ }
+ }
+ });
+ }
+
+ private static SchemaContext createSnapshot(YangModelParser parser, Multimap<Bundle, URL> multimap) {
+ List<InputStream> models = new ArrayList<>(fromUrlsToInputStreams(multimap));
+ Set<Module> modules = parser.parseYangModelsFromStreams(models);
+ SchemaContext yangStoreSnapshot = parser.resolveSchemaContext(modules);
+ return yangStoreSnapshot;
+ }
+
+ private void updateCache(SchemaContext snapshot) {
+ cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
+ for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+ try {
+ listener.getInstance().onGlobalContextUpdated(snapshot);
+ } catch (Exception e) {
+ logger.error("Exception occured during invoking listener",e);
+ }
+ }
+ }
+
+ private class BundleScanner implements BundleTrackerCustomizer<Object> {
+ @Override
+ public Object addingBundle(Bundle bundle, BundleEvent event) {
+
+ // Ignore system bundle:
+ // system bundle might have config-api on classpath &&
+ // config-api contains yang files =>
+ // system bundle might contain yang files from that bundle
+ if (bundle.getBundleId() == 0)
+ return bundle;
+
+ Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+ if (enumeration != null && enumeration.hasMoreElements()) {
+ synchronized (this) {
+ List<URL> addedURLs = new ArrayList<>();
+ while (enumeration.hasMoreElements()) {
+ URL url = enumeration.nextElement();
+ addedURLs.add(url);
+ }
+ logger.trace("Bundle {} has event {}, bundle state {}, URLs {}", bundle, event, bundle.getState(),
+ addedURLs);
+ // test that yang store is consistent
+ Multimap<Bundle, URL> proposedNewState = HashMultimap.create(consistentBundlesToYangURLs);
+ proposedNewState.putAll(inconsistentBundlesToYangURLs);
+ proposedNewState.putAll(bundle, addedURLs);
+ boolean adding = true;
+ if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
+ inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
+ }
+ }
+ }
+ return bundle;
+ }
+
+ @Override
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+ logger.debug("Modified bundle {} {} {}", bundle, event, object);
+ }
+
+ /**
+ * If removing YANG files makes yang store inconsistent, method
+ * {@link #getYangStoreSnapshot()} will throw exception. There is no
+ * rollback.
+ */
+
+ @Override
+ public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+ inconsistentBundlesToYangURLs.removeAll(bundle);
+ Collection<URL> consistentURLsToBeRemoved = consistentBundlesToYangURLs.removeAll(bundle);
+
+ if (consistentURLsToBeRemoved.isEmpty()) {
+ return; // no change
+ }
+ boolean adding = false;
+ // notifyListeners(consistentURLsToBeRemoved, adding);
+ }
+ }
+
+ private static final class YangStoreCache {
+
+ Set<URL> cachedUrls;
+ SchemaContext cachedContextSnapshot;
+
+ Optional<SchemaContext> getCachedSchemaContext(Multimap<Bundle, URL> bundlesToYangURLs) {
+ Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+ if (cachedUrls != null && cachedUrls.equals(urls)) {
+ Preconditions.checkState(cachedContextSnapshot != null);
+ return Optional.of(cachedContextSnapshot);
+ }
+ return Optional.absent();
+ }
+
+ private static Set<URL> setFromMultimapValues(Multimap<Bundle, URL> bundlesToYangURLs) {
+ Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+ Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+ return urls;
+ }
+
+ void cacheYangStore(Multimap<Bundle, URL> urls, SchemaContext ctx) {
+ this.cachedUrls = setFromMultimapValues(urls);
+ this.cachedContextSnapshot = ctx;
+ }
+
+ }
+}
import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
override protected merge(InstanceIdentifier path, Iterable<CompositeNode> data) {
- return data.iterator.next
+ val iterator = data.iterator;
+ if(iterator.hasNext) {
+ return data.iterator.next
+ }
+ return null;
}
}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.impl
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import java.util.Map
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import java.util.Map.Entry
+import java.util.HashSet
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+
+class DataUtils {
+
+ static def CompositeNode read(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+ val root = map.get(path);
+ val childs = map.getChilds(path);
+ if(root === null && childs.empty) {
+ return null;
+ }
+
+ return merge(path, root, childs);
+ }
+
+ static def CompositeNode merge(InstanceIdentifier path, CompositeNode node,
+ HashSet<Entry<InstanceIdentifier, CompositeNode>> entries) {
+ val it = new ArrayList<Node<?>>();
+ val qname = path.path.last.nodeType;
+ if (node != null) {
+ addAll(node.children);
+ }
+ for (entry : entries) {
+ val nesting = entry.key.path.size - path.path.size;
+ if (nesting === 1) {
+ add(entry.value);
+ }
+ }
+ return new CompositeNodeTOImpl(qname, null, it);
+ }
+
+ static def getChilds(Map<InstanceIdentifier, CompositeNode> map, InstanceIdentifier path) {
+ val it = new HashSet<Entry<InstanceIdentifier, CompositeNode>>();
+ for (entry : map.entrySet) {
+ if (path.contains(entry.key)) {
+ add(entry);
+ }
+ }
+ return it;
+ }
+
+}
-package org.opendaylight.controller.sal.binding.impl
+package org.opendaylight.controller.sal.dom.broker.impl
import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
import org.opendaylight.controller.md.sal.common.api.data.DataModification
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction
import org.opendaylight.yangtools.yang.common.RpcResult
import java.util.concurrent.ConcurrentHashMap
import org.opendaylight.controller.sal.common.util.Rpcs
import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import static extension org.opendaylight.controller.sal.dom.broker.impl.DataUtils.*;
class HashMapDataStore //
implements //
-RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> {
+DataReader<InstanceIdentifier, CompositeNode>, DataCommitHandler<InstanceIdentifier, CompositeNode> {
- val Map<InstanceIdentifier<? extends DataObject>,DataObject> configuration = new ConcurrentHashMap();
- val Map<InstanceIdentifier<? extends DataObject>,DataObject> operational = new ConcurrentHashMap();
+ val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
+ val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
-
- override readConfigurationData(InstanceIdentifier<? extends DataObject> path) {
- configuration.get(path);
+ override readConfigurationData(InstanceIdentifier path) {
+ configuration.read(path);
}
- override readOperationalData(InstanceIdentifier<? extends DataObject> path) {
- operational.get(path);
+ override readOperationalData(InstanceIdentifier path) {
+ operational.read(path);
}
+
+
- override requestCommit(DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new HashMapDataStoreTransaction(modification,this);
+
+ override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
+ return new HashMapDataStoreTransaction(modification, this);
}
-
+
def RpcResult<Void> rollback(HashMapDataStoreTransaction transaction) {
- return Rpcs.getRpcResult(true,null,Collections.emptySet);
+ return Rpcs.getRpcResult(true, null, Collections.emptySet);
}
-
+
def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
val modification = transaction.modification;
configuration.putAll(modification.updatedConfigurationData);
operational.putAll(modification.updatedOperationalData);
-
- for(removal : modification.removedConfigurationData) {
+
+ for (removal : modification.removedConfigurationData) {
configuration.remove(removal);
}
- for(removal : modification.removedOperationalData) {
+ for (removal : modification.removedOperationalData) {
operational.remove(removal);
}
- return Rpcs.getRpcResult(true,null,Collections.emptySet);
+ return Rpcs.getRpcResult(true, null, Collections.emptySet);
}
}
class HashMapDataStoreTransaction implements //
-DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
+DataCommitTransaction<InstanceIdentifier, CompositeNode> {
@Property
- val DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification
+ val DataModification<InstanceIdentifier, CompositeNode> modification
@Property
val HashMapDataStore datastore;
-
-
+
new(
- DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modify,
+ DataModification<InstanceIdentifier, CompositeNode> modify,
HashMapDataStore store
) {
_modification = modify;
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.osgi.framework.ServiceReference;
+import static com.google.common.base.Preconditions.*;
+
+public abstract class AbstractBrokerServiceProxy<T extends BrokerService> implements AutoCloseable, BrokerService {
+
+ private T delegate;
+ private final ServiceReference<T> reference;
+
+ public AbstractBrokerServiceProxy(ServiceReference<T> ref, T delegate) {
+ this.delegate = checkNotNull(delegate, "Delegate should not be null.");
+ this.reference = checkNotNull(ref, "Reference should not be null.");
+ }
+
+ protected final T getDelegate() {
+ checkState(delegate != null, "Proxy was closed and unregistered.");
+ return delegate;
+ }
+
+ protected final ServiceReference<T> getReference() {
+ return reference;
+ }
+
+ private Set<Registration<?>> registrations = Collections.synchronizedSet(new HashSet<Registration<?>>());
+
+ protected <R extends Registration<?>> R addRegistration(R registration) {
+ if (registration != null) {
+ registrations.add(registration);
+ }
+ return registration;
+ }
+
+ protected void closeBeforeUnregistrations() {
+ // NOOP
+ }
+
+ protected void closeAfterUnregistrations() {
+ // NOOP
+ }
+
+ @Override
+ public void close() {
+ if (delegate != null) {
+ delegate = null;
+ RuntimeException potentialException = new RuntimeException(
+ "Uncaught exceptions occured during unregistration");
+ boolean hasSuppressed = false;
+ for (Registration<?> registration : registrations) {
+ try {
+ registration.close();
+ } catch (Exception e) {
+ potentialException.addSuppressed(e);
+ hasSuppressed = true;
+ }
+ }
+ if (hasSuppressed) {
+ throw potentialException;
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataBrokerServiceProxy extends AbstractBrokerServiceProxy<DataBrokerService> implements DataBrokerService {
+
+ public DataBrokerServiceProxy(ServiceReference<DataBrokerService> ref, DataBrokerService delegate) {
+ super(ref, delegate);
+ }
+
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+ DataChangeListener listener) {
+ return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+ }
+
+ public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ return getDelegate().readConfigurationData(path);
+ }
+
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ return getDelegate().readOperationalData(path);
+ }
+
+ public DataModificationTransaction beginTransaction() {
+ return getDelegate().beginTransaction();
+ }
+
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataProviderService> implements
+ DataProviderService {
+
+ public DataProviderServiceProxy(ServiceReference<DataProviderService> ref, DataProviderService delegate) {
+ super(ref, delegate);
+ }
+
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+ DataChangeListener listener) {
+ return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+ }
+
+ public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ return getDelegate().readConfigurationData(path);
+ }
+
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ return getDelegate().readOperationalData(path);
+ }
+
+ public DataModificationTransaction beginTransaction() {
+ return getDelegate().beginTransaction();
+ }
+
+ @Override
+ public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+ getDelegate().addRefresher(store, refresher);
+ }
+
+ @Override
+ public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+ getDelegate().addValidator(store, validator);
+ }
+
+ @Override
+ public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+ InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+ return addRegistration(getDelegate().registerCommitHandler(path, commitHandler));
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+ InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+ return addRegistration(getDelegate().registerConfigurationReader(path, reader));
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+ InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+ return addRegistration(getDelegate().registerOperationalReader(path, reader));
+ }
+
+ @Override
+ public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+ getDelegate().removeRefresher(store, refresher);
+ }
+
+ @Override
+ public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+ getDelegate().removeValidator(store, validator);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class MountProviderServiceProxy extends AbstractBrokerServiceProxy<MountProvisionService> implements MountProvisionService{
+
+
+ public MountProviderServiceProxy(ServiceReference<MountProvisionService> ref, MountProvisionService delegate) {
+ super(ref, delegate);
+ }
+
+ public MountProvisionInstance getMountPoint(InstanceIdentifier path) {
+ return getDelegate().getMountPoint(path);
+ }
+
+ public MountProvisionInstance createMountPoint(InstanceIdentifier path) {
+ return getDelegate().createMountPoint(path);
+ }
+
+ public MountProvisionInstance createOrGetMountPoint(InstanceIdentifier path) {
+ return getDelegate().createOrGetMountPoint(path);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationPublishServiceProxy extends AbstractBrokerServiceProxy<NotificationPublishService> implements NotificationPublishService {
+
+ public NotificationPublishServiceProxy(ServiceReference<NotificationPublishService> ref,
+ NotificationPublishService delegate) {
+ super(ref, delegate);
+ }
+
+ public void sendNotification(CompositeNode notification) {
+ getDelegate().sendNotification(notification);
+ }
+
+ public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+ return addRegistration(getDelegate().addNotificationListener(notification, listener));
+
+ }
+
+ public void publish(CompositeNode notification) {
+ getDelegate().publish(notification);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationServiceProxy extends AbstractBrokerServiceProxy<NotificationService> implements
+ NotificationService {
+
+ public NotificationServiceProxy(ServiceReference<NotificationService> ref, NotificationService delegate) {
+ super(ref, delegate);
+ }
+
+ @Override
+ public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+ return addRegistration(getDelegate().addNotificationListener(notification, listener));
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi
+
+import org.opendaylight.controller.sal.core.api.BrokerService
+import org.osgi.framework.ServiceReference
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService
+import org.opendaylight.controller.sal.core.api.notify.NotificationService
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+
+class ProxyFactory {
+
+ static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
+ return createProxyImpl(serviceRef, service) as T;
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
+ new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
+ new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
+ new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
+ new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, MountProvisionService service) {
+ new MountProviderServiceProxy(ref as ServiceReference<MountProvisionService>, service);
+ }
+
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
+ new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
+ throw new IllegalArgumentException("Not supported class");
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.framework.ServiceReference;
+
+public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService> implements SchemaService {
+
+ public SchemaServiceProxy(ServiceReference<SchemaService> ref, SchemaService delegate) {
+ super(ref, delegate);
+ }
+
+ @Override
+ public void addModule(Module module) {
+ getDelegate().addModule(module);
+ }
+
+ @Override
+ public void removeModule(Module module) {
+ getDelegate().removeModule(module);
+ }
+
+ @Override
+ public SchemaContext getSessionContext() {
+ return null;
+ }
+
+ @Override
+ public SchemaContext getGlobalContext() {
+ return getDelegate().getGlobalContext();
+ }
+
+ @Override
+ public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+ ListenerRegistration<SchemaServiceListener> registration = getDelegate().registerSchemaServiceListener(listener);
+ addRegistration(registration);
+ return registration;
+ }
+
+
+
+}
<version>1.0-SNAPSHOT</version>
</parent>
<properties>
- <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+ <netconf.version>0.2.3-SNAPSHOT</netconf.version>
</properties>
<artifactId>sal-netconf-connector</artifactId>
<scm>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-client</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>${netconf.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
<version>0.5.9-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ <type>jar</type>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependencies>
<packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Bundle-Activator>org.opendaylight.controller.sal.connect.netconf.NetconfProvider</Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.net.URI;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class InventoryUtils {
+
+ private static final URI INVENTORY_NAMESPACE = URI.create("urn:opendaylight:inventory");
+ private static final Date INVENTORY_REVISION = date();
+ public static final QName INVENTORY_NODES = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "nodes");
+ public static final QName INVENTORY_NODE = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "node");
+ public static final QName INVENTORY_ID = new QName(INVENTORY_NAMESPACE, INVENTORY_REVISION, "id");
+
+ public static final InstanceIdentifier INVENTORY_PATH = InstanceIdentifier.builder().node(INVENTORY_NODES)
+ .toInstance();
+ public static final QName NETCONF_INVENTORY_MOUNT = null;
+
+
+
+ private static Date date() {
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+ try {
+ return formatter.parse("2013-08-19");
+ } catch (ParseException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.controller.md.sal.common.api.data.DataReader
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.netconf.client.NetconfClient
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import static extension org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*
+import java.net.InetSocketAddress
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import org.opendaylight.yangtools.yang.common.QName
+import java.util.Collections
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
+import org.opendaylight.yangtools.concepts.Registration
+
+class NetconfDevice implements DataReader<InstanceIdentifier, CompositeNode>, RpcImplementation {
+
+ var NetconfClient client;
+
+ @Property
+ var InetSocketAddress socketAddress;
+
+ @Property
+ val MountProvisionInstance mountInstance;
+
+ @Property
+ val InstanceIdentifier path;
+
+ Registration<DataReader<InstanceIdentifier,CompositeNode>> operReaderReg
+
+ Registration<DataReader<InstanceIdentifier,CompositeNode>> confReaderReg
+
+ public new(MountProvisionInstance mount,InstanceIdentifier path) {
+ _mountInstance = mount;
+ _path = path;
+ }
+
+ def start(NetconfClientDispatcher dispatcher) {
+ client = new NetconfClient("sal-netconf-connector", socketAddress, dispatcher);
+
+ confReaderReg = mountInstance.registerConfigurationReader(path,this);
+ operReaderReg = mountInstance.registerOperationalReader(path,this);
+ }
+
+ override readConfigurationData(InstanceIdentifier path) {
+ val result = invokeRpc(NETCONF_GET_CONFIG_QNAME, wrap(NETCONF_GET_CONFIG_QNAME, path.toFilterStructure()));
+ val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
+ return data?.findNode(path) as CompositeNode;
+ }
+
+ override readOperationalData(InstanceIdentifier path) {
+ val result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, path.toFilterStructure()));
+ val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
+ return data?.findNode(path) as CompositeNode;
+ }
+
+ override getSupportedRpcs() {
+ Collections.emptySet;
+ }
+
+ override invokeRpc(QName rpc, CompositeNode input) {
+ val message = rpc.toRpcMessage(input);
+ val result = client.sendMessage(message);
+ return result.toRpcResult();
+ }
+
+ def Node<?> findNode(CompositeNode node, InstanceIdentifier identifier) {
+
+ var Node<?> current = node;
+ for (arg : identifier.path) {
+ if (current instanceof SimpleNode<?>) {
+ return null;
+ } else if (current instanceof CompositeNode) {
+ val currentComposite = (current as CompositeNode);
+
+ current = currentComposite.getFirstCompositeByName(arg.nodeType);
+ if (current == null) {
+ current = currentComposite.getFirstSimpleByName(arg.nodeType);
+ }
+ if (current == null) {
+ return null;
+ }
+ }
+ }
+ return current;
+ }
+
+ public def stop() {
+ confReaderReg?.close()
+ operReaderReg?.close()
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService
+import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
+import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*;
+import static extension org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils.*;
+
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
+import java.util.Map
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
+import java.io.OptionalDataException
+import com.google.common.base.Optional
+import java.net.SocketAddress
+import java.net.InetSocketAddress
+
+class NetconfDeviceManager {
+
+ val Map<InstanceIdentifier, NetconfDevice> devices = new ConcurrentHashMap;
+
+ var ProviderSession session;
+
+ @Property
+ var DataProviderService dataService;
+
+ @Property
+ var MountProvisionService mountService;
+
+ val nodeUpdateListener = new NetconfInventoryListener(this);
+
+
+ @Property
+ var NetconfClientDispatcher dispatcher;
+
+ def void start() {
+ dataService?.registerDataChangeListener(INVENTORY_PATH, nodeUpdateListener);
+ if(dispatcher == null) {
+ dispatcher = new NetconfClientDispatcher(Optional.absent);
+ }
+ }
+
+ def netconfNodeAdded(InstanceIdentifier path, CompositeNode node) {
+ val address = node.endpointAddress;
+ val port = Integer.parseInt(node.endpointPort);
+ netconfNodeAdded(path,new InetSocketAddress(address,port))
+
+ }
+
+ def netconfNodeAdded(InstanceIdentifier path, InetSocketAddress address) {
+
+ val mountPointPath = path;
+ val mountPoint = mountService.createOrGetMountPoint(mountPointPath);
+ val localPath = InstanceIdentifier.builder().toInstance;
+ val netconfDevice = new NetconfDevice(mountPoint,localPath);
+ netconfDevice.setSocketAddress(address);
+ netconfDevice.start(dispatcher);
+ }
+
+ def netconfNodeRemoved(InstanceIdentifier path) {
+
+ }
+
+}
+
+class NetconfInventoryListener implements DataChangeListener {
+
+ val NetconfDeviceManager manager;
+
+ new(NetconfDeviceManager manager) {
+ this.manager = manager;
+ }
+
+ override onDataChanged(DataChangeEvent<InstanceIdentifier, CompositeNode> change) {
+
+ //manager.netconfNodeAdded(path, change);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public class NetconfInventoryUtils {
+
+
+ public static final QName NETCONF_MOUNT = null;
+ public static final QName NETCONF_ENDPOINT = null;
+ public static final QName NETCONF_ENDPOINT_ADDRESS = null;
+ public static final QName NETCONF_ENDPOINT_PORT = null;
+
+
+ public static String getEndpointAddress(CompositeNode node) {
+ return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_ADDRESS).getValue().toString();
+ }
+
+ public static String getEndpointPort(CompositeNode node) {
+ return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_PORT).getValue().toString();
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf
+
+import org.opendaylight.controller.netconf.api.NetconfMessage
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.common.RpcResult
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import java.net.URI
+import java.util.Collections
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.NodeUtils
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import java.util.concurrent.atomic.AtomicInteger
+import org.w3c.dom.Document
+import org.w3c.dom.Element
+import org.opendaylight.controller.sal.common.util.Rpcs
+
+class NetconfMapping {
+
+ public static val NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
+ public static val NETCONF_QNAME = new QName(NETCONF_URI,null,"netconf");
+ public static val NETCONF_RPC_QNAME = new QName(NETCONF_QNAME,"rpc");
+ public static val NETCONF_GET_QNAME = new QName(NETCONF_QNAME,"get");
+ public static val NETCONF_GET_CONFIG_QNAME = new QName(NETCONF_QNAME,"get-config");
+ public static val NETCONF_RPC_REPLY_QNAME = new QName(NETCONF_QNAME,"rpc-reply");
+ public static val NETCONF_OK_QNAME = new QName(NETCONF_QNAME,"ok");
+ public static val NETCONF_DATA_QNAME = new QName(NETCONF_QNAME,"data");
+
+
+ static val messageId = new AtomicInteger(0);
+
+
+
+ static def Node<?> toFilterStructure(InstanceIdentifier identifier) {
+ var Node<?> previous = null;
+ for (component : identifier.path.reverse) {
+ val Node<?> current = component.toNode(previous);
+ previous = current;
+ }
+ return previous;
+ }
+
+ static def dispatch Node<?> toNode(NodeIdentifierWithPredicates argument, Node<?> node) {
+ val list = new ArrayList<Node<?>>();
+ for( arg : argument.keyValues.entrySet) {
+ list.add = new SimpleNodeTOImpl(arg.key,null,arg.value);
+ }
+ return new CompositeNodeTOImpl(argument.nodeType,null,list)
+ }
+
+ static def dispatch Node<?> toNode(PathArgument argument, Node<?> node) {
+ if(node != null) {
+ return new CompositeNodeTOImpl(argument.nodeType,null,Collections.singletonList(node));
+ } else {
+ return new SimpleNodeTOImpl(argument.nodeType,null,null);
+ }
+ }
+
+ static def CompositeNode toCompositeNode(NetconfMessage message) {
+ return message.toRpcResult().result;
+ }
+
+ static def NetconfMessage toRpcMessage(QName rpc, CompositeNode node) {
+ val rpcPayload = wrap(NETCONF_RPC_QNAME,node);
+ val w3cPayload = NodeUtils.buildShadowDomTree(rpcPayload);
+ w3cPayload.documentElement.setAttribute("message-id","m-"+ messageId.andIncrement);
+ return new NetconfMessage(w3cPayload);
+ }
+
+ static def RpcResult<CompositeNode> toRpcResult(NetconfMessage message) {
+ val rawRpc = message.document.toCompositeNode() as CompositeNode;
+ //rawRpc.
+
+ return Rpcs.getRpcResult(true,rawRpc,Collections.emptySet());
+ }
+
+
+ static def wrap(QName name,Node<?> node) {
+ if(node != null) {
+ return new CompositeNodeTOImpl(name,null,Collections.singletonList(node));
+ }
+ else {
+ return new CompositeNodeTOImpl(name,null,Collections.emptyList());
+ }
+ }
+
+
+ public static def Node<?> toCompositeNode(Document document) {
+ return XmlDocumentUtils.toCompositeNode(document) as Node<?>
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.util.Hashtable;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.osgi.framework.BundleContext;
+
+public class NetconfProvider extends AbstractProvider {
+
+ private NetconfDeviceManager netconfDeviceManager;
+
+ @Override
+ protected void startImpl(BundleContext context) {
+ netconfDeviceManager = new NetconfDeviceManager();
+ context.registerService(NetconfDeviceManager.class, netconfDeviceManager, new Hashtable<String,String>());
+ }
+
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ MountProvisionService mountService = session.getService(MountProvisionService.class);
+
+
+ netconfDeviceManager.setMountService(mountService);
+ netconfDeviceManager.start();
+ }
+
+ @Override
+ protected void stopImpl(BundleContext context) {
+
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+public class XmlDocumentUtils {
+
+ public static CompositeNode toCompositeNode(Document doc) {
+ return (CompositeNode) toCompositeNode(doc.getDocumentElement());
+ }
+
+ private static Node<?> toCompositeNode(Element element) {
+ String orgNamespace = element.getNamespaceURI();
+ URI biNamespace = null;
+ if (orgNamespace != null) {
+ biNamespace = URI.create(orgNamespace);
+ }
+ QName qname = new QName(biNamespace, element.getLocalName());
+
+ List<Node<?>> values = new ArrayList<>();
+ NodeList nodes = element.getChildNodes();
+ boolean isSimpleObject = false;
+ String value = null;
+ for (int i = 0; i < nodes.getLength(); i++) {
+ org.w3c.dom.Node child = nodes.item(i);
+ if (child instanceof Element) {
+ isSimpleObject = false;
+ values.add(toCompositeNode((Element) child));
+ }
+ if (!isSimpleObject && child instanceof org.w3c.dom.Text) {
+ value = element.getTextContent();
+ if (value.matches(".*\\w.*")) {
+ isSimpleObject = true;
+ break;
+ }
+ }
+ }
+
+ if (isSimpleObject) {
+ return new SimpleNodeTOImpl<>(qname, null, value);
+ }
+ return new CompositeNodeTOImpl(qname, null, values);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.connector.netconf.test;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import io.netty.channel.ChannelFuture;
+import io.netty.util.HashedWheelTimer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
+import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClient;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
+import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
+import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
+import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
+import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.sal.dom.broker.DataBrokerImpl;
+import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+public class MountTest extends AbstractConfigTest {
+
+ private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
+ private static final InetSocketAddress tlsAddress = new InetSocketAddress("127.0.0.1", 12024);
+ private static final URI NETCONF_MONITORING_NS = URI.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring");
+
+ private static final QName NETCONF_MONITORING = new QName(NETCONF_MONITORING_NS, new Date(2010,10,04), "ietf-netconf-monitoring");
+ private static final QName NETCONF_MONITORING_STATE = new QName(NETCONF_MONITORING,"netconf-state");
+
+
+ private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
+ private DefaultCommitNotificationProducer commitNot;
+ private NetconfServerDispatcher dispatch;
+ private DataProviderService dataBroker;
+ private MountPointManagerImpl mountManager;
+ private NetconfDeviceManager netconfManager;
+
+ private static QName CONFIG_MODULES = new QName(
+ URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+ private static QName CONFIG_SERVICES = new QName(
+ URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+
+ private NetconfClient createSession(final InetSocketAddress address, NetconfClientDispatcher dispatcher) throws InterruptedException {
+ final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, dispatcher);
+ return netconfClient;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
+ new ModuleFactory[0])));
+
+ loadMessages();
+
+ NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+ factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+
+ commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
+
+ dispatch = createDispatcher(Optional.<SSLContext> absent(), factoriesListener);
+ ChannelFuture s = dispatch.createServer(tcpAddress);
+ s.await();
+
+ dataBroker = new DataBrokerImpl();
+ mountManager = new MountPointManagerImpl();
+ mountManager.setDataBroker(dataBroker);
+ netconfManager = new NetconfDeviceManager();
+
+ netconfManager.setMountService(mountManager);
+ netconfManager.setDataService(dataBroker);
+ netconfManager.start();
+
+ try (NetconfClient netconfClient = createSession(tcpAddress, netconfManager.getDispatcher())) {
+ // send edit_config.xml
+ final Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
+ assertNotNull(rpcReply);
+ }
+ }
+
+
+ protected List<ModuleFactory> getModuleFactories() {
+ return getModuleFactoriesS();
+ }
+
+ static List<ModuleFactory> getModuleFactoriesS() {
+ return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
+ new NetconfTestImplModuleFactory());
+ }
+
+ private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
+ this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
+ this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+ this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
+ this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
+ }
+
+ private NetconfServerDispatcher createDispatcher(Optional<SSLContext> sslC,
+ NetconfOperationServiceFactoryListenerImpl factoriesListener) {
+ SessionIdProvider idProvider = new SessionIdProvider();
+ NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+ new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
+
+ NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
+ factoriesListener, commitNot, idProvider);
+
+ return new NetconfServerDispatcher(sslC, serverNegotiatorFactory, listenerFactory);
+ }
+
+ private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+ final Collection<InputStream> yangDependencies = getBasicYangs();
+ return new HardcodedYangStoreService(yangDependencies);
+ }
+
+ private Collection<InputStream> getBasicYangs() throws IOException {
+ List<String> paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang",
+ "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang",
+ "/META-INF/yang/ietf-inet-types.yang");
+ final Collection<InputStream> yangDependencies = new ArrayList<>();
+ for (String path : paths) {
+ final InputStream is = Preconditions
+ .checkNotNull(getClass().getResourceAsStream(path), path + " not found");
+ yangDependencies.add(is);
+ }
+ return yangDependencies;
+ }
+
+ @Test
+ public void test() {
+ // MountProvisionInstance mount =
+ // Mockito.mock(MountProvisionInstance.class);
+ InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
+ .node(InventoryUtils.INVENTORY_NODE).toInstance();
+ netconfManager.netconfNodeAdded(path, tcpAddress);
+ InstanceIdentifier mountPointPath = path;
+ MountProvisionInstance mountPoint = mountManager.getMountPoint(mountPointPath);
+
+ CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
+ .toInstance());
+ assertNotNull(data);
+ assertEquals(CONFIG_MODULES, data.getNodeType());
+
+ CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
+ assertNotNull(data2);
+
+ InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
+
+ CompositeNode data3 = dataBroker.readOperationalData(fullPath);
+ assertNotNull(data3);
+ assertEquals(CONFIG_MODULES, data.getNodeType());
+ }
+
+}
org.eclipse.xtend.lib,
org.eclipse.xtext.xbase.*
</Private-Package>
+ <Import-Package>
+ *,
+ com.sun.jersey.spi.container.servlet
+ </Import-Package>
+ <Bundle-Activator>org.opendaylight.controller.sal.rest.impl.RestconfProvider</Bundle-Activator>
+ <Web-ContextPath>/restconf</Web-ContextPath>
</instructions>
</configuration>
</plugin>
--- /dev/null
+package org.opendaylight.controller.sal.rest.api;
+
+public class Draft02 {
+ public static class MediaTypes {
+ public static final String API = "application/yang.api";
+ public static final String DATASTORE = "application/yang.datastore";
+ public static final String DATA = "application/yang.data";
+ public static final String OPERATION = "application/yang.operation";
+ public static final String PATCH = "application/yang.patch";
+ public static final String PATCH_STATUS = "application/yang.patch-status";
+ public static final String STREAM = "application/yang.stream";
+ }
+
+ public static class Paths {
+
+ }
+}
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
/**
* Section 5 for details on each URI.
* <ul>
* <li><b>/restconf</b> - {@link #getRoot()}
- * <ul><li><b>/datastore</b> - {@link #readAllData()}
+ * <ul><li><b>/config</b>
+ * <li><b>/operational</b> - {@link #readAllData()} - Added in Draft02
+ * <li><b>/datastore</b> - {@link #readAllData()}
* <ul>
* <li>/(top-level-data-nodes) (config=true or false)
* </ul>
* <li>/version (field)
* </ul>
*/
-@Path("restconf")
-public interface RestconfService {
+@Path("/")
+public interface RestconfService extends RestconfServiceLegacy {
public static final String XML = "+xml";
public static final String JSON = "+json";
@GET
public Object getRoot();
+
@GET
- @Path("/datastore")
+ @Path("/modules")
@Produces({API+JSON,API+XML})
- public Object readAllData();
+ public StructuredData getModules();
+ @POST
+ @Path("/operations/{identifier}")
+ @Produces({Draft02.MediaTypes.API+JSON,Draft02.MediaTypes.API+XML,API+JSON,API+XML})
+ public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+
+
@GET
- @Path("/datastore/{identifier}")
- @Produces({API+JSON,API+XML})
- public StructuredData readData(@PathParam("identifier") String identifier);
+ @Path("/config/{identifier:.+}")
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+ public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
+
+
@PUT
- @Path("/datastore/{identifier}")
+ @Path("/config/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public Object createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+ public RpcResult<TransactionStatus> createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
@POST
- @Path("/datastore/{identifier}")
+ @Path("/config/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public Object updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+ public RpcResult<TransactionStatus> updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
@GET
- @Path("/modules")
+ @Path("/operational/{identifier:.+}")
+ @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML})
+ public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+
+ @PUT
+ @Path("/operational/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public Object getModules();
+ public RpcResult<TransactionStatus> createOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
@POST
- @Path("/operations/{identifier}")
+ @Path("/operational/{identifier:.+}")
@Produces({API+JSON,API+XML})
- public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+ public RpcResult<TransactionStatus> updateOperationalData(@PathParam("identifier") String identifier, CompositeNode payload);
+
+
}
--- /dev/null
+package org.opendaylight.controller.sal.rest.api;
+
+import static org.opendaylight.controller.sal.restconf.impl.MediaTypes.API;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+public interface RestconfServiceLegacy {
+
+ public static final String XML = "+xml";
+ public static final String JSON = "+json";
+
+ @Deprecated
+ @GET
+ @Path("/datastore")
+ @Produces({API+JSON,API+XML})
+ public StructuredData readAllData();
+
+ @Deprecated
+ @GET
+ @Path("/datastore/{identifier:.+}")
+ @Produces({API+JSON,API+XML})
+ public StructuredData readData(@PathParam("identifier") String identifier);
+
+ @Deprecated
+ @PUT
+ @Path("/datastore/{identifier:.+}")
+ @Produces({API+JSON,API+XML})
+ public RpcResult<TransactionStatus> createConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+ @Deprecated
+ @POST
+ @Path("/datastore/{identifier:.+}")
+ @Produces({API+JSON,API+XML})
+ public RpcResult<TransactionStatus> updateConfigurationDataLegacy(@PathParam("identifier") String identifier, CompositeNode payload);
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.rest.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+
+import com.google.gson.stream.JsonWriter;
+
+class JsonMapper {
+
+ private final Set<LeafListSchemaNode> foundLeafLists = new HashSet<>();
+ private final Set<ListSchemaNode> foundLists = new HashSet<>();
+
+ public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema) throws IOException {
+ writer.beginObject();
+ writeChildrenOfParent(writer, data, schema);
+ writer.endObject();
+ foundLeafLists.clear();
+ foundLists.clear();
+ }
+
+ private void writeChildrenOfParent(JsonWriter writer, CompositeNode parent, DataNodeContainer parentSchema) throws IOException {
+ checkNotNull(parent);
+ checkNotNull(parentSchema);
+
+ for (Node<?> child : parent.getChildren()) {
+ DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+ if (childSchema instanceof ContainerSchemaNode) {
+ writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema);
+ } else if (childSchema instanceof ListSchemaNode) {
+ if (!foundLists.contains(childSchema)) {
+ foundLists.add((ListSchemaNode) childSchema);
+ writeList(writer, (CompositeNode) child, (ListSchemaNode) childSchema);
+ }
+ } else if (childSchema instanceof LeafListSchemaNode) {
+ if (!foundLeafLists.contains(childSchema)) {
+ foundLeafLists.add((LeafListSchemaNode) childSchema);
+ writeLeafList(writer, (SimpleNode<?>) child, (LeafListSchemaNode) childSchema);
+ }
+ } else if (childSchema instanceof LeafSchemaNode) {
+ writeLeaf(writer, (SimpleNode<?>) child, (LeafSchemaNode) childSchema);
+ }
+ }
+
+ for (Node<?> child : parent.getChildren()) {
+ DataSchemaNode childSchema = findSchemaForNode(child, parentSchema.getChildNodes());
+ if (childSchema instanceof LeafListSchemaNode) {
+ foundLeafLists.remove((LeafListSchemaNode) childSchema);
+ } else if (childSchema instanceof ListSchemaNode) {
+ foundLists.remove((ListSchemaNode) childSchema);
+ }
+ }
+ }
+
+ private DataSchemaNode findSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
+ for (DataSchemaNode dsn : dataSchemaNode) {
+ if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
+ return dsn;
+ }
+ }
+ return null;
+ }
+
+ private void writeContainer(JsonWriter writer, CompositeNode node, ContainerSchemaNode schema) throws IOException {
+ writer.name(node.getNodeType().getLocalName());
+ writer.beginObject();
+ writeChildrenOfParent(writer, node, schema);
+ writer.endObject();
+ }
+
+ private void writeList(JsonWriter writer, CompositeNode node, ListSchemaNode schema) throws IOException {
+ writer.name(node.getNodeType().getLocalName());
+ writer.beginArray();
+
+ if (node.getParent() != null) {
+ CompositeNode parent = node.getParent();
+ List<CompositeNode> nodeLists = parent.getCompositesByName(node.getNodeType());
+ for (CompositeNode nodeList : nodeLists) {
+ writer.beginObject();
+ writeChildrenOfParent(writer, nodeList, schema);
+ writer.endObject();
+ }
+ } else {
+ writer.beginObject();
+ writeChildrenOfParent(writer, node, schema);
+ writer.endObject();
+ }
+
+ writer.endArray();
+ }
+
+ private void writeLeafList(JsonWriter writer, SimpleNode<?> node, LeafListSchemaNode schema) throws IOException {
+ writer.name(node.getNodeType().getLocalName());
+ writer.beginArray();
+
+ CompositeNode parent = node.getParent();
+ List<SimpleNode<?>> nodeLeafLists = parent.getSimpleNodesByName(node.getNodeType());
+ for (SimpleNode<?> nodeLeafList : nodeLeafLists) {
+ writeValueOfNodeByType(writer, nodeLeafList, schema.getType());
+ }
+
+ writer.endArray();
+ }
+
+ private void writeLeaf(JsonWriter writer, SimpleNode<?> node, LeafSchemaNode schema) throws IOException {
+ writer.name(node.getNodeType().getLocalName());
+ writeValueOfNodeByType(writer, node, schema.getType());
+ }
+
+ private void writeValueOfNodeByType(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> type) throws IOException {
+ if (!(node.getValue() instanceof String)) {
+ throw new IllegalStateException("Value in SimpleNode should be type String");
+ }
+
+ String value = (String) node.getValue();
+ // TODO check Leafref, InstanceIdentifierTypeDefinition, IdentityrefTypeDefinition, UnionTypeDefinition
+ if (type.getBaseType() != null) {
+ writeValueOfNodeByType(writer, node, type.getBaseType());
+ } else if (type instanceof InstanceIdentifierTypeDefinition) {
+ writer.value(((InstanceIdentifierTypeDefinition) type).getPathStatement().toString());
+ } else if (type instanceof DecimalTypeDefinition
+ || type instanceof IntegerTypeDefinition
+ || type instanceof UnsignedIntegerTypeDefinition) {
+ writer.value(new NumberForJsonWriter(value));
+ } else if (type instanceof BooleanTypeDefinition) {
+ writer.value(Boolean.parseBoolean(value));
+ } else if (type instanceof EmptyTypeDefinition) {
+ writer.value("[null]");
+ } else {
+ writer.value(value);
+ }
+ }
+
+ private static final class NumberForJsonWriter extends Number {
+
+ private static final long serialVersionUID = -3147729419814417666L;
+ private final String value;
+
+ public NumberForJsonWriter(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public int intValue() {
+ throw new IllegalStateException("Should not be invoked");
+ }
+
+ @Override
+ public long longValue() {
+ throw new IllegalStateException("Should not be invoked");
+ }
+
+ @Override
+ public float floatValue() {
+ throw new IllegalStateException("Should not be invoked");
+ }
+
+ @Override
+ public double doubleValue() {
+ throw new IllegalStateException("Should not be invoked");
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ }
+
+}
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- // TODO Auto-generated method stub
- return false;
+ return true;
}
@Override
--- /dev/null
+package org.opendaylight.controller.sal.rest.impl;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
+import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.osgi.framework.BundleContext;
+
+public class RestconfProvider extends AbstractProvider {
+
+ private ListenerRegistration<SchemaServiceListener> listenerRegistration;
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ DataBrokerService dataService = session.getService(DataBrokerService.class);
+
+ BrokerFacade.getInstance().setContext(session);
+ BrokerFacade.getInstance().setDataService(dataService);
+
+ SchemaService schemaService = session.getService(SchemaService.class);
+ listenerRegistration = schemaService.registerSchemaServiceListener(ControllerContext.getInstance());
+ ControllerContext.getInstance().setSchemas(schemaService.getGlobalContext());
+ }
+
+ @Override
+ protected void stopImpl(BundleContext context) {
+ super.stopImpl(context);
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
-import java.util.List;
-import java.util.Set;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import org.opendaylight.controller.sal.rest.api.RestconfService;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
import com.google.gson.stream.JsonWriter;
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- // TODO Auto-generated method stub
- return false;
+ return true;
}
@Override
throws IOException, WebApplicationException {
JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, "UTF-8"));
writer.setIndent(" ");
- writer.beginObject();
- convertNodeToJsonAccordingToSchema(writer, t.getData(), t.getSchema());
- writer.endObject();
+ JsonMapper jsonMapper = new JsonMapper();
+ jsonMapper.write(writer, t.getData(), (DataNodeContainer) t.getSchema());
+ writer.flush();
}
-
- private void convertNodeToJsonAccordingToSchema(JsonWriter writer, Node<?> node, DataSchemaNode dataSchemaNode) throws IOException {
- if (node instanceof CompositeNode) {
- if (!(dataSchemaNode instanceof DataNodeContainer)) {
- throw new IllegalStateException("CompositeNode should be represented as DataNodeContainer");
- }
- if (dataSchemaNode instanceof ContainerSchemaNode) {
- writer.name(node.getNodeType().getLocalName());
- writer.beginObject();
- String listName = "";
- for (Node<?> n : ((CompositeNode) node).getChildren()) {
- DataSchemaNode foundDataSchemaNode = findSchemaForNode(n, ((DataNodeContainer) dataSchemaNode).getChildNodes());
- if (foundDataSchemaNode instanceof ListSchemaNode) {
- if (listName.equals(n.getNodeType().getLocalName())) {
- continue;
- }
- listName = n.getNodeType().getLocalName();
- }
- convertNodeToJsonAccordingToSchema(writer, n, foundDataSchemaNode);
- }
- writer.endObject();
- } else if (dataSchemaNode instanceof ListSchemaNode) {
- writer.name(node.getNodeType().getLocalName());
- writer.beginArray();
- List<Node<?>> nodeSiblings = node.getParent().getChildren();
- for (Node<?> nodeSibling : nodeSiblings) {
- if (nodeSibling.getNodeType().getLocalName().equals(node.getNodeType().getLocalName())) {
- DataSchemaNode schemaForNodeSibling = findSchemaForNode(nodeSibling,
- ((DataNodeContainer) dataSchemaNode.getParent()).getChildNodes());
- writer.beginObject();
- for (Node<?> child : ((CompositeNode) nodeSibling).getChildren()) {
- DataSchemaNode schemaForChild = findSchemaForNode(child,
- ((DataNodeContainer) schemaForNodeSibling).getChildNodes());
- convertNodeToJsonAccordingToSchema(writer, child, schemaForChild);
- }
- writer.endObject();
- }
- }
- writer.endArray();
- }
- } else if (node instanceof SimpleNode<?>) {
- if (!(dataSchemaNode instanceof LeafSchemaNode)) {
- throw new IllegalStateException("SimpleNode should should be represented as LeafSchemaNode");
- }
- writeLeaf(writer, (LeafSchemaNode) dataSchemaNode, (SimpleNode<?>) node);
- }
- }
-
- private DataSchemaNode findSchemaForNode(Node<?> node, Set<DataSchemaNode> dataSchemaNode) {
- for (DataSchemaNode dsn : dataSchemaNode) {
- if (node.getNodeType().getLocalName().equals(dsn.getQName().getLocalName())) {
- return dsn;
- }
- }
- return null;
- }
-
- private void writeLeaf(JsonWriter writer, LeafSchemaNode leafSchemaNode, SimpleNode<?> data) throws IOException {
- TypeDefinition<?> type = leafSchemaNode.getType();
-
- writer.name(data.getNodeType().getLocalName());
-
- if (type instanceof DecimalTypeDefinition) {
- writer.value((Double.valueOf((String) data.getValue())).doubleValue());
- } else if (type instanceof IntegerTypeDefinition) {
- writer.value((Integer.valueOf((String) data.getValue())).intValue());
- } else if (type instanceof EmptyTypeDefinition) {
- writer.value("[null]");
- } else {
- writer.value(String.valueOf(data.getValue()));
- }
- }
-
+
}
return future.get;
}
- def commitConfigurationDataUpdate(InstanceIdentifier path, CompositeNode payload) {
+ def commitConfigurationDataPut(InstanceIdentifier path, CompositeNode payload) {
val transaction = dataService.beginTransaction;
transaction.putConfigurationData(path, payload);
return transaction.commit()
}
- def commitConfigurationDataCreate(InstanceIdentifier path, CompositeNode payload) {
+ def commitOperationalDataPut(InstanceIdentifier path, CompositeNode payload) {
val transaction = dataService.beginTransaction;
- transaction.putConfigurationData(path, payload);
+ transaction.putOperationalData(path, payload);
return transaction.commit()
}
import org.opendaylight.yangtools.yang.model.api.SchemaContext
import static com.google.common.base.Preconditions.*
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import java.util.concurrent.ConcurrentHashMap
+
+class ControllerContext implements SchemaServiceListener {
-class ControllerContext {
-
val static ControllerContext INSTANCE = new ControllerContext
-
+
val static NULL_VALUE = "null"
-
+
@Property
SchemaContext schemas;
private val BiMap<URI, String> uriToModuleName = HashBiMap.create();
private val Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
+ private val Map<QName,RpcDefinition> qnameToRpc = new ConcurrentHashMap();
+
private new() {
if (INSTANCE != null) {
if (targetNode instanceof ListSchemaNode) {
val listNode = targetNode as ListSchemaNode;
val keysSize = listNode.keyDefinition.size
+
// every key has to be filled
if ((strings.length - consumed) < keysSize) {
return null;
var i = 0;
for (key : listNode.keyDefinition) {
val uriKeyValue = uriKeyValues.get(i);
+
// key value cannot be NULL
if (uriKeyValue.equals(NULL_VALUE)) {
return null
consumed = consumed + i;
builder.nodeWithKey(targetNode.QName, keyValues);
} else {
+
// Only one instance of node is allowed
builder.node(targetNode.QName);
}
}
}
- public def QName toRpcQName(String name) {
+ public def QName toQName(String name) {
+ val module = name.toModuleName;
+ val node = name.toNodeName;
+ val namespace = moduleNameToUri.get(module);
+ return new QName(namespace,null,node);
+ }
+
+ override onGlobalContextUpdated(SchemaContext context) {
+ this.schemas = context;
+ for(operation : context.operations) {
+ val qname = new QName(operation.QName.namespace,null,operation.QName.localName);
+ qnameToRpc.put(qname,operation);
+ }
+ }
+
+ def ContainerSchemaNode getRpcOutputSchema(QName name) {
+ qnameToRpc.get(name)?.output;
}
+
}
+++ /dev/null
-package org.opendaylight.controller.sal.restconf.impl
-
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-
-class JsonMapper {
-
- @Property
- ControllerContext controllerContext
-
- def convert(DataSchemaNode schema, CompositeNode data) {
- return ""
- }
-
-}
\ No newline at end of file
override readAllData() {
// return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ throw new UnsupportedOperationException("Reading all data is currently not supported.")
}
override getModules() {
}
override getRoot() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
-
+ return null;
}
override readData(String identifier) {
}
override createConfigurationData(String identifier, CompositeNode payload) {
-// return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
}
override updateConfigurationData(String identifier, CompositeNode payload) {
-// return broker.commitConfigurationDataCreate(identifier.toInstanceIdentifier.getInstanceIdentifier, payload);
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitConfigurationDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
}
override invokeRpc(String identifier, CompositeNode payload) {
- val rpcResult = broker.invokeRpc(identifier.toRpcQName, payload);
- return new StructuredData(rpcResult.result, identifier.toInstanceIdentifier.getSchemaNode)
+ val rpc = identifier.toQName;
+ val rpcResult = broker.invokeRpc(rpc, payload);
+ val schema = controllerContext.getRpcOutputSchema(rpc);
+ return new StructuredData(rpcResult.result, schema);
+ }
+
+ override readConfigurationData(String identifier) {
+ val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+ val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+ return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+ }
+
+ override readOperationalData(String identifier) {
+ val instanceIdentifierWithSchemaNode = identifier.toInstanceIdentifier
+ val data = broker.readOperationalData(instanceIdentifierWithSchemaNode.getInstanceIdentifier);
+ return new StructuredData(data, instanceIdentifierWithSchemaNode.schemaNode)
+ }
+
+ override updateConfigurationDataLegacy(String identifier, CompositeNode payload) {
+ updateConfigurationData(identifier,payload);
+ }
+
+ override createConfigurationDataLegacy(String identifier, CompositeNode payload) {
+ createConfigurationData(identifier,payload);
+ }
+
+ override createOperationalData(String identifier, CompositeNode payload) {
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
+ }
+
+ override updateOperationalData(String identifier, CompositeNode payload) {
+ val identifierWithSchemaNode = identifier.toInstanceIdentifier
+ return broker.commitOperationalDataPut(identifierWithSchemaNode.instanceIdentifier,payload).get();
}
}
--- /dev/null
+<?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>JAXRSRestconf</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.sal.rest.impl.RestconfApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAXRSRestconf</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</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>NB api</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>
+ </security-constraint>
+
+</web-app>
package org.opendaylight.controller.sal.restconf.impl.test;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import javax.ws.rs.WebApplicationException;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.*;
import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.slf4j.Logger;
}
}
+
+ static String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+ String jsonResult = null;
+ Set<Module> modules = null;
+
+ try {
+ modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ assertNotNull("modules can't be null.", modules);
+
+ InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+ CompositeNode compositeNode = null;
+ try {
+ compositeNode = TestUtils.loadCompositeNode(xmlStream);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ assertNotNull("Composite node can't be null", compositeNode);
+
+ StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+ for (Module module : modules) {
+ for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+ StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+ ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+ try {
+ structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+ } catch (WebApplicationException | IOException e) {
+ e.printStackTrace();
+ }
+ assertFalse(
+ "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+ byteArrayOS.toString().isEmpty());
+ jsonResult = byteArrayOS.toString();
+ try {
+ outputToFile(byteArrayOS);
+ } catch (IOException e) {
+ System.out.println("Output file wasn't cloased sucessfuly.");
+ }
+ }
+ }
+ return jsonResult;
+ }
+
+ static void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+ FileOutputStream fileOS = null;
+ try {
+ String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+ File outFile = new File(path + "/data.json");
+ fileOS = new FileOutputStream(outFile);
+ try {
+ fileOS.write(outputStream.toByteArray());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ fileOS.close();
+ } catch (FileNotFoundException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ static String readJsonFromFile(String path,boolean removeWhiteChars) {
+ FileReader fileReader = getFileReader(path);
+
+ StringBuilder strBuilder = new StringBuilder();
+ char[] buffer = new char[1000];
+
+ while (true) {
+ int loadedCharNum;
+ try {
+ loadedCharNum = fileReader.read(buffer);
+ } catch (IOException e) {
+ break;
+ }
+ if (loadedCharNum == -1) {
+ break;
+ }
+ strBuilder.append(buffer, 0, loadedCharNum);
+ }
+ try {
+ fileReader.close();
+ } catch (IOException e) {
+ System.out.println("The file wasn't closed");
+ }
+ String rawStr = strBuilder.toString();
+ if (removeWhiteChars) {
+ rawStr = rawStr.replace("\n", "");
+ rawStr = rawStr.replace("\r", "");
+ rawStr = rawStr.replace("\t", "");
+ rawStr = removeSpaces(rawStr);
+ }
+
+ return rawStr;
+ }
+
+ private static FileReader getFileReader(String path) {
+ String fullPath = YangAndXmlToJsonConversionJsonReaderTest.class.getResource(path).getPath();
+ assertNotNull("Path to file can't be null.", fullPath);
+ File file = new File(fullPath);
+ assertNotNull("File can't be null", file);
+ FileReader fileReader = null;
+ try {
+ fileReader = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ assertNotNull("File reader can't be null.", fileReader);
+ return fileReader;
+ }
+
+ private static String removeSpaces(String rawStr) {
+ StringBuilder strBuilder = new StringBuilder();
+ int i = 0;
+ int quoteCount = 0;
+ while (i < rawStr.length()) {
+ if (rawStr.substring(i, i + 1).equals("\"")) {
+ quoteCount++;
+ }
+
+ if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
+ strBuilder.append(rawStr.charAt(i));
+ }
+ i++;
+ }
+
+ return strBuilder.toString();
+ }
+
+
}
public void testStructuredDataToXmlProvider() throws FileNotFoundException {
URI uri = null;
try {
- uri = new URI("/restconf/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+ uri = new URI("/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
} catch (UnsupportedEncodingException | URISyntaxException e) {
e.printStackTrace();
}
public void testXmlToCompositeNodeProvider() throws ParserConfigurationException, SAXException, IOException {
URI uri = null;
try {
- uri = new URI("/restconf/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+ uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
} catch (UnsupportedEncodingException | URISyntaxException e) {
e.printStackTrace();
}
public void testXmlToCompositeNodeProviderExceptions() {
URI uri = null;
try {
- uri = new URI("/restconf/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+ uri = new URI("/operations/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
} catch (UnsupportedEncodingException | URISyntaxException e) {
e.printStackTrace();
}
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.Test;
+
+import com.google.gson.stream.JsonReader;
+
+public class YangAndXmlToJsonConversionJsonReaderTest {
+
+ @Test
+ public void simpleYangTypesWithJsonReaderTest() {
+ String jsonOutput;
+ jsonOutput = TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
+ false);
+
+// jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+// "/yang-to-json-conversion/simple-yang-types");
+
+ StringReader strReader = new StringReader(jsonOutput);
+ JsonReader jReader = new JsonReader(strReader);
+ try {
+ checkCont1(jReader);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void checkCont1(JsonReader jReader) throws IOException {
+ jReader.beginObject();
+ assertNotNull("cont1 is missing.", jReader.hasNext());
+ jReader.nextName();
+ checkCont1Elements(jReader, prepareInputData(jReader), "cont1/");
+ jReader.endObject();
+
+ }
+
+ private Map<String, String> prepareInputData(JsonReader jReader) {
+ Map<String, String> dataMap = new HashMap<>();
+ dataMap.put("cont1/lf11", "lf");
+ dataMap.put("cont1/lflst11.1", "55");
+ dataMap.put("cont1/lflst11.2", "56");
+ dataMap.put("cont1/lflst11.3", "57");
+ dataMap.put("cont1/lflst12.1", "lflst12 str1");
+ dataMap.put("cont1/lflst12.2", "lflst12 str2");
+ dataMap.put("cont1/lflst12.3", "lflst12 str3");
+
+ dataMap.put("cont1/lst11.1/lf111", "140");
+ dataMap.put("cont1/lst11.1/lf112", "lf112 str");
+ dataMap.put("cont1/lst11.1/cont111/lf1111", "lf1111 str");
+ dataMap.put("cont1/lst11.1/cont111/lflst1111.1", "2048");
+ dataMap.put("cont1/lst11.1/cont111/lflst1111.2", "1024");
+ dataMap.put("cont1/lst11.1/cont111/lflst1111.3", "4096");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111A", "lf1111A str11");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111B", "4");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111A", "lf1111A str12");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111B", "7");
+ dataMap.put("cont1/lst11.1/lst111.1/lf1111", "65");
+ dataMap.put("cont1/lst11.1/lst112.1/lf1121", "lf1121 str11");
+
+ dataMap.put("cont1/lst11.2/lf111", "141");
+ dataMap.put("cont1/lst11.2/lf112", "lf112 str2");
+ dataMap.put("cont1/lst11.2/cont111/lf1111", "lf1111 str2");
+ dataMap.put("cont1/lst11.2/cont111/lflst1111.1", "2049");
+ dataMap.put("cont1/lst11.2/cont111/lflst1111.2", "1025");
+ dataMap.put("cont1/lst11.2/cont111/lflst1111.3", "4097");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111A", "lf1111A str21");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111B", "5");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111A", "lf1111A str22");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111B", "8");
+ dataMap.put("cont1/lst11.2/lst111.1/lf1111", "55");
+ dataMap.put("cont1/lst11.2/lst111.2/lf1111", "56");
+ dataMap.put("cont1/lst11.2/lst112.1/lf1121", "lf1121 str21");
+ dataMap.put("cont1/lst11.2/lst112.2/lf1121", "lf1121 str22");
+
+ return dataMap;
+
+ }
+
+ private void checkCont1Elements(JsonReader jReader, Map<String, String> dataMap, String pthPref) throws IOException {
+ Set<String> keys = new HashSet<>();
+ jReader.beginObject();
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf11")) {
+ assertEquals("Key " + keyName + " has incorrect value.", dataMap.get(pthPref + keyName),
+ jReader.nextString());
+ keys.add(keyName);
+ } else if (keyName.equals("lflst11")) {
+ checkLflstValues(jReader, pthPref + keyName, dataMap);
+ keys.add(keyName);
+ } else if (keyName.equals("lflst12")) {
+ checkLflstValues(jReader, pthPref + keyName, dataMap);
+ keys.add(keyName);
+ } else if (keyName.equals("lst11")) {
+ checkLst11(jReader, pthPref + keyName, dataMap);
+ keys.add(keyName);
+ } else {
+ assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+ }
+ }
+ jReader.endObject();
+ assertEquals("Incorrect number of keys in cont1", 4, keys.size());
+
+ }
+
+ private void checkLst11(JsonReader jReader, String pthPref, Map<String, String> dataMap) throws IOException {
+ jReader.beginArray();
+
+ int arrayLength = 0;
+ while (jReader.hasNext()) {
+ checkLst11Elements(jReader, pthPref + "." + ++arrayLength + "/", dataMap);
+ }
+ jReader.endArray();
+ assertEquals("Incorrect number of items in lst11 array.", 2, arrayLength);
+ }
+
+ private void checkLst11Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf111")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ } else if (keyName.equals("lf112")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ } else if (keyName.equals("cont111")) {
+ checkCont111(jReader, pthPref + keyName, data);
+ } else if (keyName.equals("lst111")) {
+ checkLst111(jReader, pthPref + keyName, data);
+ } else if (keyName.equals("lst112")) {
+ checkLst112(jReader, pthPref + keyName, data);
+ } else {
+ assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+ }
+ }
+ jReader.endObject();
+ }
+
+ private void checkLst112(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 0;
+ while (jReader.hasNext()) {
+ checkLst112Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+ }
+ jReader.endArray();
+ }
+
+ private void checkLst112Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ if (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ }
+ jReader.endObject();
+
+ }
+
+ private void checkLst111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 0;
+ while (jReader.hasNext()) {
+ checkLst111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+ }
+ jReader.endArray();
+ }
+
+ private void checkLst111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ if (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ }
+ jReader.endObject();
+ }
+
+ private void checkCont111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ checkCont111Elements(jReader, pthPref + "/", data);
+ jReader.endObject();
+ }
+
+ private void checkCont111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf1111")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ } else if (keyName.equals("lflst1111")) {
+ checkLflstValues(jReader, pthPref + keyName, data);
+ } else if (keyName.equals("lst1111")) {
+ checkLst1111(jReader, pthPref + keyName, data);
+ }
+ }
+
+ }
+
+ private void checkLst1111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 0;
+ while (jReader.hasNext()) {
+ checkLst1111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+ }
+ jReader.endArray();
+ }
+
+ private void checkLst1111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf1111A")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+
+ } else if (keyName.equals("lf1111B")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ }
+ }
+ jReader.endObject();
+ }
+
+ private void checkLflstValues(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 1;
+ String keyValue = null;
+ List<String> searchedValues = new ArrayList<>();
+ while ((keyValue = data.get(pthPref + "." + arrayIndex++)) != null) {
+ searchedValues.add(keyValue);
+ }
+
+ while (jReader.hasNext()) {
+ String value = jReader.nextString();
+ assertTrue("Value " + value + " of lflst " + pthPref + " wasn't found", searchedValues.contains(value));
+ }
+
+ jReader.endArray();
+ }
+
+
+
+}
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
-import java.io.*;
-import java.util.Set;
-import java.util.regex.*;
+import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
+import org.junit.Test;
-import org.junit.*;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.model.api.*;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+public class YangAndXmlToJsonConversionRegExTest {
-public class YangAndXmlToJsonConversion {
-
- @Ignore
@Test
/**
* Test for simple yang types (leaf, list, leaf-list, container and various combination of them)
public void simpleYangTypesTest() {
String jsonOutput = null;
- jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
- "/yang-to-json-conversion/simple-yang-types");
+// jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+// "/yang-to-json-conversion/simple-yang-types");
-// jsonOutput =
-// readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json");
+ jsonOutput =
+ TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",true);
verifyJsonOutputForSimpleYangTypes(jsonOutput);
-
- }
+ }
private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) {
return null;
}
- private String readJsonFromFile(String path) {
- String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath();
- assertNotNull("Path to file can't be null.", fullPath);
- File file = new File(fullPath);
- assertNotNull("File can't be null", file);
- FileReader fileReader = null;
- try {
- fileReader = new FileReader(file);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- assertNotNull("File reader can't be null.", fileReader);
-
- StringBuilder strBuilder = new StringBuilder();
- char[] buffer = new char[1000];
-
- while (true) {
- int loadedCharNum;
- try {
- loadedCharNum = fileReader.read(buffer);
- } catch (IOException e) {
- break;
- }
- if (loadedCharNum == -1) {
- break;
- }
- strBuilder.append(buffer, 0, loadedCharNum);
- }
- try {
- fileReader.close();
- } catch (IOException e) {
- System.out.println("The file wasn't closed");
- ;
- }
- String rawStr = strBuilder.toString();
- rawStr = rawStr.replace("\n", "");
- rawStr = rawStr.replace("\r", "");
- rawStr = rawStr.replace("\t", "");
- rawStr = removeSpaces(rawStr);
-
- return rawStr;
- }
-
- private String removeSpaces(String rawStr) {
- StringBuilder strBuilder = new StringBuilder();
- int i = 0;
- int quoteCount = 0;
- while (i < rawStr.length()) {
- if (rawStr.substring(i, i + 1).equals("\"")) {
- quoteCount++;
- }
- if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
- strBuilder.append(rawStr.charAt(i));
- }
- i++;
- }
-
- return strBuilder.toString();
- }
- private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
- String jsonResult = null;
- Set<Module> modules = null;
- try {
- modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath());
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- assertNotNull("modules can't be null.", modules);
-
- InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath);
- CompositeNode compositeNode = null;
- try {
- compositeNode = TestUtils.loadCompositeNode(xmlStream);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- assertNotNull("Composite node can't be null", compositeNode);
+// private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+// String jsonResult = null;
+// Set<Module> modules = null;
+//
+// try {
+// modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+// } catch (FileNotFoundException e) {
+// e.printStackTrace();
+// }
+// assertNotNull("modules can't be null.", modules);
+//
+// InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+// CompositeNode compositeNode = null;
+// try {
+// compositeNode = TestUtils.loadCompositeNode(xmlStream);
+// } catch (FileNotFoundException e) {
+// e.printStackTrace();
+// }
+// assertNotNull("Composite node can't be null", compositeNode);
+//
+// StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+// for (Module module : modules) {
+// for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+// StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+// ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+// try {
+// structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+// } catch (WebApplicationException | IOException e) {
+// e.printStackTrace();
+// }
+// assertFalse(
+// "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+// byteArrayOS.toString().isEmpty());
+// jsonResult = byteArrayOS.toString();
+// try {
+// outputToFile(byteArrayOS);
+// } catch (IOException e) {
+// System.out.println("Output file wasn't cloased sucessfuly.");
+// }
+// }
+// }
+// return jsonResult;
+// }
+//
+// private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+// FileOutputStream fileOS = null;
+// try {
+// String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+// File outFile = new File(path + "/data.json");
+// fileOS = new FileOutputStream(outFile);
+// try {
+// fileOS.write(outputStream.toByteArray());
+// } catch (IOException e) {
+// e.printStackTrace();
+// }
+// fileOS.close();
+// } catch (FileNotFoundException e1) {
+// e1.printStackTrace();
+// }
+// }
+
- StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
- for (Module module : modules) {
- for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
- StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
- ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
- try {
- structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
- } catch (WebApplicationException | IOException e) {
- e.printStackTrace();
- }
- assertFalse(
- "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
- byteArrayOS.toString().isEmpty());
- jsonResult = byteArrayOS.toString();
- try {
- outputToFile(byteArrayOS);
- } catch (IOException e) {
- System.out.println("Output file wasn't cloased sucessfuly.");
- }
- }
- }
- return jsonResult;
- }
-
- private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
- FileOutputStream fileOS = null;
- try {
- String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath();
- File outFile = new File(path + "/data.json");
- fileOS = new FileOutputStream(outFile);
- try {
- fileOS.write(outputStream.toByteArray());
- } catch (IOException e) {
- e.printStackTrace();
- }
- fileOS.close();
- } catch (FileNotFoundException e1) {
- e1.printStackTrace();
- }
- }
}
"lf1111B": 7
}
]
- }
+ },
+ "lst111" : [
+ {
+ "lf1111" : 65
+ }
+ ],
+ "lst112" : [
+ {
+ "lf1121" : "lf1121 str11"
+ }
+ ]
+
},
{
"lf111":141,
"lf1111B": 8
}
]
- }
+ },
+ "lst111" : [
+ {
+ "lf1111" : 55
+ },
+ {
+ "lf1111" : 56
+ }
+ ],
}
]
+ "lst112" : [
+ {
+ "lf1121" : "lf1121 str21"
+ },
+ {
+ "lf1121" : "lf1121 str22"
+ }
+ ]
+ }
+ ]
}
}
\ No newline at end of file
<?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>sal-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- </parent>
+ 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>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-zeromq-connector</artifactId>
+ <packaging>bundle</packaging>
- <artifactId>sal-zeromq-connector</artifactId>
- <packaging>bundle</packaging>
+ <properties>
+ <scala.version>2.10.3</scala.version>
+ </properties>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Import-Package>
- org.opendaylight.controller.sal.connector.api,
- org.opendaylight.controller.sal.core.api,
- org.opendaylight.yangtools.concepts;version="[0.1,1)",
- org.opendaylight.yangtools.yang.common;version="[0.5,1)",
- org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
- org.zeromq;version="[0.3,1)"
- </Import-Package>
- <Bundle-Activator>org.opendaylight.controller.sal.connector.zeromq.Activator</Bundle-Activator>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.northbound</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-binding</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-connector-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- <version>1.0-SNAPSHOT</version>
- </dependency>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.opendaylight.controller.sal.connector.api,
+ org.opendaylight.controller.sal.core.api,
+ org.opendaylight.yangtools.concepts;version="[0.1,1)",
+ org.opendaylight.yangtools.yang.common;version="[0.5,1)",
+ org.opendaylight.yangtools.yang.data.api;version="[0.5,1)",
+ org.zeromq;version="[0.3,1)"
+ </Import-Package>
+ <Bundle-Activator>org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Activator</Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.jeromq</groupId>
- <artifactId>jeromq</artifactId>
- <version>0.3.0-SNAPSHOT</version>
- </dependency>
+ <plugin>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>scala-maven-plugin</artifactId>
+ <version>3.1.6</version>
+ <configuration>
+ <recompileMode>incremental</recompileMode>
+ <args>
+ <arg>-target:jvm-1.7</arg>
+ </args>
+ <javacArgs>
+ <javacArg>-source</javacArg><javacArg>1.7</javacArg>
+ <javacArg>-target</javacArg><javacArg>1.7</javacArg>
+ </javacArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <id>scala-compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>scala-test-compile</id>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ </execution>
+ </executions>
- </dependencies>
- <repositories>
- <repository>
- <id>sonatype-nexus-snapshots</id>
- <url>https://oss.sonatype.org/content/repositories/snapshots</url>
- <releases>
- <enabled>false</enabled>
- </releases>
- <snapshots>
- <enabled>true</enabled>
- </snapshots>
- </repository>
- </repositories>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default-compile</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>default-testCompile</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.scala-lang</groupId>
+ <artifactId>scala-library</artifactId>
+ <version>${scala.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-connector-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jeromq</groupId>
+ <artifactId>jeromq</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+
+ </dependencies>
+ <repositories>
+ <repository>
+ <id>sonatype-nexus-snapshots</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
</project>
--- /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.sal.connector.remoterpc.api;
+
+import java.util.Map;
+import java.util.Set;
+
+public interface RouteChange<I, R> {
+
+ Map<I, Set<R>> getRemovals();
+ Map<I, Set<R>> getAnnouncements();
+}
--- /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.sal.connector.remoterpc.api;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.util.EventListener;
+
+public interface RouteChangeListener extends EventListener {
+
+ public void onRouteChanged(RouteChange<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> change);
+}
--- /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.sal.connector.remoterpc.api;
+
+import java.util.Set;
+
+public interface RoutingTable<I,R> {
+
+ /**
+ * Adds a network address for the route. If address for route
+ * exists, appends the address to the list
+ *
+ * @param routeId route identifier
+ * @param route network address
+ */
+ public void addRoute(I routeId, R route);
+
+ /**
+ * Adds a network address for the route. If the route already exists,
+ * it throws. This method would be used when registering a global service.
+ *
+ * @param routeId route identifier
+ * @param route network address
+ * @throws DuplicateRouteException
+ */
+ public void addGlobalRoute(I routeId, R route) throws DuplicateRouteException;
+
+ /**
+ * Removes the network address for the route from routing table. If only
+ * one network address existed, remove the route as well.
+ * @param routeId
+ * @param route
+ */
+ public void removeRoute(I routeId, R route);
+
+ /**
+ * Returns a set of network addresses associated with this route
+ * @param routeId
+ * @return
+ */
+ public Set<R> getRoutes(I routeId);
+
+ /**
+ * Returns only one address from the list of network addresses
+ * associated with the route. The algorithm to determine that
+ * one address is upto the implementer
+ * @param route
+ * @return
+ */
+ public R getARoute(I routeId);
+
+ public void registerRouteChangeListener(RouteChangeListener listener);
+
+ public class DuplicateRouteException extends Exception {}
+}
--- /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.sal.connector.remoterpc.router.zeromq;
+
+import org.opendaylight.controller.sal.core.api.AbstractProvider;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.osgi.framework.BundleContext;
+
+public class Activator extends AbstractProvider {
+
+ ZeroMqRpcRouter router;
+
+ @Override
+ public void onSessionInitiated(ProviderSession session) {
+ router = ZeroMqRpcRouter.getInstance();
+ router.setBrokerSession(session);
+ router.start();
+ }
+
+ @Override
+ protected void stopImpl(BundleContext context) {
+ router.stop();
+ }
+
+}
-package org.opendaylight.controller.sal.connector.zeromq;
+/*
+ * 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.sal.connector.remoterpc.router.zeromq;
import org.codehaus.jackson.map.ObjectMapper;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import java.io.*;
-import java.util.Arrays;
public class Message implements Serializable {
- public enum MessageType {
- ANNOUNCE((byte) 0),
+ public static enum MessageType {
+ ANNOUNCE((byte) 0), //TODO: Remove announce, add rpc registration and deregistration
HEARTBEAT((byte) 1),
REQUEST((byte) 2),
RESPONSE((byte) 3);
return o.readObject();
}
- public static byte[] toJsonBytes(Message m){
+ public static byte[] toJsonBytes(Message m) throws IOException {
ObjectMapper o = new ObjectMapper();
- try {
- System.out.println(o.writeValueAsString(m));
- return o.writeValueAsBytes(m);
- } catch (IOException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- return null;
+ return o.writeValueAsBytes(m);
}
- public static Message fromJsonBytes(byte [] bytes){
+ public static Message fromJsonBytes(byte [] bytes) throws IOException {
ObjectMapper o = new ObjectMapper();
- Message m = null;
- try {
- m = o.readValue(bytes, Message.class);
- } catch (IOException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- return m;
+ return o.readValue(bytes, Message.class);
}
public static class Response extends Message implements RpcRouter.RpcReply {
}
}
+ /**
+ * Builds a {@link Message} object
+ */
+ public static class MessageBuilder{
+
+ private Message message;
+
+ public MessageBuilder(){
+ message = new Message();
+ }
+
+
+ public MessageBuilder type(MessageType type){
+ message.setType(type);
+ return this;
+ }
+
+ public MessageBuilder sender(String sender){
+ message.setSender(sender);
+ return this;
+ }
+
+ public MessageBuilder route(RpcRouter.RouteIdentifier route){
+ message.setRoute(route);
+ return this;
+ }
+
+ public MessageBuilder payload(Object obj){
+ message.setPayload(obj);
+ return this;
+ }
+
+ public Message build(){
+ return message;
+ }
+ }
}
-package org.opendaylight.controller.sal.connector.zeromq;
+/*
+ * 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.sal.connector.remoterpc.router.zeromq;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
-package org.opendaylight.controller.sal.connector.zeromq;
+/*
+ * 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.sal.connector.remoterpc.router.zeromq;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
import java.io.Serializable;
-/**
- * Created with IntelliJ IDEA.
- * User: abhishk2
- * Date: 10/25/13
- * Time: 12:32 PM
- * To change this template use File | Settings | File Templates.
- */
public class RpcRequestImpl implements RpcRouter.RpcRequest<QName, QName, InstanceIdentifier, Object>,Serializable {
private RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> routeIdentifier;
--- /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.sal.connector.remoterpc.router.zeromq;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.controller.sal.connector.remoterpc.router.zeromq.Message.MessageType;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
+import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZMQ;
+
+/**
+ * ZeroMq based implementation of RpcRouter
+ * TODO:
+ * 1. Make it multi VM aware
+ * 2. Make rpc request handling async and non-blocking. Note zmq socket is not thread safe
+ * 3. sendRpc() should use connection pooling
+ * 4. Read properties from config file using existing(?) ODL properties framework
+ */
+public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
+
+ private ExecutorService serverPool;
+ private static ExecutorService handlersPool;
+
+ private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
+
+ private ProviderSession brokerSession;
+
+ private ZMQ.Context context;
+ private ZMQ.Socket publisher;
+ private ZMQ.Socket subscriber;
+ private ZMQ.Socket replySocket;
+
+ private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
+
+ private final RpcFacade facade = new RpcFacade();
+ private final RpcListener listener = new RpcListener();
+
+ private final String localIp = getLocalIpAddress();
+
+ private String pubPort = System.getProperty("pub.port");// port on which announcements are sent
+ private String subPort = System.getProperty("sub.port");// other controller's pub port
+ private String pubIp = System.getProperty("pub.ip"); // other controller's ip
+ private String rpcPort = System.getProperty("rpc.port");// port on which RPC messages are received
+
+ private Logger _logger = LoggerFactory.getLogger(ZeroMqRpcRouter.class);
+
+ //Prevent instantiation
+ private ZeroMqRpcRouter() {
+ }
+
+ public static ZeroMqRpcRouter getInstance() {
+ return _instance;
+ }
+
+ public void start() {
+ context = ZMQ.context(2);
+ publisher = context.socket(ZMQ.PUB);
+ int ret = publisher.bind("tcp://*:" + pubPort);
+ // serverPool = Executors.newSingleThreadExecutor();
+ serverPool = Executors.newCachedThreadPool();
+ handlersPool = Executors.newCachedThreadPool();
+ routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
+
+ // Start listening for announce and rpc messages
+ serverPool.execute(receive());
+
+ brokerSession.addRpcRegistrationListener(listener);
+
+ Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
+ for (QName rpc : currentlySupported) {
+ listener.onRpcImplementationAdded(rpc);
+ }
+
+ }
+
+ public void stop() {
+ if (handlersPool != null)
+ handlersPool.shutdown();
+ if (serverPool != null)
+ serverPool.shutdown();
+ if (publisher != null) {
+ publisher.setLinger(0);
+ publisher.close();
+ }
+ if (replySocket != null) {
+ replySocket.setLinger(0);
+ replySocket.close();
+ }
+ if (subscriber != null) {
+ subscriber.setLinger(0);
+ subscriber.close();
+ }
+ if (context != null)
+ context.term();
+
+ }
+
+ private Runnable receive() {
+ return new Runnable() {
+ public void run() {
+ try {
+ // Bind to RPC reply socket
+ replySocket = context.socket(ZMQ.REP);
+ replySocket.bind("tcp://*:" + rpcPort);
+
+ // Bind to publishing controller
+ subscriber = context.socket(ZMQ.SUB);
+ String pubAddress = "tcp://" + pubIp + ":" + subPort;
+ subscriber.connect(pubAddress);
+ _logger.debug("{} Subscribing at[{}]", Thread.currentThread().getName(), pubAddress);
+
+ //subscribe for announcements
+ //TODO: Message type would be changed. Update this
+ subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
+
+ // Poller enables listening on multiple sockets using a single thread
+ ZMQ.Poller poller = new ZMQ.Poller(2);
+ poller.register(replySocket, ZMQ.Poller.POLLIN);
+ poller.register(subscriber, ZMQ.Poller.POLLIN);
+
+ //TODO: Add code to restart the thread after exception
+ while (!Thread.currentThread().isInterrupted()) {
+
+ poller.poll();
+
+ if (poller.pollin(0)) {
+ handleRpcCall();
+ }
+ if (poller.pollin(1)) {
+ handleAnnouncement();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ replySocket.setLinger(0);
+ replySocket.close();
+ subscriber.setLinger(0);
+ subscriber.close();
+ }
+ };
+ }
+
+ /**
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ private void handleAnnouncement() throws IOException, ClassNotFoundException {
+
+ _logger.info("Announcement received");
+ Message.MessageType topic = (MessageType) Message.deserialize(subscriber.recv());
+
+ if (subscriber.hasReceiveMore()) {
+ try {
+ Message m = (Message) Message.deserialize(subscriber.recv());
+ _logger.debug("Announcement message [{}]", m);
+
+ // TODO: check on msg type or topic. Both
+ // should be same. Need to normalize.
+ if (Message.MessageType.ANNOUNCE == m.getType())
+ updateRoutingTable(m);
+ } catch (IOException | ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * @throws InterruptedException
+ * @throws ExecutionException
+ */
+ private void handleRpcCall() throws InterruptedException, ExecutionException {
+ try {
+ Message request = parseMessage(replySocket);
+
+ _logger.debug("Received rpc request [{}]", request);
+
+ // Call broker to process the message then reply
+ Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc(
+ (QName) request.getRoute().getType(), (CompositeNode) request.getPayload());
+
+ RpcResult<CompositeNode> result = rpc.get();
+
+ Message response = new Message.MessageBuilder()
+ .type(MessageType.RESPONSE)
+ .sender(localIp + ":" + rpcPort)
+ .route(request.getRoute())
+ //.payload(result) TODO: enable and test
+ .build();
+
+ replySocket.send(Message.serialize(response));
+
+ _logger.debug("Sent rpc response [{}]", response);
+
+ } catch (IOException ex) {
+ //TODO: handle exception and send error codes to caller
+ ex.printStackTrace();
+ }
+ }
+
+
+ @Override
+ public Future<RpcReply<Object>> sendRpc(
+ final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
+
+ return handlersPool.submit(new Callable<RpcReply<Object>>() {
+
+ @Override
+ public RpcReply<Object> call() {
+ ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
+
+ // TODO pick the ip and port from routing table based on routing identifier
+ requestSocket.connect("tcp://" + pubIp + ":5554");
+
+ Message requestMessage = new Message.MessageBuilder()
+ .type(MessageType.REQUEST)
+ .sender(localIp + ":" + rpcPort)
+ .route(input.getRoutingInformation())
+ .payload(input.getPayload())
+ .build();
+
+ _logger.debug("Sending rpc request [{}]", requestMessage);
+
+ RpcReply<Object> reply = null;
+
+ try {
+
+ requestSocket.send(Message.serialize(requestMessage));
+ final Message response = parseMessage(requestSocket);
+
+ _logger.debug("Received response [{}]", response);
+
+ reply = new RpcReply<Object>() {
+
+ @Override
+ public Object getPayload() {
+ return response.getPayload();
+ }
+ };
+ } catch (IOException ex) {
+ // TODO: Pass exception back to the caller
+ ex.printStackTrace();
+ }
+
+ return reply;
+ }
+ });
+ }
+
+ /**
+ * TODO: Remove this implementation and use RoutingTable implementation to send announcements
+ * Publishes a notice to other controllers in the cluster
+ *
+ * @param notice
+ */
+ public void publish(final Message notice) {
+ Runnable task = new Runnable() {
+ public void run() {
+
+ try {
+
+ publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
+ publisher.send(Message.serialize(notice));
+ _logger.debug("Announcement sent [{}]", notice);
+ } catch (IOException ex) {
+ _logger.error("Error in sending announcement [{}]", notice);
+ ex.printStackTrace();
+ }
+ }
+ };
+ handlersPool.execute(task);
+ }
+
+ /**
+ * Finds IPv4 address of the local VM
+ * TODO: This method is non-deterministic. There may be more than one IPv4 address. Cant say which
+ * address will be returned. Read IP from a property file or enhance the code to make it deterministic.
+ * Should we use IP or hostname?
+ *
+ * @return
+ */
+ private String getLocalIpAddress() {
+ String hostAddress = null;
+ Enumeration e = null;
+ try {
+ e = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e1) {
+ e1.printStackTrace();
+ }
+ while (e.hasMoreElements()) {
+
+ NetworkInterface n = (NetworkInterface) e.nextElement();
+
+ Enumeration ee = n.getInetAddresses();
+ while (ee.hasMoreElements()) {
+ InetAddress i = (InetAddress) ee.nextElement();
+ if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
+ hostAddress = i.getHostAddress();
+ }
+ }
+ return hostAddress;
+
+ }
+
+ /**
+ * TODO: Change to use external routing table implementation
+ *
+ * @param msg
+ */
+ private void updateRoutingTable(Message msg) {
+ routingTable.put(msg.getRoute(), msg.getSender());
+ RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
+
+ // Currently only registers rpc implementation.
+ // TODO: do registration for instance based routing
+ QName rpcType = route.getType();
+ RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
+ _logger.debug("Routing table updated");
+ }
+
+ /**
+ * @param socket
+ * @return
+ */
+ private Message parseMessage(ZMQ.Socket socket) {
+
+ Message msg = null;
+ try {
+ byte[] bytes = socket.recv();
+ _logger.debug("Received bytes:[{}]", bytes.length);
+ msg = (Message) Message.deserialize(bytes);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return msg;
+ }
+
+ private class RpcFacade implements RpcImplementation {
+
+ @Override
+ public Set<QName> getSupportedRpcs() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+ routeId.setType(rpc);
+
+ RpcRequestImpl request = new RpcRequestImpl();
+ request.setRouteIdentifier(routeId);
+ request.setPayload(input);
+
+ final Future<RpcReply<Object>> ret = sendRpc(request);
+
+ //TODO: Review result handling
+ RpcResult<CompositeNode> result = new RpcResult<CompositeNode>() {
+ @Override
+ public boolean isSuccessful() {
+ try {
+ ret.get();
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public CompositeNode getResult() {
+ return null;
+ }
+
+ @Override
+ public Collection<RpcError> getErrors() {
+ return Collections.EMPTY_LIST;
+ }
+ };
+ return result;
+ }
+ }
+
+ /**
+ * Listener for rpc registrations
+ */
+ private class RpcListener implements RpcRegistrationListener {
+
+ @Override
+ public void onRpcImplementationAdded(QName name) {
+
+ _logger.debug("Announcing registration for [{}]", name);
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl();
+ routeId.setType(name);
+
+ //TODO: Make notice immutable and change message type
+ Message notice = new Message.MessageBuilder()
+ .type(MessageType.ANNOUNCE)
+ .sender("tcp://" + localIp + ":" + rpcPort)
+ .route(routeId)
+ .build();
+
+ publish(notice);
+ }
+
+ @Override
+ public void onRpcImplementationRemoved(QName name) {
+ // TODO: send a rpc-deregistrtation notice
+
+ }
+ }
+
+ public void setBrokerSession(ProviderSession session) {
+ this.brokerSession = session;
+
+ }
+
+}
+++ /dev/null
-package org.opendaylight.controller.sal.connector.zeromq;
-
-import org.opendaylight.controller.sal.core.api.AbstractProvider;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.osgi.framework.BundleContext;
-
-public class Activator extends AbstractProvider {
-
- ZeroMqRpcRouter router;
-
- @Override
- public void onSessionInitiated(ProviderSession session) {
- router = ZeroMqRpcRouter.getInstance();
- router.setBrokerSession(session);
- router.start();
- }
-
- @Override
- protected void stopImpl(BundleContext context) {
- router.stop();
- }
-
-}
+++ /dev/null
-package org.opendaylight.controller.sal.connector.zeromq;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-
-import java.io.Serializable;
-
-/**
- * Created with IntelliJ IDEA.
- * User: abhishk2
- * Date: 10/24/13
- * Time: 4:25 PM
- * To change this template use File | Settings | File Templates.
- */
-public class RpcReplyImpl implements RpcRouter.RpcReply<Object>,Serializable {
-
- private Object payload;
-
- @Override
- public Object getPayload() {
- return payload; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public void setPayload(Object payload){
- this.payload = payload;
- }
-}
+++ /dev/null
-package org.opendaylight.controller.sal.connector.zeromq;
-
-import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
-import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
-import org.opendaylight.controller.sal.core.api.RpcImplementation;
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.zeromq.ZMQ;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.*;
-import java.util.concurrent.*;
-
-public class ZeroMqRpcRouter implements RpcRouter<QName, QName, InstanceIdentifier, Object> {
-
- private ExecutorService serverPool;
- private static ExecutorService handlersPool;
-
- private Map<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String> routingTable;
-
- private ProviderSession brokerSession;
-
- private ZMQ.Context context;
- private ZMQ.Socket publisher;
- private ZMQ.Socket subscriber;
- private ZMQ.Socket replySocket;
-
- private static ZeroMqRpcRouter _instance = new ZeroMqRpcRouter();
-
- private final RpcFacade facade = new RpcFacade();
- private final RpcListener listener = new RpcListener();
-
- private String pubPort = System.getProperty("pub.port");//port on which announcements are sent
- private String subPort = System.getProperty("sub.port");//other controller's pub port
- private String pubIp = System.getProperty("pub.ip"); //other controller's ip
- private String rpcPort = System.getProperty("rpc.port");//port on which RPC messages are received
-
-
- private ZeroMqRpcRouter() {
- }
-
- public static ZeroMqRpcRouter getInstance() {
- return _instance;
- }
-
- public void start() {
- context = ZMQ.context(2);
- serverPool = Executors.newSingleThreadExecutor();
- handlersPool = Executors.newCachedThreadPool();
- routingTable = new ConcurrentHashMap<RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier>, String>();
-
- // Start listening for announce and rpc messages
- serverPool.execute(receive());
-
-
- brokerSession.addRpcRegistrationListener(listener);
- Set<QName> currentlySupported = brokerSession.getSupportedRpcs();
- for(QName rpc : currentlySupported) {
- listener.onRpcImplementationAdded(rpc);
- }
-
-
- }
-
- public void stop() {
- if (handlersPool != null) handlersPool.shutdown();
- if (serverPool != null) serverPool.shutdown();
- if (publisher != null) {
- publisher.setLinger(0);
- publisher.close();
- }
- if (replySocket != null) {
- replySocket.setLinger(0);
- replySocket.close();
- }
- if (subscriber != null) {
- subscriber.setLinger(0);
- subscriber.close();
- }
- if (context != null) context.term();
-
-
- }
-
- private Runnable receive() {
- return new Runnable() {
- public void run() {
- try {
- // Bind to RPC reply socket
- replySocket = context.socket(ZMQ.REP);
- replySocket.bind("tcp://*:" + rpcPort);
-
- // Bind to publishing controller
- subscriber = context.socket(ZMQ.SUB);
- subscriber.connect("tcp://" + pubIp + ":" + subPort);
- System.out.println("Subscribing at[" + "tcp://" + pubIp + ":" + subPort + "]");
-
- subscriber.subscribe(Message.serialize(Message.MessageType.ANNOUNCE));
-
- // Initialize poll set
- ZMQ.Poller poller = new ZMQ.Poller(2);
- poller.register(replySocket, ZMQ.Poller.POLLIN);
- poller.register(subscriber, ZMQ.Poller.POLLIN);
-
- while (!Thread.currentThread().isInterrupted()) {
-
- poller.poll(250);
- //TODO: Fix this
- if (poller.pollin(0)) {
- //receive rpc request and reply
- try {
- Message req = parseMessage(replySocket);
- Message resp = new Message();
- //Call broker to process the message then reply
- Future<RpcResult<CompositeNode>> rpc = brokerSession.rpc((QName) req.getRoute().getType(), (CompositeNode) req.getPayload());
- RpcResult<CompositeNode> result = rpc.get();
- resp.setType(Message.MessageType.RESPONSE);
- resp.setSender(getLocalIpAddress() + ":" + rpcPort);
- resp.setRoute(req.getRoute());
- resp.setPayload(result.isSuccessful());
- replySocket.send(Message.serialize(resp));
-
- } catch (IOException ex) {// | ClassNotFoundException ex) {
- System.out.println("Rpc request could not be handled" + ex);
- }
- }
- if (poller.pollin(1)) {
- //get subscription and update routing table
- //try {
- Message.MessageType topic = (Message.MessageType)Message.deserialize(subscriber.recv());
- System.out.println("Topic:[" + topic + "]");
-
- if (subscriber.hasReceiveMore()) {
- try {
- Message m = (Message) Message.deserialize(subscriber.recv());
- System.out.println(m);
- //TODO: check on msg type or topic. Both should be same. Need to normalize.
- if (Message.MessageType.ANNOUNCE == m.getType()) updateRoutingTable(m);
- } catch (IOException | ClassNotFoundException e) {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- }
-//
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- replySocket.setLinger(0);
- replySocket.close();
- subscriber.setLinger(0);
- subscriber.close();
- }
- };
- }
-
- private void updateRoutingTable(Message msg) {
- routingTable.put(msg.getRoute(), msg.getSender());
- RpcRouter.RouteIdentifier<QName, QName, InstanceIdentifier> route = msg.getRoute();
- QName rpcType = route.getType();
- System.out.println("Routing Table\n" + routingTable);
-
- RpcRegistration registration = brokerSession.addRpcImplementation(rpcType, facade);
- }
-
- private Message parseMessage(ZMQ.Socket socket) {
- //Message m = new Message();
- //socket.setReceiveBufferSize(40000);
- Message msg = null;
- try {
- byte[] bytes = socket.recv();
- System.out.println("Received bytes:[" + bytes.length + "]");
- msg = (Message) Message.deserialize(bytes);
- } catch (Throwable t) {
- System.out.println("Caught exception");
- t.printStackTrace();
- }
- return msg;
- /*m.setType((Message.MessageType) Message.deserialize(socket.recv()));
-
- if (socket.hasReceiveMore()) {
- m.setSender((String) Message.deserialize(socket.recv()));
- }
- if (socket.hasReceiveMore()) {
- m.setRoute((RouteIdentifier) Message.deserialize(socket.recv()));
- }
- if (socket.hasReceiveMore()) {
- m.setPayload(Message.deserialize(socket.recv()));
- }
- return m;*/
- }
-
- @Override
- public Future<RpcReply<Object>> sendRpc(final RpcRequest<QName, QName, InstanceIdentifier, Object> input) {
-
- return handlersPool.submit(new Callable<RpcReply<Object>>() {
-
- @Override
- public RpcReply<Object> call() {
- ZMQ.Socket requestSocket = context.socket(ZMQ.REQ);
- Message req = new Message();
- Message resp = null;
- RpcReplyImpl reply = new RpcReplyImpl();
- requestSocket.connect((String) routingTable.get(input.getRoutingInformation().getRoute()));
-
- req.setType(Message.MessageType.REQUEST);
- req.setSender(getLocalIpAddress() + ":" + rpcPort);
- req.setRoute(input.getRoutingInformation());
- req.setPayload(input.getPayload());
- try {
- requestSocket.send(Message.serialize(req));
- resp = parseMessage(requestSocket);
- reply.setPayload(resp.getPayload());
- } catch (IOException ex) {//| ClassNotFoundException ex) {
- //Log and ignore
- System.out.println("Error in RPC send. Input could not be serialized[" + input + "]");
- }
-
- return reply;
- }
- });
- }
-
- public void publish(final Message message) {
- Runnable task = new Runnable() {
- public void run() {
- // Bind to publishing port
- publisher = context.socket(ZMQ.PUB);
- publisher.bind("tcp://*:" + pubPort);
- System.out.println("Publisher started at port[" + pubPort + "]");
- try {
- Message outMessage = new Message();
- outMessage.setType(Message.MessageType.ANNOUNCE);
- outMessage.setSender("tcp://" + getLocalIpAddress() + ":" + rpcPort);
- outMessage.setRoute(message.getRoute());
-
- System.out.println("Sending announcement[" + outMessage + "]");
- publisher.sendMore(Message.serialize(Message.MessageType.ANNOUNCE));
- publisher.send(Message.serialize(outMessage));
-
- } catch (IOException ex) {
- //Log and ignore
- System.out.println("Error in publishing");
- ex.printStackTrace();
- }
- System.out.println("Published message[" + message + "]");
- publisher.close();
- }
- };
- handlersPool.execute(task);
- }
-
- private String getLocalIpAddress() {
- String hostAddress = null;
- Enumeration e = null;
- try {
- e = NetworkInterface.getNetworkInterfaces();
- } catch (SocketException e1) {
- e1.printStackTrace();
- }
- while (e.hasMoreElements()) {
-
- NetworkInterface n = (NetworkInterface) e.nextElement();
- Enumeration ee = n.getInetAddresses();
- while (ee.hasMoreElements()) {
- InetAddress i = (InetAddress) ee.nextElement();
- if ((i instanceof Inet4Address) && (i.isSiteLocalAddress()))
- hostAddress = i.getHostAddress();
- }
- }
-
- return hostAddress;
-
-
- }
-
-
- private class RpcFacade implements RpcImplementation {
-
-
- @Override
- public Set<QName> getSupportedRpcs() {
- return Collections.emptySet();
- }
-
- @Override
- public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-
- RpcRequestImpl request = new RpcRequestImpl();
- RouteIdentifierImpl routeId = new RouteIdentifierImpl();
- routeId.setContext(null);
- routeId.setRoute(null);
- routeId.setType(rpc);
-
- request.setRouteIdentifier(routeId);
- request.setPayload(input);
- // Create message
-
- Future<org.opendaylight.controller.sal.connector.api.RpcRouter.RpcReply<Object>> ret = sendRpc(request);
-
- return null;
- }
- }
-
- private class RpcListener implements RpcRegistrationListener {
-
- @Override
- public void onRpcImplementationAdded(QName name) {
-
- Message msg = new Message();
- RouteIdentifierImpl routeId = new RouteIdentifierImpl();
- routeId.setType(name);
- msg.setRoute(routeId);
- publish(msg);
- }
-
- @Override
- public void onRpcImplementationRemoved(QName name) {
- // TODO Auto-generated method stub
-
- }
- }
-
- public void setBrokerSession(ProviderSession session) {
- this.brokerSession = session;
-
- }
-
-}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-manager</artifactId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>equinoxSDK381</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.9</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+ <version>4.0</version>
+ </dependency>
</dependencies>
</project>
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import org.ops4j.pax.exam.util.PathUtils;
@RunWith(PaxExam.class)
public class ToasterTest {
public static final String ODL = "org.opendaylight.controller";
public static final String YANG = "org.opendaylight.yangtools";
+ public static final String CONTROLLER = "org.opendaylight.controller";
+ public static final String YANGTOOLS = "org.opendaylight.yangtools";
+
+
public static final String SAMPLE = "org.opendaylight.controller.samples";
@Test
@Configuration
public Option[] config() {
return options(systemProperty("osgi.console").value("2401"),
+ systemProperty("logback.configurationFile").value(
+ "file:" + PathUtils.getBaseDir()
+ + "/src/test/resources/logback.xml"),
mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
- mavenBundle(ODL, "sal-binding-api").versionAsInProject(), //
- mavenBundle(ODL, "sal-binding-config").versionAsInProject(),
- mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject(), //
mavenBundle(ODL, "sal-common").versionAsInProject(), //
mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
mavenBundle(ODL, "config-api").versionAsInProject(), //
mavenBundle(ODL, "config-manager").versionAsInProject(), //
mavenBundle("commons-io", "commons-io").versionAsInProject(),
+ mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+ mavenBundle(CONTROLLER, "sal-binding-api").versionAsInProject(), //
+ mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(),
+ mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), //
+ mavenBundle("org.javassist", "javassist").versionAsInProject(), //
+ mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), //
+
+ mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+
+
+ mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), //
+ mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(),
+ mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(),
+
+
+ mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), //
+ mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), //
+ mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), //
+
+ mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
mavenBundle(SAMPLE, "sample-toaster").versionAsInProject(), //
mavenBundle(SAMPLE, "sample-toaster-consumer").versionAsInProject(), //
<configuration scan="true">
+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
--- /dev/null
+<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>
+ <artifactId>sal-test-parent</artifactId>
+ <groupId>org.opendaylight.controller.tests</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-rest-connector-it</artifactId>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+ <properties>
+ <exam.version>3.0.0</exam.version>
+ <url.version>1.5.0</url.version>
+ <geminiweb.version>2.2.0.RELEASE</geminiweb.version>
+ <virgo.version>3.6.0.RELEASE</virgo.version>
+ <spring.version>3.1.3.RELEASE</spring.version>
+ <jersey.version>1.17</jersey.version>
+ <spring-security.version>3.1.3.RELEASE</spring-security.version>
+ <netconf.version>0.2.2-SNAPSHOT</netconf.version>
+ <config.version>0.2.2-SNAPSHOT</config.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>maven-paxexam-plugin</artifactId>
+ <version>1.2.4</version>
+ <executions>
+ <execution>
+ <id>generate-config</id>
+ <goals>
+ <goal>generate-depends-file</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse
+ m2e settings only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.ops4j.pax.exam
+ </groupId>
+ <artifactId>
+ maven-paxexam-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.4,)
+ </versionRange>
+ <goals>
+ <goal>
+ generate-depends-file
+ </goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>logging.bridge</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>xtend-lib-osgi</artifactId>
+ <version>2.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner.implementation</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-rest-connector</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-it</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>exificient</artifactId>
+ <version>0.9.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-container-native</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-junit4</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
+ <version>4.0.10.Final</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-link-mvn</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.8.1.v20120830-144521</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-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>sal-core-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <version>0.2.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+ <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+ <version>4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.8</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>javax.servlet</artifactId>
+ <version>3.0.0.v201112011016</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>javax.servlet.jsp</artifactId>
+ <version>2.2.0.v201112011158</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.ds</artifactId>
+ <version>1.4.0.v20120522-1841</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.util</artifactId>
+ <version>1.0.400.v20120522-2049</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi.services</artifactId>
+ <version>3.3.100.v20120522-1822</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.osgi</artifactId>
+ <version>3.8.1.v20120830-144521</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.command</artifactId>
+ <version>0.8.0.v201108120515</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ <version>0.8.0.v201108120515</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.shell</artifactId>
+ <version>0.8.0.v201110170705</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.cm</artifactId>
+ <version>1.0.400.v20120522-1841</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.console</artifactId>
+ <version>1.0.0.v20120522-1841</version>
+ </dependency>
+ <dependency>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.eclipse.equinox.launcher</artifactId>
+ <version>1.3.0.v20120522-1813</version>
+ </dependency>
+ <!-- Gemini Web -->
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.gemini.web.core</artifactId>
+ <version>${geminiweb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.gemini.web.extender</artifactId>
+ <version>${geminiweb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.gemini.web.tomcat</artifactId>
+ <version>${geminiweb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.kernel.equinox.extensions</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.common</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.io</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.math</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.osgi</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.osgi.manifest</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>geminiweb</groupId>
+ <artifactId>org.eclipse.virgo.util.parser.manifest</artifactId>
+ <version>${virgo.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.dependencymanager</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.spec.javax.transaction</groupId>
+ <artifactId>jboss-transaction-api_1.1_spec</artifactId>
+ <version>1.0.1.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.fileinstall</artifactId>
+ <version>3.1.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>virgomirror</groupId>
+ <artifactId>org.eclipse.jdt.core.compiler.batch</artifactId>
+ <version>3.8.0.I20120518-2145</version>
+ </dependency>
+ <dependency>
+ <groupId>eclipselink</groupId>
+ <artifactId>javax.persistence</artifactId>
+ <version>2.0.4.v201112161009</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.activation</artifactId>
+ <version>1.1.0.v201211130549</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.annotation</artifactId>
+ <version>1.1.0.v201209060031</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.ejb</artifactId>
+ <version>3.1.1.v201204261316</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.el</artifactId>
+ <version>2.2.0.v201108011116</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.mail.glassfish</artifactId>
+ <version>1.4.1.v201108011116</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.xml.rpc</artifactId>
+ <version>1.1.0.v201005080400</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina</artifactId>
+ <version>7.0.32.v201211201336</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina.ha</artifactId>
+ <version>7.0.32.v201211201952</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.catalina.tribes</artifactId>
+ <version>7.0.32.v201211201952</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.coyote</artifactId>
+ <version>7.0.32.v201211201952</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.el</artifactId>
+ <version>7.0.32.v201211081135</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.jasper</artifactId>
+ <version>7.0.32.v201211201952</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.juli.extras</artifactId>
+ <version>7.0.32.v201211081135</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.tomcat.api</artifactId>
+ <version>7.0.32.v201211081135</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>org.apache.tomcat.util</artifactId>
+ <version>7.0.32.v201211201952</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.servlet.jsp.jstl</artifactId>
+ <version>1.2.0.v201105211821</version>
+ </dependency>
+ <dependency>
+ <groupId>orbit</groupId>
+ <artifactId>javax.servlet.jsp.jstl.impl</artifactId>
+ <version>1.2.0.v201210211230</version>
+ </dependency>
+ <!-- Add Pax Exam -->
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-container-native</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-junit4</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.exam</groupId>
+ <artifactId>pax-exam-link-mvn</artifactId>
+ <version>${exam.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-aether</artifactId>
+ <version>${url.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>4.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.asm</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.aop</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.context</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.context.support</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.core</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.beans</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.expression</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.web</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.aopalliance</groupId>
+ <artifactId>com.springsource.org.aopalliance</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.web.servlet</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <!-- Spring security -->
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-config</artifactId>
+ <version>${spring-security.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <version>${spring-security.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ <version>${spring-security.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-taglibs</artifactId>
+ <version>${spring-security.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>org.springframework.transaction</artifactId>
+ <version>${spring-security.version}</version>
+ </dependency>
+ <!-- Visual VM hook -->
+ <dependency>
+ <groupId>org.ow2.chameleon.management</groupId>
+ <artifactId>chameleon-mbeans</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <!-- Jersey for JAXRS -->
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <!-- <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId>
+ <version>${jersey.version}</version> </dependency> -->
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-server</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-json</artifactId>
+ <version>${jersey.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>eclipselink</groupId>
+ <artifactId>javax.resource</artifactId>
+ <version>1.5.0.v200906010428</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>com.sun.jersey.jersey-servlet</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>org.apache.catalina.filters.CorsFilter</artifactId>
+ <version>7.0.42</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-util</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-store-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-store-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>logback-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-file-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-api</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-impl</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-util</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-client</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-mapping-api</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-netconf-connector</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-impl</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+package org.opendaylight.controller.test.restconf.it;
+
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.*;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackages;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.exam.CoreOptions.maven;
+
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
+import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceManager;
+import org.opendaylight.controller.sal.connect.netconf.NetconfInventoryUtils;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
+import org.opendaylight.controller.test.sal.binding.it.TestHelper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.util.PathUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import static org.opendaylight.controller.test.sal.binding.it.TestHelper.*;
+
+@RunWith(PaxExam.class)
+public class ServiceProviderController {
+
+ public static final String ODL = "org.opendaylight.controller";
+ public static final String YANG = "org.opendaylight.yangtools";
+ public static final String SAMPLE = "org.opendaylight.controller.samples";
+
+ private static QName CONFIG_MODULES = new QName(
+ URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+ private static QName CONFIG_SERVICES = new QName(
+ URI.create("urn:opendaylight:params:xml:ns:yang:controller:config"), null, "modules");
+ @Inject
+ BundleContext context;
+
+ @Inject
+ MountProvisionService mountService;
+
+ @Inject
+ DataBrokerService dataBroker;
+
+ @Inject
+ NetconfDeviceManager netconfManager;
+
+ @Test
+ public void properInitialized() throws Exception {
+
+ Map<QName, String> arg = Collections.singletonMap(InventoryUtils.INVENTORY_ID, "foo");
+
+ InstanceIdentifier path = InstanceIdentifier.builder(InventoryUtils.INVENTORY_PATH)
+ .nodeWithKey(InventoryUtils.INVENTORY_NODE, InventoryUtils.INVENTORY_ID, "foo").toInstance();
+
+ netconfManager.netconfNodeAdded(path, new InetSocketAddress("127.0.0.1", 8383));
+
+
+ InstanceIdentifier mountPointPath = path;
+
+ /** We retrive a mountpoint **/
+ MountProvisionInstance mountPoint = mountService.getMountPoint(mountPointPath);
+ CompositeNode data = mountPoint.readOperationalData(InstanceIdentifier.builder().node(CONFIG_MODULES)
+ .toInstance());
+ assertNotNull(data);
+ assertEquals(CONFIG_MODULES, data.getNodeType());
+
+ CompositeNode data2 = mountPoint.readOperationalData(InstanceIdentifier.builder().toInstance());
+ assertNotNull(data2);
+
+ InstanceIdentifier fullPath = InstanceIdentifier.builder(mountPointPath).node(CONFIG_MODULES).toInstance();
+
+ CompositeNode data3 = dataBroker.readOperationalData(fullPath);
+ assertNotNull(data3);
+ assertEquals(CONFIG_MODULES, data.getNodeType());
+
+ //Thread.sleep(30 * 60 * 1000); // Waiting for services to get wired.
+ //assertTrue(true);
+ // assertTrue(consumer.createToast(WhiteBread.class, 5));
+ }
+
+ @Configuration
+ public Option[] config() {
+ return options(
+ mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
+ mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
+ mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
+ mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
+
+ mdSalCoreBundles(),
+ baseModelBundles(),
+ flowCapableModelBundles(),
+ configMinumumBundles(),
+
+ // mavenBundle(ODL,
+ // "sal-binding-broker-impl").versionAsInProject().update(), //
+ mavenBundle(ODL, "sal-common").versionAsInProject(), //
+ mavenBundle(ODL, "sal-common-api").versionAsInProject(),//
+ mavenBundle(ODL, "sal-common-impl").versionAsInProject(), //
+ mavenBundle(ODL, "sal-common-util").versionAsInProject(), //
+
+ mavenBundle(ODL, "sal-core-api").versionAsInProject().update(), //
+ mavenBundle(ODL, "sal-broker-impl").versionAsInProject(), //
+ mavenBundle(ODL, "sal-core-spi").versionAsInProject().update(), //
+
+ mavenBundle(ODL, "sal-connector-api").versionAsInProject(), //
+ // mavenBundle(SAMPLE,
+ // "zeromq-test-provider").versionAsInProject(), //
+ mavenBundle(ODL, "sal-rest-connector").versionAsInProject(), //
+ mavenBundle(ODL, "sal-netconf-connector").versionAsInProject(), //
+
+ mavenBundle(YANG, "concepts").versionAsInProject(),
+ mavenBundle(YANG, "yang-binding").versionAsInProject(), //
+ mavenBundle(YANG, "yang-common").versionAsInProject(), //
+ mavenBundle(YANG, "yang-data-api").versionAsInProject(), //
+ mavenBundle(YANG, "yang-data-impl").versionAsInProject(), //
+ mavenBundle(YANG, "yang-model-api").versionAsInProject(), //
+ mavenBundle(YANG, "yang-model-util").versionAsInProject(), //
+ mavenBundle(YANG, "yang-parser-api").versionAsInProject(),
+ mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+
+ mavenBundle(YANG + ".thirdparty", "xtend-lib-osgi").versionAsInProject(), //
+ mavenBundle(YANG + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), //
+ mavenBundle("com.google.guava", "guava").versionAsInProject(), //
+
+ // systemProperty("logback.configurationFile").value(
+ // "file:" + PathUtils.getBaseDir() +
+ // "/src/test/resources/logback.xml"),
+ // To start OSGi console for inspection remotely
+ systemProperty("osgi.console").value("2401"),
+ systemProperty("org.eclipse.gemini.web.tomcat.config.path").value(
+ PathUtils.getBaseDir() + "/src/test/resources/tomcat-server.xml"),
+
+ // setting default level. Jersey bundles will need to be started
+ // earlier.
+ systemProperty("osgi.bundles.defaultStartLevel").value("4"),
+
+ systemProperty("netconf.tcp.address").value("127.0.0.1"),
+ systemProperty("netconf.tcp.port").value("8383"),
+
+ // Set the systemPackages (used by clustering)
+ systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+
+ mavenBundle("org.apache.servicemix.bundles", "org.apache.servicemix.bundles.xerces", "2.11.0_1"),
+ mavenBundle("org.eclipse.birt.runtime.3_7_1", "org.apache.xml.resolver", "1.2.0"),
+
+ mavenBundle("org.slf4j", "jcl-over-slf4j").versionAsInProject(),
+ mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(),
+ mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(),
+ mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(),
+ mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(),
+ mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "clustering.services").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "containermanager").versionAsInProject(),
+ // List all the opendaylight modules
+ mavenBundle("org.opendaylight.controller", "configuration").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "sal").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "switchmanager").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "usermanager").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "logging.bridge").versionAsInProject(),
+ // mavenBundle("org.opendaylight.controller",
+ // "clustering.test").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "bundlescanner").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "bundlescanner.implementation").versionAsInProject(),
+
+ // Northbound bundles
+ mavenBundle("org.opendaylight.controller", "commons.northbound").versionAsInProject(),
+ mavenBundle("org.codehaus.jackson", "jackson-mapper-asl").versionAsInProject(),
+ mavenBundle("org.codehaus.jackson", "jackson-core-asl").versionAsInProject(),
+ mavenBundle("org.codehaus.jackson", "jackson-jaxrs").versionAsInProject(),
+ mavenBundle("org.codehaus.jackson", "jackson-xc").versionAsInProject(),
+ mavenBundle("org.codehaus.jettison", "jettison").versionAsInProject(),
+
+ mavenBundle("commons-io", "commons-io").versionAsInProject(),
+
+ // mavenBundle("commons-fileupload",
+ // "commons-fileupload").versionAsInProject(),
+
+ mavenBundle("io.netty", "netty-handler").versionAsInProject(),
+ mavenBundle("io.netty", "netty-codec").versionAsInProject(),
+ mavenBundle("io.netty", "netty-buffer").versionAsInProject(),
+ mavenBundle("io.netty", "netty-transport").versionAsInProject(),
+ mavenBundle("io.netty", "netty-common").versionAsInProject(),
+
+ mavenBundle(ODL, "config-api").versionAsInProject(),
+ mavenBundle(ODL, "config-manager").versionAsInProject(),
+ mavenBundle(ODL, "config-util").versionAsInProject(),
+ mavenBundle(ODL, "yang-jmx-generator").versionAsInProject(),
+ mavenBundle(ODL, "yang-store-api").versionAsInProject(),
+ mavenBundle(ODL, "yang-store-impl").versionAsInProject(),
+ mavenBundle(ODL, "logback-config").versionAsInProject(),
+ mavenBundle(ODL, "config-persister-api").versionAsInProject(),
+ // mavenBundle(ODL,"config-persister-file-adapter").versionAsInProject(),
+ mavenBundle(ODL, "netconf-api").versionAsInProject(),
+ mavenBundle(ODL, "netconf-impl").versionAsInProject(),
+ mavenBundle(ODL, "netconf-client").versionAsInProject(),
+ mavenBundle(ODL, "netconf-util").versionAsInProject(),
+ mavenBundle(ODL + ".thirdparty", "ganymed", "1.0-SNAPSHOT"),
+ mavenBundle(ODL, "netconf-mapping-api").versionAsInProject(),
+ mavenBundle(ODL, "config-netconf-connector").versionAsInProject(),
+ mavenBundle(ODL, "config-persister-impl").versionAsInProject(),
+
+ mavenBundle("org.opendaylight.bgpcep", "framework").versionAsInProject(),
+ mavenBundle("org.opendaylight.bgpcep", "util").versionAsInProject(),
+ mavenBundle(YANG, "binding-generator-spi").versionAsInProject(), //
+ mavenBundle(YANG, "binding-model-api").versionAsInProject(), //
+ mavenBundle(YANG, "binding-generator-util").versionAsInProject(),
+ mavenBundle(YANG, "yang-parser-impl").versionAsInProject(),
+ mavenBundle(YANG, "binding-type-provider").versionAsInProject(),
+
+ mavenBundle("org.opendaylight.controller.thirdparty", "exificient", "0.9.2"),
+
+ mavenBundle("equinoxSDK381", "javax.servlet").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "javax.servlet.jsp").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.ds").versionAsInProject(),
+ mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.osgi.services").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.apache.felix.gogo.command").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.apache.felix.gogo.runtime").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.apache.felix.gogo.shell").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.cm").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
+ mavenBundle("equinoxSDK381", "org.eclipse.equinox.launcher").versionAsInProject(),
+
+ mavenBundle("geminiweb", "org.eclipse.gemini.web.core").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.gemini.web.extender").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.gemini.web.tomcat").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.kernel.equinox.extensions").versionAsInProject().noStart(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.util.common").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.util.io").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.util.math").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.util.osgi.manifest").versionAsInProject(),
+ mavenBundle("geminiweb", "org.eclipse.virgo.util.parser.manifest").versionAsInProject(),
+
+ mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.dependencymanager.shell").versionAsInProject(),
+
+ mavenBundle("com.google.code.gson", "gson").versionAsInProject(),
+ mavenBundle("org.jboss.spec.javax.transaction", "jboss-transaction-api_1.1_spec").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.fileinstall").versionAsInProject(),
+ mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(),
+ mavenBundle("commons-codec", "commons-codec").versionAsInProject(),
+ mavenBundle("virgomirror", "org.eclipse.jdt.core.compiler.batch").versionAsInProject(),
+ mavenBundle("eclipselink", "javax.persistence").versionAsInProject(),
+ mavenBundle("eclipselink", "javax.resource").versionAsInProject(),
+
+ mavenBundle("orbit", "javax.activation").versionAsInProject(),
+ mavenBundle("orbit", "javax.annotation").versionAsInProject(),
+ mavenBundle("orbit", "javax.ejb").versionAsInProject(),
+ mavenBundle("orbit", "javax.el").versionAsInProject(),
+ mavenBundle("orbit", "javax.mail.glassfish").versionAsInProject(),
+ mavenBundle("orbit", "javax.xml.rpc").versionAsInProject(),
+ mavenBundle("orbit", "org.apache.catalina").versionAsInProject(),
+ // these are bundle fragments that can't be started on its own
+ mavenBundle("orbit", "org.apache.catalina.ha").versionAsInProject().noStart(),
+ mavenBundle("orbit", "org.apache.catalina.tribes").versionAsInProject().noStart(),
+ mavenBundle("orbit", "org.apache.coyote").versionAsInProject().noStart(),
+ mavenBundle("orbit", "org.apache.jasper").versionAsInProject().noStart(),
+
+ mavenBundle("orbit", "org.apache.el").versionAsInProject(),
+ mavenBundle("orbit", "org.apache.juli.extras").versionAsInProject(),
+ mavenBundle("orbit", "org.apache.tomcat.api").versionAsInProject(),
+ mavenBundle("orbit", "org.apache.tomcat.util").versionAsInProject().noStart(),
+ mavenBundle("orbit", "javax.servlet.jsp.jstl").versionAsInProject(),
+ mavenBundle("orbit", "javax.servlet.jsp.jstl.impl").versionAsInProject(),
+
+ mavenBundle("org.ops4j.pax.exam", "pax-exam-container-native").versionAsInProject(),
+ mavenBundle("org.ops4j.pax.exam", "pax-exam-junit4").versionAsInProject(),
+ mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn").versionAsInProject(),
+ mavenBundle("org.ops4j.pax.url", "pax-url-aether").versionAsInProject(),
+
+ mavenBundle("org.ow2.asm", "asm-all").versionAsInProject(),
+
+ mavenBundle("org.springframework", "org.springframework.asm").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.aop").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.context").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.context.support").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.core").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.beans").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.expression").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.web").versionAsInProject(),
+
+ mavenBundle("org.aopalliance", "com.springsource.org.aopalliance").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.web.servlet").versionAsInProject(),
+ mavenBundle("org.springframework.security", "spring-security-config").versionAsInProject(),
+ mavenBundle("org.springframework.security", "spring-security-core").versionAsInProject(),
+ mavenBundle("org.springframework.security", "spring-security-web").versionAsInProject(),
+ mavenBundle("org.springframework.security", "spring-security-taglibs").versionAsInProject(),
+ mavenBundle("org.springframework", "org.springframework.transaction").versionAsInProject(),
+
+ mavenBundle("org.ow2.chameleon.management", "chameleon-mbeans").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller.thirdparty", "com.sun.jersey.jersey-servlet")
+ .versionAsInProject().startLevel(2),
+ mavenBundle("org.opendaylight.controller.thirdparty", "org.apache.catalina.filters.CorsFilter")
+ .versionAsInProject().noStart(),
+
+ // Jersey needs to be started before the northbound application
+ // bundles, using a lower start level
+ mavenBundle("com.sun.jersey", "jersey-client").versionAsInProject(),
+ mavenBundle("com.sun.jersey", "jersey-server").versionAsInProject().startLevel(2),
+ mavenBundle("com.sun.jersey", "jersey-core").versionAsInProject().startLevel(2),
+ mavenBundle("com.sun.jersey", "jersey-json").versionAsInProject().startLevel(2),
+
+ junitBundles());
+ }
+
+}
--- /dev/null
+#pax.exam.system = default
+pax.exam.logging = none
+pax.exam.service.timeout = 5000
+
-<configuration scan="true">\r
-\r
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
- <encoder>\r
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
- </pattern>\r
- </encoder>\r
- </appender>\r
-\r
- <root level="error">\r
- <appender-ref ref="STDOUT" />\r
- </root>\r
-</configuration>\r
+<configuration scan="true">
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+ </pattern>
+ </encoder>
+ </appender>
+
+ <root level="error">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+<?xml version='1.0' encoding='utf-8'?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ You under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License. -->
+<Server>
+ <!--APR library loader. Documentation at /docs/apr.html -->
+ <Listener className="org.apache.catalina.core.AprLifecycleListener"
+ SSLEngine="on" />
+ <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
+ <Listener className="org.apache.catalina.core.JasperListener" />
+ <!-- Prevent memory leaks due to use of particular java/javax APIs -->
+ <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
+ <Listener
+ className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+ <Listener
+ className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
+
+ <Service name="Catalina">
+ <Connector port="8080" protocol="HTTP/1.1"
+ connectionTimeout="20000" redirectPort="8443" />
+
+ <!-- Please remove the comments around the following Connector tag
+ to enable HTTPS Authentication support. Remember to add a valid keystore
+ in the configuration folder. More info : http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration -->
+
+ <!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
+ maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS"
+ keystoreFile="configuration/keystore" keystorePass="changeit"/> -->
+
+ <Engine name="Catalina" defaultHost="localhost">
+ <Host name="localhost" appBase="" unpackWARs="false"
+ autoDeploy="false" deployOnStartup="false" createDirs="false">
+ <!-- Realm
+ className="org.opendaylight.controller.security.ControllerCustomRealm" /> -->
+ <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
+
+ <Valve className="org.apache.catalina.valves.AccessLogValve"
+ directory="logs" prefix="web_access_log_" suffix=".txt"
+ resolveHosts="false" rotatable="true"
+ fileDateFormat="yyyy-MM"
+ pattern="%{yyyy-MM-dd HH:mm:ss.SSS z}t - [%a] - %r" />
+
+ </Host>
+ </Engine>
+ </Service>
+</Server>
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>config-netconf-connector</artifactId>
<name>${project.artifactId}</name>
<version>${bgpcep.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
<build>
package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
import org.opendaylight.controller.config.yang.store.api.YangStoreException;
import org.opendaylight.controller.config.yang.store.api.YangStoreService;
import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
import org.opendaylight.yangtools.yang.model.api.Module;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
/**
* Manages life cycle of {@link YangStoreSnapshot}.
Element response = get();
- System.err.println(XmlUtil.toString(response));
-
assertEquals(2, getElementsSize(response, "instance"));
assertEquals(2, getElementsSize(response, "asdf"));
assertEquals(5, getElementsSize(response, "inner-running-data"));
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>config-persister-impl</artifactId>
<name>${project.artifactId}</name>
javax.management,
javax.xml.parsers,
org.opendaylight.controller.config.persist.api,
- org.opendaylight.controller.config.stat,
org.opendaylight.controller.config.persist.api.storage,
org.opendaylight.controller.netconf.api,
org.opendaylight.controller.netconf.api.jmx,
import com.google.common.base.Optional;
import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(NoOpStorageAdapter.class);
@Override
- public void setProperties(ConfigProvider configProvider) {
- logger.debug("setProperties called with {}", configProvider);
+ public void setProperties(BundleContext bundleContext) {
+ logger.debug("setProperties called with {}", bundleContext);
}
@Override
import com.google.common.base.Optional;
import org.opendaylight.controller.config.persist.api.Persister;
import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
import java.io.IOException;
this.storage = storage;
}
- public static Optional<PersisterImpl> createFromProperties(ConfigProvider configProvider) {
- String storageAdapterClass = configProvider.getProperty(STORAGE_ADAPTER_CLASS_PROP);
+ public static Optional<PersisterImpl> createFromProperties(BundleContext bundleContext) {
+ String storageAdapterClass = bundleContext.getProperty(STORAGE_ADAPTER_CLASS_PROP);
StorageAdapter storage;
if (storageAdapterClass == null || storageAdapterClass.equals("")) {
return Optional.absent();
try {
storage = StorageAdapter.class.cast(resolveClass(storageAdapterClass, StorageAdapter.class).newInstance());
- storage.setProperties(configProvider);
+ storage.setProperties(bundleContext);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new IllegalArgumentException("Unable to instantiate storage adapter from " + storageAdapterClass, e);
import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
import org.opendaylight.controller.netconf.persist.impl.NoOpStorageAdapter;
import org.opendaylight.controller.netconf.persist.impl.PersisterImpl;
-import org.opendaylight.controller.config.stat.ConfigProvider;
import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil.TLSConfiguration;
import org.osgi.framework.BundleActivator;
public void start(BundleContext context) throws Exception {
logger.debug("ConfigPersister activator started");
- ConfigProvider configProvider = new ConfigProvider.ConfigProviderImpl(context);
- Optional<PersisterImpl> maybePersister = PersisterImpl.createFromProperties(configProvider);
+ Optional<PersisterImpl> maybePersister = PersisterImpl.createFromProperties(context);
if (maybePersister.isPresent() == false) {
throw new IllegalStateException("No persister is defined in " + PersisterImpl.STORAGE_ADAPTER_CLASS_PROP
+ " property. For noop persister use " + NoOpStorageAdapter.class.getCanonicalName()
+ " . Persister is not operational");
}
- Optional<TLSConfiguration> maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(configProvider);
- Optional<InetSocketAddress> maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(configProvider);
+ Optional<TLSConfiguration> maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(context);
+ Optional<InetSocketAddress> maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(context);
InetSocketAddress address;
if (maybeTLSConfiguration.isPresent()) {
import org.opendaylight.controller.config.persist.api.Persister;
import org.opendaylight.controller.config.persist.api.storage.StorageAdapter;
import org.opendaylight.controller.config.persist.storage.file.FileStorageAdapter;
-import org.opendaylight.controller.config.stat.ConfigProvider;
+import org.osgi.framework.BundleContext;
import java.io.File;
import java.io.IOException;
public class PersisterImplTest {
@Mock
- ConfigProvider mockedConfigProvider;
+ BundleContext mockedContext;
@Before
public void setUpMocks() {
@Test
public void testFromProperties() throws Exception {
- doReturn(MockAdapter.class.getName()).when(mockedConfigProvider).getProperty(
+ doReturn(MockAdapter.class.getName()).when(mockedContext).getProperty(
PersisterImpl.STORAGE_ADAPTER_CLASS_PROP);
- PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedConfigProvider).get();
+ PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedContext).get();
persisterImpl.persistConfig(null);
persisterImpl.loadLastConfig();
persisterImpl.persistConfig(null);
@Test
public void testFromProperties2() throws Exception {
- mockedConfigProvider = mock(ConfigProvider.class);
- doReturn(FileStorageAdapter.class.getName()).when(mockedConfigProvider).getProperty(
+ mockedContext = mock(BundleContext.class);
+ doReturn(FileStorageAdapter.class.getName()).when(mockedContext).getProperty(
PersisterImpl.STORAGE_ADAPTER_CLASS_PROP);
doReturn("target" + File.separator + "generated-test-sources" + File.separator + "testFile").when(
- mockedConfigProvider).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
- doReturn("mockedConfigProvider").when(mockedConfigProvider).toString();
- doReturn(null).when(mockedConfigProvider).getProperty("numberOfBackups");
+ mockedContext).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
+ doReturn("mockedContext").when(mockedContext).toString();
+ doReturn(null).when(mockedContext).getProperty("numberOfBackups");
- PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedConfigProvider).get();
+ PersisterImpl persisterImpl = PersisterImpl.createFromProperties(mockedContext).get();
assertTrue(persisterImpl.getStorage() instanceof FileStorageAdapter);
}
@Test
public void testFromProperties3() throws Exception {
- mockedConfigProvider = mock(ConfigProvider.class);
- doReturn(FileStorageAdapter.class.getName()).when(mockedConfigProvider).getProperty(
+ mockedContext = mock(BundleContext.class);
+ doReturn(FileStorageAdapter.class.getName()).when(mockedContext).getProperty(
PersisterImpl.STORAGE_ADAPTER_CLASS_PROP);
doReturn("target" + File.separator + "generated-test-sources" + File.separator + "testFile").when(
- mockedConfigProvider).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
- doReturn("mockedConfigProvider").when(mockedConfigProvider).toString();
- doReturn("0").when(mockedConfigProvider).getProperty("numberOfBackups");
+ mockedContext).getProperty(FileStorageAdapter.FILE_STORAGE_PROP);
+ doReturn("mockedContext").when(mockedContext).toString();
+ doReturn("0").when(mockedContext).getProperty("numberOfBackups");
try {
- PersisterImpl.createFromProperties(mockedConfigProvider).get();
+ PersisterImpl.createFromProperties(mockedContext).get();
fail();
} catch (RuntimeException e) {
assertThat(
static int props = 0;
@Override
- public void setProperties(ConfigProvider configProvider) {
+ public void setProperties(BundleContext configProvider) {
props++;
}
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>netconf-api</artifactId>
javax.management,
org.opendaylight.controller.config.api.jmx,
org.opendaylight.protocol.framework,
- org.w3c.dom
+ io.netty.channel,
+ io.netty.util.concurrent,
+ org.w3c.dom,
+ org.slf4j
</Import-Package>
<Export-Package>
org.opendaylight.controller.netconf.api,
</Export-Package>
</instructions>
</configuration>
- </plugin>
+ </plugin>
</plugins>
</build>
public interface NetconfOperationRouter extends AutoCloseable {
- Document onNetconfMessage(Document message) throws NetconfDocumentedException;
+ Document onNetconfMessage(Document message, NetconfSession session)
+ throws NetconfDocumentedException;
@Override
void close();
* 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.api;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+
+import java.io.IOException;
+import java.util.Map;
+
import org.opendaylight.protocol.framework.AbstractProtocolSession;
+import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
+import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
+import org.opendaylight.protocol.framework.SessionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public abstract class NetconfSession extends AbstractProtocolSession<NetconfMessage> {
- public abstract void sendMessage(NetconfMessage netconfMessage);
+ private ChannelHandler exiEncoder;
+ private String exiEncoderName;
+ private String removeAfterMessageSentname;
+ private String pmeName,pmdName;
+ private final Channel channel;
+ private final SessionListener sessionListener;
+ private final long sessionId;
+ private boolean up = false;
+ private static final Logger logger = LoggerFactory.getLogger(NetconfSession.class);
+ private static final int T = 0;
+
+ protected NetconfSession(SessionListener sessionListener, Channel channel, long sessionId) {
+ this.sessionListener = sessionListener;
+ this.channel = channel;
+ this.sessionId = sessionId;
+ logger.debug("Session {} created", toString());
+
+ ChannelHandler pmd = channel.pipeline().get(ProtocolMessageDecoder.class);
+ ChannelHandler pme = channel.pipeline().get(ProtocolMessageEncoder.class);
+
+ for (Map.Entry<String, ChannelHandler> entry:channel.pipeline().toMap().entrySet()){
+ if (entry.getValue().equals(pmd)){
+ pmdName = entry.getKey();
+ }
+ if (entry.getValue().equals(pme)){
+ pmeName = entry.getKey();
+ }
+ }
+ }
+ @Override
+ public void close() {
+ channel.close();
+ sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed"));
+ }
+
+ @Override
+ protected void handleMessage(NetconfMessage netconfMessage) {
+ logger.debug("handlign incomming message");
+ sessionListener.onMessage(this, netconfMessage);
+ }
+
+ public void sendMessage(NetconfMessage netconfMessage) {
+ channel.writeAndFlush(netconfMessage);
+ if (exiEncoder!=null){
+ if (channel.pipeline().get(exiEncoderName)== null){
+ channel.pipeline().addBefore(pmeName, exiEncoderName, exiEncoder);
+ }
+ }
+ if (removeAfterMessageSentname!=null){
+ channel.pipeline().remove(removeAfterMessageSentname);
+ removeAfterMessageSentname = null;
+ }
+ }
+
+ @Override
+ protected void endOfInput() {
+ logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
+ : "initialized");
+ if (isUp()) {
+ this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
+ }
+ }
+
+ @Override
+ protected void sessionUp() {
+ logger.debug("Session {} up", toString());
+ sessionListener.onSessionUp(this);
+ this.up = true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("ServerNetconfSession{");
+ sb.append("sessionId=").append(sessionId);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public boolean isUp() {
+ return up;
+ }
+
+ public long getSessionId() {
+ return sessionId;
+ }
+
+ public <T extends ChannelHandler> T remove(Class<T> handlerType) {
+ return channel.pipeline().remove(handlerType);
+ }
+
+ public <T extends ChannelHandler> T getHandler(Class<T> handlerType) {
+ return channel.pipeline().get(handlerType);
+ }
+
+ public void addFirst(ChannelHandler handler, String name){
+ channel.pipeline().addFirst(name, handler);
+ }
+ public void addLast(ChannelHandler handler, String name){
+ channel.pipeline().addLast(name, handler);
+ }
+
+ public void addExiDecoder(String name,ChannelHandler handler){
+ if (channel.pipeline().get(name)== null){
+ channel.pipeline().addBefore(pmdName, name, handler);
+ }
+ }
+ public void addExiEncoderAfterMessageSent(String name, ChannelHandler handler){
+ this.exiEncoder = handler;
+ this.exiEncoderName = name;
+ }
+
+ public void addExiEncoder(String name, ChannelHandler handler){
+ channel.pipeline().addBefore(pmeName, name, handler);
+ }
+
+ public void removeAfterMessageSent(String handlerName){
+ this.removeAfterMessageSentname = handlerName;
+ }
+
}
+
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>netconf-client</artifactId>
<name>${project.artifactId}</name>
package org.opendaylight.controller.netconf.client;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GlobalEventExecutor;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.protocol.framework.NeverReconnectStrategy;
-import org.opendaylight.protocol.framework.ReconnectStrategy;
-import org.opendaylight.protocol.framework.TimedReconnectStrategy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
public class NetconfClient implements Closeable {
private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
Preconditions.checkState(clientSession != null, "Client was not initialized successfully");
return Sets.newHashSet(clientSession.getServerCapabilities());
}
+
+ public NetconfClientSession getClientSession() {
+ return clientSession;
+ }
}
package org.opendaylight.controller.netconf.client;
import io.netty.channel.Channel;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+
+import java.util.Collection;
+
import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.protocol.framework.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.util.Collection;
-
public class NetconfClientSession extends NetconfSession {
- private final SessionListener sessionListener;
- private final long sessionId;
- private final Channel channel;
-
private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class);
private final Collection<String> capabilities;
- private boolean up;
public NetconfClientSession(SessionListener sessionListener, Channel channel, long sessionId,
Collection<String> capabilities) {
- this.sessionListener = sessionListener;
- this.channel = channel;
- this.sessionId = sessionId;
+ super(sessionListener,channel,sessionId);
this.capabilities = capabilities;
logger.debug("Client Session {} created", toString());
}
- @Override
- public void close() {
- channel.close();
- sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Client Session closed"));
- }
-
- @Override
- protected void handleMessage(NetconfMessage netconfMessage) {
- logger.debug("Client Session {} received message {}", toString(),
- XmlUtil.toString(netconfMessage.getDocument()));
- sessionListener.onMessage(this, netconfMessage);
- }
-
- @Override
- public void sendMessage(NetconfMessage netconfMessage) {
- channel.writeAndFlush(netconfMessage);
- }
-
- @Override
- protected void endOfInput() {
- logger.debug("Client Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
- : "initialized");
- if (isUp()) {
- this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
- }
- }
-
- @Override
- protected void sessionUp() {
- logger.debug("Client Session {} up", toString());
- sessionListener.onSessionUp(this);
- this.up = true;
- }
-
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ClientNetconfSession{");
- sb.append("sessionId=").append(sessionId);
- sb.append('}');
- return sb.toString();
- }
-
- public boolean isUp() {
- return up;
- }
-
- public long getSessionId() {
- return sessionId;
- }
-
public Collection<String> getServerCapabilities() {
return capabilities;
}
+
}
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<capabilities>
<capability>urn:ietf:params:netconf:base:1.0</capability>
+ <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
</capabilities>
</hello>
\ No newline at end of file
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>netconf-impl</artifactId>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
-
<!-- test dependencies -->
<dependency>
<groupId>org.opendaylight.bgpcep</groupId>
<artifactId>netconf-client</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
<build>
io.netty.channel.socket,
io.netty.util,
io.netty.util.concurrent,
+ io.netty.buffer,
+ io.netty.handler.codec,
javax.management,
javax.net.ssl,
javax.xml.namespace,
org.opendaylight.controller.netconf.util.mapping,
org.opendaylight.controller.netconf.util.osgi,
org.opendaylight.controller.netconf.util.xml,
+ org.opendaylight.controller.netconf.util.handler,
org.opendaylight.protocol.framework,
org.osgi.framework,
org.osgi.util.tracker,
org.w3c.dom,
org.xml.sax,
org.opendaylight.controller.netconf.util.messages,
- org.opendaylight.controller.config.stat
+ com.siemens.ct.exi.exceptions
</Import-Package>
</instructions>
</configuration>
package org.opendaylight.controller.netconf.impl;
import io.netty.channel.Channel;
-import org.opendaylight.controller.netconf.api.NetconfMessage;
+
import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.protocol.framework.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
-
public class NetconfServerSession extends NetconfSession {
- private final SessionListener sessionListener;
- private final Channel channel;
-
private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class);
- private final long sessionId;
- private boolean up = false;
public NetconfServerSession(SessionListener sessionListener, Channel channel, long sessionId) {
- this.sessionListener = sessionListener;
- this.channel = channel;
- this.sessionId = sessionId;
+ super(sessionListener,channel,sessionId);
logger.debug("Session {} created", toString());
}
-
- @Override
- public void close() {
- channel.close();
- sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed"));
- }
-
- @Override
- protected void handleMessage(NetconfMessage netconfMessage) {
- logger.debug("Session {} received message {}", toString(), XmlUtil.toString(netconfMessage.getDocument()));
- sessionListener.onMessage(this, netconfMessage);
- }
-
- public void sendMessage(NetconfMessage netconfMessage) {
- channel.writeAndFlush(netconfMessage);
- }
-
- @Override
- protected void endOfInput() {
- logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up"
- : "initialized");
- if (isUp()) {
- this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session."));
- }
- }
-
- @Override
- protected void sessionUp() {
- logger.debug("Session {} up", toString());
- sessionListener.onSessionUp(this);
- this.up = true;
- }
-
- @Override
- public String toString() {
- final StringBuffer sb = new StringBuffer("ServerNetconfSession{");
- sb.append("sessionId=").append(sessionId);
- sb.append('}');
- return sb.toString();
- }
-
- public boolean isUp() {
- return up;
- }
-
- public long getSessionId() {
- return sessionId;
- }
}
package org.opendaylight.controller.netconf.impl;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
+import static com.google.common.base.Preconditions.checkState;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
-import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
public class NetconfServerSessionListener implements
SessionListener<NetconfMessage, NetconfServerSession, NetconfTerminationReason> {
Preconditions.checkState(operationRouter != null, "Cannot handle message, session up was not yet received");
// FIXME: there is no validation since the document may contain yang
// schemas
- final NetconfMessage message = processDocument(netconfMessage);
+ final NetconfMessage message = processDocument(netconfMessage,
+ session);
logger.debug("Respondign with message {}", XmlUtil.toString(message.getDocument()));
session.sendMessage(message);
logger.info("Session {} closed successfully", session.getSessionId());
}
- private NetconfMessage processDocument(final NetconfMessage netconfMessage) throws NetconfDocumentedException {
+ private NetconfMessage processDocument(final NetconfMessage netconfMessage,
+ NetconfSession session) throws NetconfDocumentedException {
final Document incommingDocument = netconfMessage.getDocument();
final Node rootNode = incommingDocument.getDocumentElement();
- if (rootNode.getNodeName().equals(XmlNetconfConstants.RPC_KEY)) {
+ if (rootNode.getLocalName().equals(XmlNetconfConstants.RPC_KEY)) {
final String messageId = rootNode.getAttributes().getNamedItem(MESSAGE_ID).getTextContent();
checkState(messageId != null);
final Document responseDocument = XmlUtil.newDocument();
- Document rpcReply = operationRouter.onNetconfMessage(incommingDocument);
+ Document rpcReply = operationRouter.onNetconfMessage(
+ incommingDocument, session);
responseDocument.appendChild(responseDocument.importNode(rpcReply.getDocumentElement(), true));
return new NetconfMessage(responseDocument);
} else {
private final SessionIdProvider idProvider;
public NetconfServerSessionListenerFactory(NetconfOperationServiceFactoryListener factoriesListener,
- DefaultCommitNotificationProducer commitNotifier, SessionIdProvider idProvider) {
+ DefaultCommitNotificationProducer commitNotifier,
+ SessionIdProvider idProvider) {
this.factoriesListener = factoriesListener;
this.commitNotifier = commitNotifier;
this.idProvider = idProvider;
CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot);
- NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot,
- capabilityProvider, commitNotifier);
+ NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(
+ netconfOperationServiceSnapshot, capabilityProvider,
+ commitNotifier);
return new NetconfServerSessionListener(operationRouter);
}
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.ByteToMessageDecoder;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class ExiDecoderHandler extends ByteToMessageDecoder {\r
+\r
+ public static final String HANDLER_NAME;\r
+\r
+ static {\r
+ HANDLER_NAME = "exiDecoder";\r
+ }\r
+\r
+ private final static Logger logger = LoggerFactory\r
+ .getLogger(ExiDecoderHandler.class);\r
+\r
+ private ExiParameters parameters;\r
+\r
+ public ExiDecoderHandler(ExiParameters parameters) {\r
+ this.parameters = parameters;\r
+ }\r
+\r
+ @Override\r
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in,\r
+ List<Object> out) {\r
+ try {\r
+ ExiUtil.decode(in, out, this.parameters);\r
+ } catch (Exception e) {\r
+ throw new IllegalStateException("Unable to decode exi message.");\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.MessageToByteEncoder;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+\r
+public class ExiEncoderHandler extends MessageToByteEncoder<Object> {\r
+\r
+ public static final String HANDLER_NAME;\r
+ static {\r
+ HANDLER_NAME = "exiEncoder";\r
+ }\r
+\r
+ private ExiParameters parameters;\r
+\r
+ public ExiEncoderHandler(ExiParameters parameters) {\r
+ this.parameters = parameters;\r
+ }\r
+\r
+ @Override\r
+ protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)\r
+ throws Exception {\r
+ try {\r
+ ExiUtil.encode(msg, out, this.parameters);\r
+ } catch (Exception e) {\r
+ throw new IllegalStateException("Unable to encode exi message.");\r
+ }\r
+ }\r
+}\r
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
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;
-public class DefaultCloseSession extends AbstractNetconfOperation {
+public class DefaultCloseSession extends AbstractNetconfOperation implements DefaultNetconfOperation {
public static final String CLOSE_SESSION = "close-session";
+ private NetconfSession netconfSession;
public DefaultCloseSession(String netconfSessionIdForReporting) {
super(netconfSessionIdForReporting);
opRouter.close();
return document.createElement(XmlNetconfConstants.OK);
}
+
+ @Override
+ public void setNetconfSession(NetconfSession s) {
+ this.netconfSession = s;
+ }
+
+ public NetconfSession getNetconfSession() {
+ return netconfSession;
+ }
}
package org.opendaylight.controller.netconf.impl.mapping.operations;
-import com.google.common.collect.Maps;
+import java.io.InputStream;
+import java.util.Map;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
-import java.io.InputStream;
-import java.util.Map;
+import com.google.common.collect.Maps;
public class DefaultCommit implements NetconfOperationFilter {
}
@Override
- public int getSoringOrder() {
+ public int getSortingOrder() {
return 0;
}
@Override
public int compareTo(NetconfOperationFilter o) {
- return Integer.compare(getSoringOrder(), o.getSoringOrder());
+ return Integer.compare(getSortingOrder(), o.getSortingOrder());
}
private boolean canHandle(OperationNameAndNamespace operationNameAndNamespace) {
}
private Element getConfigSnapshot(NetconfOperationRouter opRouter) throws NetconfDocumentedException {
- final Document responseDocument = opRouter.onNetconfMessage(getConfigMessage);
+ final Document responseDocument = opRouter.onNetconfMessage(
+ getConfigMessage, null);
XmlElement dataElement;
try {
package org.opendaylight.controller.netconf.impl.mapping.operations;
-import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.Map;
+
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
+import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
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 java.util.HashMap;
-import java.util.Map;
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
-public final class DefaultGetSchema extends AbstractNetconfOperation {
+public final class DefaultGetSchema extends AbstractNetconfOperation implements DefaultNetconfOperation {
private final CapabilityProvider cap;
+ private NetconfSession netconfSession;
private static final Logger logger = LoggerFactory.getLogger(DefaultGetSchema.class);
}
}
+
+ public void setNetconfSession(NetconfSession s) {
+ this.netconfSession = s;
+ }
+
+ public NetconfSession getNetconfSession() {
+ return netconfSession;
+ }
}
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\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.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\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.xml.ExiParameters;\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.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+\r
+public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+ public static final String START_EXI = "start-exi";\r
+\r
+ private static NetconfSession netconfSession;\r
+\r
+ private static final Logger logger = LoggerFactory.getLogger(DefaultStartExi.class);\r
+\r
+ public DefaultStartExi(String netconfSessionIdForReporting) {\r
+ super(netconfSessionIdForReporting);\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
+ }\r
+\r
+ @Override\r
+ protected Element handle(Document document, XmlElement operationElement,\r
+ NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+\r
+ Element getSchemaResult = document\r
+ .createElement(XmlNetconfConstants.OK);\r
+ XmlUtil.addNamespaceAttr(getSchemaResult,\r
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+\r
+\r
+ try {\r
+ ExiParameters exiParams = new ExiParameters();\r
+ exiParams.setParametersFromXmlElement(operationElement);\r
+\r
+ netconfSession.addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));\r
+ netconfSession.addExiEncoderAfterMessageSent(ExiEncoderHandler.HANDLER_NAME,new ExiEncoderHandler(exiParams));\r
+\r
+ } catch (EXIException e) {\r
+ getSchemaResult = document\r
+ .createElement(XmlNetconfConstants.RPC_ERROR);\r
+ }\r
+\r
+ logger.info("{} operation successful", START_EXI);\r
+ logger.debug("received start-exi message {} ", XmlUtil.toString(document));\r
+ return getSchemaResult;\r
+\r
+ }\r
+\r
+ @Override\r
+ public void setNetconfSession(NetconfSession s) {\r
+ netconfSession = s;\r
+ }\r
+\r
+ public NetconfSession getNetconfSession() {\r
+ return netconfSession;\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\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.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\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.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\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
+\r
+ public static final String STOP_EXI = "stop-exi";\r
+ private NetconfSession netconfSession;\r
+\r
+ private static final Logger logger = LoggerFactory\r
+ .getLogger(DefaultStartExi.class);\r
+\r
+ public DefaultStopExi(String netconfSessionIdForReporting) {\r
+ super(netconfSessionIdForReporting);\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
+ }\r
+\r
+ @Override\r
+ protected Element handle(Document document, XmlElement operationElement,\r
+ NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+ netconfSession.remove(ExiDecoderHandler.class);\r
+ netconfSession.removeAfterMessageSent(ExiEncoderHandler.HANDLER_NAME);\r
+\r
+ Element getSchemaResult = document.createElement(XmlNetconfConstants.OK);\r
+ XmlUtil.addNamespaceAttr(getSchemaResult,\r
+ XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+ logger.info("{} operation successful", STOP_EXI);\r
+ logger.debug("received stop-exi message {} ", XmlUtil.toString(document));\r
+ return getSchemaResult;\r
+ }\r
+\r
+ @Override\r
+ public void setNetconfSession(NetconfSession s) {\r
+ this.netconfSession = s;\r
+ }\r
+\r
+ public NetconfSession getNetconfSession() {\r
+ return netconfSession;\r
+ }\r
+}
\ No newline at end of file
import com.google.common.base.Optional;
import io.netty.util.HashedWheelTimer;
-import org.opendaylight.controller.config.stat.ConfigProvider;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
@Override
public void start(final BundleContext context) throws Exception {
- final ConfigProvider configProvider = new ConfigProvider.ConfigProviderImpl(context);
- maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(configProvider);
- maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(configProvider);
+ maybeTCPAddress = NetconfConfigUtil.extractTCPNetconfAddress(context);
+ maybeTLSConfiguration = NetconfConfigUtil.extractTLSConfiguration(context);
if (maybeTCPAddress.isPresent() == false && maybeTLSConfiguration.isPresent() == false) {
throw new IllegalStateException("TCP nor TLS is configured, netconf not available.");
}
*/
package org.opendaylight.controller.netconf.impl.osgi;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+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.api.NetconfSession;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit;
import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi;
+import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi;
+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.slf4j.LoggerFactory;
import org.w3c.dom.Document;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
public class NetconfOperationRouterImpl implements NetconfOperationRouter {
private final CapabilityProvider capabilityProvider;
+
public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
- CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+ CapabilityProvider capabilityProvider,
+ DefaultCommitNotificationProducer commitNotifier) {
this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
.getNetconfSessionIdForReporting()));
defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot
.getNetconfSessionIdForReporting()));
+ defaultNetconfOperations.add(new DefaultStartExi(
+ netconfOperationServiceSnapshot
+ .getNetconfSessionIdForReporting()));
+ defaultNetconfOperations.add(new DefaultStopExi(
+ netconfOperationServiceSnapshot
+ .getNetconfSessionIdForReporting()));
allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
}
@Override
- public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException {
- NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message);
+ public synchronized Document onNetconfMessage(Document message,
+ NetconfSession session) throws NetconfDocumentedException {
+ NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(
+ message, session);
logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message),
netconfOperationExecution.operationWithHighestPriority);
return chain.getFirst().execute(message, this);
}
- private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) {
+ private NetconfOperationExecution getNetconfOperationWithHighestPriority(
+ Document message, NetconfSession session) {
// TODO test
- TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
+ TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
+ message, session);
Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
NetconfOperation.class.getName(), XmlUtil.toString(message));
return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
}
- private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
+ private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
+ Document message, NetconfSession session) {
TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
for (NetconfOperation netconfOperation : allNetconfOperations) {
final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
-
+ if (netconfOperation instanceof DefaultNetconfOperation) {
+ ((DefaultNetconfOperation) netconfOperation)
+ .setNetconfSession(session);
+ }
if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
+ '}';
}
+
+
+
}
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<capabilities>
<capability>urn:ietf:params:netconf:base:1.0</capability>
+ <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
</capabilities>
<session-id>1</session-id>
</hello>
--- /dev/null
+package org.opendaylight.controller.netconf.impl;\r
+\r
+import static junit.framework.Assert.assertNotNull;\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.junit.Test;\r
+import org.opendaylight.controller.netconf.api.NetconfMessage;\r
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+\r
+\r
+\r
+public class ExiEncodeDecodeTest {\r
+ @Test\r
+ public void encodeExi() throws Exception{\r
+\r
+ String startExiString = XmlFileLoader.xmlFileToString("netconfMessages/startExi.xml");\r
+ assertNotNull(startExiString);\r
+\r
+ NetconfMessage startExiMessage = XmlFileLoader.xmlFileToNetconfMessage(("netconfMessages/startExi.xml"));\r
+ assertNotNull(startExiMessage);\r
+\r
+ ExiParameters exiParams = new ExiParameters();\r
+ exiParams.setParametersFromXmlElement(XmlElement.fromDomElement(startExiMessage.getDocument().getDocumentElement()));\r
+ assertNotNull(exiParams);\r
+\r
+ ByteBuf encodedBuf = Unpooled.buffer();\r
+ ByteBuf sourceBuf = Unpooled.copiedBuffer(startExiString.getBytes());\r
+ ExiUtil.encode(sourceBuf, encodedBuf, exiParams);\r
+\r
+ List<Object> newOut = new ArrayList<Object>();\r
+ ExiUtil.decode(encodedBuf, newOut, exiParams);\r
+\r
+ ByteBuf decodedBuf = (ByteBuf)newOut.get(0);\r
+ String decodedString = new String(decodedBuf.array(),"UTF-8");\r
+ assertNotNull(decodedString);\r
+ }\r
+}\r
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>netconf-it</artifactId>
<artifactId>mockito-configuration</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
<build>
import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
// private static final Logger logger =
// LoggerFactory.getLogger(NetconfITTest.class);
//
+
private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
- private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession;
+ private NetconfMessage getConfig, getConfigCandidate, editConfig,
+ closeSession, startExi, stopExi;
private DefaultCommitNotificationProducer commitNot;
private NetconfServerDispatcher dispatch;
this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
+ this.startExi = XmlFileLoader
+ .xmlFileToNetconfMessage("netconfMessages/startExi.xml");
+ this.stopExi = XmlFileLoader
+ .xmlFileToNetconfMessage("netconfMessages/stopExi.xml");
this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
}
final Element rpcReply = message.getDocument().getDocumentElement();
final XmlElement resultElement = XmlElement.fromDomElement(rpcReply).getOnlyChildElement();
assertEquals("result", resultElement.getName());
+
final String namespace = resultElement.getNamespaceAttribute();
assertEquals(expectedNamespace, namespace);
}
});
}
+ @Test
+// @Ignore
+ public void testStartExi() throws Exception {
+ try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
+
+
+ Document rpcReply = netconfClient.sendMessage(this.startExi)
+ .getDocument();
+ assertIsOK(rpcReply);
+
+ ExiParameters exiParams = new ExiParameters();
+ exiParams.setParametersFromXmlElement(XmlElement.fromDomDocument(this.startExi.getDocument()));
+
+ netconfClient.getClientSession().addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));
+ netconfClient.getClientSession().addExiEncoder(ExiEncoderHandler.HANDLER_NAME, new ExiEncoderHandler(exiParams));
+
+ rpcReply = netconfClient.sendMessage(this.editConfig)
+ .getDocument();
+ assertIsOK(rpcReply);
+
+ rpcReply = netconfClient.sendMessage(this.stopExi)
+ .getDocument();
+ assertIsOK(rpcReply);
+
+ }
+ }
+
@Test
public void testCloseSession() throws Exception {
try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
// edit config
- Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
+ Document rpcReply = netconfClient.sendMessage(this.editConfig)
+ .getDocument();
assertIsOK(rpcReply);
- rpcReply = netconfClient.sendMessage(this.closeSession).getDocument();
+ rpcReply = netconfClient.sendMessage(this.closeSession)
+ .getDocument();
assertIsOK(rpcReply);
}
}
private void assertIsOK(final Document rpcReply) {
- assertEquals("rpc-reply", rpcReply.getDocumentElement().getTagName());
+ assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName());
assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
}
private NetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception {
final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, NETCONF_CLIENT_DISPATCHER);
-
assertEquals(expected, Long.toString(netconfClient.getSessionId()));
-
return netconfClient;
}
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>netconf-mapping-api</artifactId>
--- /dev/null
+package org.opendaylight.controller.netconf.mapping.api;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+\r
+public interface DefaultNetconfOperation {\r
+ void setNetconfSession(NetconfSession s);\r
+}\r
Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain)
throws NetconfDocumentedException;
- int getSoringOrder();
+ int getSortingOrder();
}
<parent>
<artifactId>netconf-subsystem</artifactId>
<groupId>org.opendaylight.controller</groupId>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
</parent>
<artifactId>netconf-util</artifactId>
<name>${project.artifactId}</name>
<artifactId>netty-handler</artifactId>
<version>${netconf.netty.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.siemens.ct.exi</groupId>
+ <artifactId>exificient</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller.thirdparty</groupId>
<artifactId>ganymed</artifactId>
org.opendaylight.controller.netconf.util.osgi,
org.opendaylight.controller.netconf.util.mapping,
org.opendaylight.controller.netconf.util.messages,
+ org.opendaylight.controller.netconf.util.handler,
</Export-Package>
<Import-Package>
- org.opendaylight.controller.config.stat,
com.google.common.base,
com.google.common.collect,
ch.ethz.ssh2,
javax.xml.transform.stream,
javax.xml.validation,
javax.xml.xpath,
+ javax.xml.transform.sax,
org.opendaylight.controller.netconf.api,
org.opendaylight.controller.netconf.mapping.api,
org.opendaylight.protocol.framework,
org.slf4j,
org.w3c.dom,
org.xml.sax,
+ com.siemens.ct.exi,
+ com.siemens.ct.exi.api.sax,
+ com.siemens.ct.exi.grammars,
+ com.siemens.ct.exi.helpers,
+ com.siemens.ct.exi.exceptions,
+ com.siemens.ct.exi.api.dom,
+ org.xml.sax.helpers,
</Import-Package>
</instructions>
</configuration>
package org.opendaylight.controller.netconf.util.handler;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
import java.util.List;
import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
public class NetconfMessageAggregator extends ByteToMessageDecoder {
private final static Logger logger = LoggerFactory.getLogger(NetconfMessageAggregator.class);
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
int index = indexOfSequence(in, eom);
if (index == -1) {
- logger.debug("Message is not complete, read agian.");
+ logger.debug("Message is not complete, read again.");
ctx.read();
} else {
ByteBuf msg = in.readBytes(index);
package org.opendaylight.controller.netconf.util.mapping;
-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.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.util.Map;
public abstract class AbstractNetconfOperation implements NetconfOperation {
private final String netconfSessionIdForReporting;
Map<String, Attr> attributes = requestElement.getAttributes();
Element response = handle(document, operationElement, opRouter);
-
Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
XmlNetconfConstants.RPC_REPLY_KEY);
- rpcReply.appendChild(response);
- for (String attrName : attributes.keySet()) {
- rpcReply.setAttribute(attrName, attributes.get(attrName).getNodeValue());
+ if(XmlElement.fromDomElement(response).hasNamespace()) {
+ rpcReply.appendChild(response);
+ } else {
+ Element responseNS = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, response.getNodeName());
+ NodeList list = response.getChildNodes();
+ while(list.getLength()!=0) {
+ responseNS.appendChild(list.item(0));
+ }
+ rpcReply.appendChild(responseNS);
}
+ for (String attrName : attributes.keySet()) {
+ rpcReply.setAttributeNode((Attr) document.importNode(attributes.get(attrName), true));
+ }
document.appendChild(rpcReply);
return document;
}
package org.opendaylight.controller.netconf.util.osgi;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Optional;
+import org.opendaylight.protocol.util.SSLUtil;
+import org.osgi.framework.BundleContext;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.InetSocketAddress;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-
-import org.opendaylight.controller.config.stat.ConfigProvider;
-import org.opendaylight.protocol.util.SSLUtil;
-
-import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
public class NetconfConfigUtil {
private static final String PREFIX_PROP = "netconf.";
private static final String NETCONF_TLS_KEYSTORE_PROP = PREFIX_PROP + InfixProp.tls + ".keystore";
private static final String NETCONF_TLS_KEYSTORE_PASSWORD_PROP = NETCONF_TLS_KEYSTORE_PROP + ".password";
- public static Optional<InetSocketAddress> extractTCPNetconfAddress(ConfigProvider configProvider) {
- return extractSomeNetconfAddress(configProvider, InfixProp.tcp);
+ public static Optional<InetSocketAddress> extractTCPNetconfAddress(BundleContext context) {
+ return extractSomeNetconfAddress(context, InfixProp.tcp);
}
- public static Optional<TLSConfiguration> extractTLSConfiguration(ConfigProvider configProvider) {
- Optional<InetSocketAddress> address = extractSomeNetconfAddress(configProvider, InfixProp.tls);
+ public static Optional<TLSConfiguration> extractTLSConfiguration(BundleContext context) {
+ Optional<InetSocketAddress> address = extractSomeNetconfAddress(context, InfixProp.tls);
if (address.isPresent()) {
- String keystoreFileName = configProvider.getProperty(NETCONF_TLS_KEYSTORE_PROP);
+ String keystoreFileName = context.getProperty(NETCONF_TLS_KEYSTORE_PROP);
File keystoreFile = new File(keystoreFileName);
checkState(keystoreFile.exists() && keystoreFile.isFile() && keystoreFile.canRead(),
"Keystore file %s does not exist or is not readable file", keystoreFileName);
keystoreFile = keystoreFile.getAbsoluteFile();
- String keystorePassword = configProvider.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
+ String keystorePassword = context.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
checkNotNull(keystoreFileName, "Property %s must be defined for tls netconf server",
NETCONF_TLS_KEYSTORE_PROP);
keystorePassword = keystorePassword != null ? keystorePassword : "";
}
/**
- * @param configProvider
+ * @param context
* from which properties are being read.
* @param infixProp
* either tcp or tls
* @throws IllegalStateException
* if address or port are invalid
*/
- private static Optional<InetSocketAddress> extractSomeNetconfAddress(ConfigProvider configProvider,
+ private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
InfixProp infixProp) {
- String address = configProvider.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
+ String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
if (address == null) {
return Optional.absent();
}
String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
- String portString = configProvider.getProperty(portKey);
+ String portString = context.getProperty(portKey);
checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
try {
int port = Integer.valueOf(portString);
--- /dev/null
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import com.siemens.ct.exi.CodingMode;\r
+import com.siemens.ct.exi.FidelityOptions;\r
+import com.siemens.ct.exi.GrammarFactory;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.grammars.Grammars;\r
+\r
+public class ExiParameters {\r
+\r
+ private static final String EXI_PARAMETER_ALIGNMENT = "alignment";\r
+ private static final String EXI_PARAMETER_BYTE_ALIGNED = "byte-aligned";\r
+ private static final String EXI_PARAMETER_COMPRESSED = "compressed";\r
+\r
+ private static final String EXI_PARAMETER_FIDELITY = "fidelity";\r
+ private static final String EXI_FIDELITY_DTD = "dtd";\r
+ private static final String EXI_FIDELITY_LEXICAL_VALUES = "lexical-values";\r
+ private static final String EXI_FIDELITY_COMMENTS = "comments";\r
+ private static final String EXI_FIDELITY_PIS = "pis";\r
+ private static final String EXI_FIDELITY_PREFIXES = "prefixes";\r
+\r
+ private static final String EXI_PARAMETER_SCHEMA = "schema";\r
+ private static final String EXI_PARAMETER_SCHEMA_NONE = "none";\r
+ private static final String EXI_PARAMETER_SCHEMA_BUILT_IN = "builtin";\r
+ private static final String EXI_PARAMETER_SCHEMA_BASE_1_1 = "base:1.1";\r
+\r
+ private static final String NETCONF_XSD_LOCATION = "";\r
+\r
+ private FidelityOptions fidelityOptions;\r
+ private Grammars grammars;\r
+ private CodingMode codingMode = CodingMode.BIT_PACKED;\r
+\r
+ public void setParametersFromXmlElement(XmlElement operationElement)\r
+ throws EXIException {\r
+\r
+ if (operationElement.getElementsByTagName(EXI_PARAMETER_ALIGNMENT)\r
+ .getLength() > 0) {\r
+\r
+ if (operationElement.getElementsByTagName(\r
+ EXI_PARAMETER_BYTE_ALIGNED)\r
+ .getLength() > 0) {\r
+ this.codingMode = CodingMode.BYTE_PACKED;\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(\r
+ EXI_PARAMETER_BYTE_ALIGNED).getLength() > 0) {\r
+ this.codingMode = CodingMode.BYTE_PACKED;\r
+ }\r
+ if (operationElement.getElementsByTagName(EXI_PARAMETER_COMPRESSED)\r
+ .getLength() > 0) {\r
+ this.codingMode = CodingMode.COMPRESSION;\r
+ }\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(EXI_PARAMETER_FIDELITY)\r
+ .getLength() > 0) {\r
+\r
+ this.fidelityOptions = FidelityOptions.createDefault();\r
+\r
+ if (operationElement.getElementsByTagName(EXI_FIDELITY_DTD)\r
+ .getLength() > 0) {\r
+ this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_DTD,\r
+ true);\r
+ }\r
+ if (operationElement.getElementsByTagName(\r
+ EXI_FIDELITY_LEXICAL_VALUES)\r
+ .getLength() > 0) {\r
+ this.fidelityOptions.setFidelity(\r
+ FidelityOptions.FEATURE_LEXICAL_VALUE, true);\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(EXI_FIDELITY_COMMENTS)\r
+ .getLength() > 0) {\r
+ this.fidelityOptions.setFidelity(\r
+ FidelityOptions.FEATURE_COMMENT, true);\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(EXI_FIDELITY_PIS)\r
+ .getLength() > 0) {\r
+ this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_PI,\r
+ true);\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(EXI_FIDELITY_PREFIXES)\r
+ .getLength() > 0) {\r
+ this.fidelityOptions.setFidelity(\r
+ FidelityOptions.FEATURE_PREFIX, true);\r
+ }\r
+\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(EXI_PARAMETER_SCHEMA)\r
+ .getLength() > 0) {\r
+\r
+ GrammarFactory grammarFactory = GrammarFactory.newInstance();\r
+ if (operationElement\r
+ .getElementsByTagName(EXI_PARAMETER_SCHEMA_NONE)\r
+ .getLength() > 0) {\r
+ this.grammars = grammarFactory.createSchemaLessGrammars();\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(\r
+ EXI_PARAMETER_SCHEMA_BUILT_IN).getLength() > 0) {\r
+ this.grammars = grammarFactory.createXSDTypesOnlyGrammars();\r
+ }\r
+\r
+ if (operationElement.getElementsByTagName(\r
+ EXI_PARAMETER_SCHEMA_BASE_1_1).getLength() > 0) {\r
+ this.grammars = grammarFactory\r
+ .createGrammars(NETCONF_XSD_LOCATION);\r
+ }\r
+\r
+ }\r
+ }\r
+\r
+ public FidelityOptions getFidelityOptions() {\r
+ return fidelityOptions;\r
+ }\r
+\r
+ public Grammars getGrammars() {\r
+ return grammars;\r
+ }\r
+\r
+ public CodingMode getCodingMode() {\r
+ return codingMode;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.EmptyByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.xml.parsers.ParserConfigurationException;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.xml.sax.SAXException;\r
+\r
+import com.siemens.ct.exi.EXIFactory;\r
+import com.siemens.ct.exi.api.dom.DOMBuilder;\r
+import com.siemens.ct.exi.api.dom.DOMWriter;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.helpers.DefaultEXIFactory;\r
+\r
+public class ExiUtil {\r
+\r
+ private final static Logger logger = LoggerFactory.getLogger(ExiUtil.class);\r
+\r
+\r
+\r
+ public static void encode(final Object msg, final ByteBuf out,\r
+ ExiParameters parameters)\r
+ throws EXIException, IOException, SAXException {\r
+ final byte[] bytes = toExi(msg, parameters);\r
+ out.writeBytes(bytes);\r
+ }\r
+\r
+ public static void decode(ByteBuf in, List<Object> out,\r
+ ExiParameters parameters) throws ParserConfigurationException, EXIException, IOException\r
+ {\r
+ if (in instanceof EmptyByteBuf){\r
+ return;\r
+ }\r
+\r
+ EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+ if (parameters.getGrammars() != null) {\r
+ exiFactory.setGrammars(parameters.getGrammars());\r
+ }\r
+\r
+ if (parameters.getFidelityOptions() != null) {\r
+ exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+ }\r
+\r
+ exiFactory.setCodingMode(parameters.getCodingMode());\r
+ try (ByteArrayInputStream exiIS = new ByteArrayInputStream(((ByteBuf)in).readBytes(((ByteBuf)in).readableBytes()).array())){\r
+ DOMBuilder domBuilder = new DOMBuilder(exiFactory);\r
+ ByteBuf result = Unpooled.copiedBuffer(XmlUtil.toString(domBuilder.parse(exiIS)).getBytes());\r
+ exiIS.close();\r
+ out.add(result);\r
+ }\r
+ }\r
+\r
+ private static byte[] toExi(Object msg, ExiParameters parameters) throws EXIException, IOException,\r
+ SAXException {\r
+\r
+ if (!(msg instanceof ByteBuf)){\r
+ return Unpooled.EMPTY_BUFFER.array();\r
+ }\r
+\r
+ EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+ if (parameters.getGrammars() != null) {\r
+ exiFactory.setGrammars(parameters.getGrammars());\r
+ }\r
+\r
+ if (parameters.getFidelityOptions() != null) {\r
+ exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+ }\r
+\r
+ Document doc = XmlUtil.readXmlToDocument(new String( ((ByteBuf)msg).readBytes(((ByteBuf)msg).readableBytes()).array(),"UTF-8"));\r
+ exiFactory.setCodingMode(parameters.getCodingMode());\r
+\r
+ try (ByteArrayOutputStream exiOS = new ByteArrayOutputStream()){\r
+ DOMWriter domWriter = new DOMWriter(exiFactory);\r
+ domWriter.setOutput(exiOS);\r
+ domWriter.encode(doc) ;\r
+ exiOS.close();\r
+ return exiOS.toByteArray();\r
+ }\r
+ }\r
+\r
+}\r
}
public String getName() {
+ if (element.getLocalName()!=null && !element.getLocalName().equals("")){
+ return element.getLocalName();
+ }
return element.getTagName();
}
return element.getAttributeNS(namespace, attributeName);
}
+ public NodeList getElementsByTagName(String name) {
+ return element.getElementsByTagName(name);
+ }
+
public void appendChild(Element element) {
this.element.appendChild(element);
// Element newElement = (Element) element.cloneNode(true);
public String getNamespaceAttribute() {
String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY);
- Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify a %s attribute",
- toString(), XmlUtil.XMLNS_ATTRIBUTE_KEY);
+ Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify namespace",
+ toString());
return attribute;
}
return element.hashCode();
}
+ public boolean hasNamespace() {
+ try {
+ getNamespaceAttribute();
+ } catch (IllegalStateException e) {
+ try {
+ getNamespace();
+ } catch (IllegalStateException e1) {
+ return false;
+ }
+ return true;
+ }
+ return true;
+ }
+
private static interface ElementFilteringStrategy {
boolean accept(Element e);
}
//
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";
package org.opendaylight.controller.netconf.util.xml;
-import com.google.common.base.Charsets;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.xml.sax.SAXException;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.validation.SchemaFactory;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import com.google.common.base.Charsets;
public class XmlUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setCoalescing(true);
- // factory.setValidating(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setIgnoringComments(true);
return factory;
package org.opendaylight.controller.netconf.util.test;
-import com.google.common.base.Charsets;
-import com.google.common.base.Preconditions;
-import com.google.common.io.CharStreams;
-import com.google.common.io.InputSupplier;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.xml.parsers.ParserConfigurationException;
+
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
+import com.google.common.io.CharStreams;
+import com.google.common.io.InputSupplier;
public class XmlFileLoader {
--- /dev/null
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" message-id="a">\r
+<start-exi>\r
+<alignment>pre-compression</alignment>\r
+<fidelity>\r
+<dtd/>\r
+<lexical-values/>\r
+</fidelity>\r
+</start-exi>\r
+</rpc>
\ No newline at end of file
--- /dev/null
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+ <stop-exi/>\r
+</rpc>
\ No newline at end of file
<relativePath>../commons/opendaylight</relativePath>
</parent>
- <version>0.2.2-SNAPSHOT</version>
+ <version>0.2.3-SNAPSHOT</version>
<artifactId>netconf-subsystem</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<module>netconf-mapping-api</module>
<module>netconf-client</module>
<module>../../third-party/ganymed</module>
+ <module>../../third-party/com.siemens.ct.exi</module>
</modules>
<profiles>
<maven.bundle.version>2.3.7</maven.bundle.version>
<slf4j.version>1.7.2</slf4j.version>
<netconf.netty.version>4.0.10.Final</netconf.netty.version>
+ <ct.exi.version>0.9.2</ct.exi.version>
</properties>
<dependencies>
<artifactId>logback-config</artifactId>
<version>${config.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.siemens.ct.exi</groupId>
+ <artifactId>exificient</artifactId>
+ <version>${ct.exi.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.util.Hashtable;\r
-import java.util.Dictionary;\r
-import org.apache.felix.dm.Component;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;\r
-\r
-public class Activator extends ComponentActivatorAbstractBase {\r
- protected static final Logger logger = LoggerFactory\r
- .getLogger(Activator.class);\r
-\r
- /**\r
- * Function called when the activator starts just after some\r
- * initializations are done by the\r
- * ComponentActivatorAbstractBase.\r
- *\r
- */\r
- public void init() {\r
-\r
- }\r
-\r
- /**\r
- * Function called when the activator stops just before the\r
- * cleanup done by ComponentActivatorAbstractBase\r
- *\r
- */\r
- public void destroy() {\r
-\r
- }\r
-\r
- /**\r
- * Function that is used to communicate to dependency manager the\r
- * list of known implementations for services inside a container\r
- *\r
- *\r
- * @return An array containing all the CLASS objects that will be\r
- * instantiated in order to get an fully working implementation\r
- * Object\r
- */\r
- public Object[] getImplementations() {\r
- Object[] res = { NeutronFloatingIPInterface.class,\r
- NeutronRouterInterface.class,\r
- NeutronPortInterface.class,\r
- NeutronSubnetInterface.class,\r
- NeutronNetworkInterface.class };\r
- return res;\r
- }\r
-\r
- /**\r
- * Function that is called when configuration of the dependencies\r
- * is required.\r
- *\r
- * @param c dependency manager Component object, used for\r
- * configuring the dependencies exported and imported\r
- * @param imp Implementation class that is being configured,\r
- * needed as long as the same routine can configure multiple\r
- * implementations\r
- * @param containerName The containerName being configured, this allow\r
- * also optional per-container different behavior if needed, usually\r
- * should not be the case though.\r
- */\r
- public void configureInstance(Component c, Object imp, String containerName) {\r
- if (imp.equals(NeutronFloatingIPInterface.class)) {\r
- // export the service\r
- c.setInterface(\r
- new String[] { INeutronFloatingIPCRUD.class.getName() }, null);\r
- Dictionary<String, String> props = new Hashtable<String, String>();\r
- props.put("salListenerName", "neutron");\r
- c.add(createContainerServiceDependency(containerName)\r
- .setService(IClusterContainerServices.class)\r
- .setCallbacks("setClusterContainerService",\r
- "unsetClusterContainerService").setRequired(true));\r
- }\r
- if (imp.equals(NeutronRouterInterface.class)) {\r
- // export the service\r
- c.setInterface(\r
- new String[] { INeutronRouterCRUD.class.getName() }, null);\r
- Dictionary<String, String> props = new Hashtable<String, String>();\r
- props.put("salListenerName", "neutron");\r
- c.add(createContainerServiceDependency(containerName)\r
- .setService(IClusterContainerServices.class)\r
- .setCallbacks("setClusterContainerService",\r
- "unsetClusterContainerService").setRequired(true));\r
- }\r
- if (imp.equals(NeutronPortInterface.class)) {\r
- // export the service\r
- c.setInterface(\r
- new String[] { INeutronPortCRUD.class.getName() }, null);\r
- Dictionary<String, String> props = new Hashtable<String, String>();\r
- props.put("salListenerName", "neutron");\r
- c.add(createContainerServiceDependency(containerName)\r
- .setService(IClusterContainerServices.class)\r
- .setCallbacks("setClusterContainerService",\r
- "unsetClusterContainerService").setRequired(true));\r
- }\r
- if (imp.equals(NeutronSubnetInterface.class)) {\r
- // export the service\r
- c.setInterface(\r
- new String[] { INeutronSubnetCRUD.class.getName() }, null);\r
- Dictionary<String, String> props = new Hashtable<String, String>();\r
- props.put("salListenerName", "neutron");\r
- c.add(createContainerServiceDependency(containerName)\r
- .setService(IClusterContainerServices.class)\r
- .setCallbacks("setClusterContainerService",\r
- "unsetClusterContainerService").setRequired(true));\r
- }\r
- if (imp.equals(NeutronNetworkInterface.class)) {\r
- // export the service\r
- c.setInterface(\r
- new String[] { INeutronNetworkCRUD.class.getName() }, null);\r
- Dictionary<String, String> props = new Hashtable<String, String>();\r
- props.put("salListenerName", "neutron");\r
- c.add(createContainerServiceDependency(containerName)\r
- .setService(IClusterContainerServices.class)\r
- .setCallbacks("setClusterContainerService",\r
- "unsetClusterContainerService").setRequired(true));\r
- }\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.implementation;
+
+import java.util.Hashtable;
+import java.util.Dictionary;
+import org.apache.felix.dm.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+
+public class Activator extends ComponentActivatorAbstractBase {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(Activator.class);
+
+ /**
+ * Function called when the activator starts just after some
+ * initializations are done by the
+ * ComponentActivatorAbstractBase.
+ *
+ */
+ public void init() {
+
+ }
+
+ /**
+ * Function called when the activator stops just before the
+ * cleanup done by ComponentActivatorAbstractBase
+ *
+ */
+ public void destroy() {
+
+ }
+
+ /**
+ * Function that is used to communicate to dependency manager the
+ * list of known implementations for services inside a container
+ *
+ *
+ * @return An array containing all the CLASS objects that will be
+ * instantiated in order to get an fully working implementation
+ * Object
+ */
+ public Object[] getImplementations() {
+ Object[] res = { NeutronFloatingIPInterface.class,
+ NeutronRouterInterface.class,
+ NeutronPortInterface.class,
+ NeutronSubnetInterface.class,
+ NeutronNetworkInterface.class };
+ return res;
+ }
+
+ /**
+ * Function that is called when configuration of the dependencies
+ * is required.
+ *
+ * @param c dependency manager Component object, used for
+ * configuring the dependencies exported and imported
+ * @param imp Implementation class that is being configured,
+ * needed as long as the same routine can configure multiple
+ * implementations
+ * @param containerName The containerName being configured, this allow
+ * also optional per-container different behavior if needed, usually
+ * should not be the case though.
+ */
+ public void configureInstance(Component c, Object imp, String containerName) {
+ if (imp.equals(NeutronFloatingIPInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronFloatingIPCRUD.class.getName() }, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronRouterInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronRouterCRUD.class.getName() }, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronPortInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronPortCRUD.class.getName() }, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronSubnetInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronSubnetCRUD.class.getName() }, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronNetworkInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronNetworkCRUD.class.getName() }, null);
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("salListenerName", "neutron");
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ }
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronFloatingIPInterface implements INeutronFloatingIPCRUD {\r
- private static final Logger logger = LoggerFactory.getLogger(NeutronFloatingIPInterface.class);\r
- private String containerName = null;\r
-\r
- private IClusterContainerServices clusterContainerService = null;\r
- private ConcurrentMap<String, NeutronFloatingIP> floatingIPDB;\r
-\r
- // methods needed for creating caches\r
-\r
- void setClusterContainerService(IClusterContainerServices s) {\r
- logger.debug("Cluster Service set");\r
- this.clusterContainerService = s;\r
- }\r
-\r
- void unsetClusterContainerService(IClusterContainerServices s) {\r
- if (this.clusterContainerService == s) {\r
- logger.debug("Cluster Service removed!");\r
- this.clusterContainerService = null;\r
- }\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void allocateCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't create cache");\r
- return;\r
- }\r
- logger.debug("Creating Cache for Neutron FloatingIPs");\r
- try {\r
- // neutron caches\r
- this.clusterContainerService.createCache("neutronFloatingIPs",\r
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
- } catch (CacheConfigException cce) {\r
- logger.error("Cache couldn't be created for Neutron - check cache mode");\r
- } catch (CacheExistException cce) {\r
- logger.error("Cache for Neutron already exists, destroy and recreate");\r
- }\r
- logger.debug("Cache successfully created for NeutronFloatingIps");\r
- }\r
-\r
- @SuppressWarnings({ "unchecked", "deprecation" })\r
- private void retrieveCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
- return;\r
- }\r
-\r
- logger.debug("Retrieving cache for Neutron FloatingIPs");\r
- floatingIPDB = (ConcurrentMap<String, NeutronFloatingIP>) this.clusterContainerService\r
- .getCache("neutronFloatingIPs");\r
- if (floatingIPDB == null) {\r
- logger.error("Cache couldn't be retrieved for Neutron FloatingIPs");\r
- }\r
- logger.debug("Cache was successfully retrieved for Neutron FloatingIPs");\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void destroyCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterMger, can't destroy cache");\r
- return;\r
- }\r
- logger.debug("Destroying Cache for HostTracker");\r
- this.clusterContainerService.destroyCache("neutronFloatingIPs");\r
- }\r
-\r
- private void startUp() {\r
- allocateCache();\r
- retrieveCache();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when all the required\r
- * dependencies are satisfied\r
- *\r
- */\r
- void init(Component c) {\r
- Dictionary<?, ?> props = c.getServiceProperties();\r
- if (props != null) {\r
- this.containerName = (String) props.get("containerName");\r
- logger.debug("Running containerName: {}", this.containerName);\r
- } else {\r
- // In the Global instance case the containerName is empty\r
- this.containerName = "";\r
- }\r
- startUp();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when at least one dependency\r
- * become unsatisfied or when the component is shutting down because for\r
- * example bundle is being stopped.\r
- *\r
- */\r
- void destroy() {\r
- destroyCache();\r
- }\r
-\r
- /**\r
- * Function called by dependency manager after "init ()" is called and after\r
- * the services provided by the class are registered in the service registry\r
- *\r
- */\r
- void start() {\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager before the services exported by\r
- * the component are unregistered, this will be followed by a "destroy ()"\r
- * calls\r
- *\r
- */\r
- void stop() {\r
- }\r
-\r
- // this method uses reflection to update an object from it's delta.\r
-\r
- private boolean overwrite(Object target, Object delta) {\r
- Method[] methods = target.getClass().getMethods();\r
-\r
- for(Method toMethod: methods){\r
- if(toMethod.getDeclaringClass().equals(target.getClass())\r
- && toMethod.getName().startsWith("set")){\r
-\r
- String toName = toMethod.getName();\r
- String fromName = toName.replace("set", "get");\r
-\r
- try {\r
- Method fromMethod = delta.getClass().getMethod(fromName);\r
- Object value = fromMethod.invoke(delta, (Object[])null);\r
- if(value != null){\r
- toMethod.invoke(target, value);\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- // IfNBFloatingIPCRUD interface methods\r
-\r
- public boolean floatingIPExists(String uuid) {\r
- return floatingIPDB.containsKey(uuid);\r
- }\r
-\r
- public NeutronFloatingIP getFloatingIP(String uuid) {\r
- if (!floatingIPExists(uuid))\r
- return null;\r
- return floatingIPDB.get(uuid);\r
- }\r
-\r
- public List<NeutronFloatingIP> getAllFloatingIPs() {\r
- Set<NeutronFloatingIP> allIPs = new HashSet<NeutronFloatingIP>();\r
- for (Entry<String, NeutronFloatingIP> entry : floatingIPDB.entrySet()) {\r
- NeutronFloatingIP floatingip = entry.getValue();\r
- allIPs.add(floatingip);\r
- }\r
- logger.debug("Exiting getAllFloatingIPs, Found {} FloatingIPs", allIPs.size());\r
- List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();\r
- ans.addAll(allIPs);\r
- return ans;\r
- }\r
-\r
- public boolean addFloatingIP(NeutronFloatingIP input) {\r
- INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
- INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-\r
- if (floatingIPExists(input.getID()))\r
- return false;\r
- //if floating_ip_address isn't there, allocate from the subnet pool\r
- NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(input.getFloatingNetworkUUID()).getSubnets().get(0));\r
- if (input.getFloatingIPAddress() == null)\r
- input.setFloatingIPAddress(subnet.getLowAddr());\r
- subnet.allocateIP(input.getFloatingIPAddress());\r
-\r
- //if port_id is there, bind port to this floating ip\r
- if (input.getPortUUID() != null) {\r
- NeutronPort port = portCRUD.getPort(input.getPortUUID());\r
- port.addFloatingIP(input.getFixedIPAddress(), input);\r
- }\r
-\r
- floatingIPDB.putIfAbsent(input.getID(), input);\r
- return true;\r
- }\r
-\r
- public boolean removeFloatingIP(String uuid) {\r
- INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
- INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-\r
- if (!floatingIPExists(uuid))\r
- return false;\r
- NeutronFloatingIP floatIP = getFloatingIP(uuid);\r
- //if floating_ip_address isn't there, allocate from the subnet pool\r
- NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(floatIP.getFloatingNetworkUUID()).getSubnets().get(0));\r
- subnet.releaseIP(floatIP.getFloatingIPAddress());\r
- if (floatIP.getPortUUID() != null) {\r
- NeutronPort port = portCRUD.getPort(floatIP.getPortUUID());\r
- port.removeFloatingIP(floatIP.getFixedIPAddress());\r
- }\r
- floatingIPDB.remove(uuid);\r
- return true;\r
- }\r
-\r
- public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta) {\r
- INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
-\r
- if (!floatingIPExists(uuid))\r
- return false;\r
- NeutronFloatingIP target = floatingIPDB.get(uuid);\r
- if (target.getPortUUID() != null) {\r
- NeutronPort port = portCRUD.getPort(target.getPortUUID());\r
- port.removeFloatingIP(target.getFixedIPAddress());\r
- }\r
-\r
- //if port_id is there, bind port to this floating ip\r
- if (delta.getPortUUID() != null) {\r
- NeutronPort port = portCRUD.getPort(delta.getPortUUID());\r
- port.addFloatingIP(delta.getFixedIPAddress(), delta);\r
- }\r
-\r
- target.setPortUUID(delta.getPortUUID());\r
- target.setFixedIPAddress(delta.getFixedIPAddress());\r
- return true;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronFloatingIPInterface implements INeutronFloatingIPCRUD {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronFloatingIPInterface.class);
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private ConcurrentMap<String, NeutronFloatingIP> floatingIPDB;
+
+ // methods needed for creating caches
+
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ this.clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (this.clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ this.clusterContainerService = null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron FloatingIPs");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronFloatingIPs",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for NeutronFloatingIps");
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron FloatingIPs");
+ floatingIPDB = (ConcurrentMap<String, NeutronFloatingIP>) this.clusterContainerService
+ .getCache("neutronFloatingIPs");
+ if (floatingIPDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron FloatingIPs");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron FloatingIPs");
+ }
+
+ @SuppressWarnings("deprecation")
+ private void destroyCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for HostTracker");
+ this.clusterContainerService.destroyCache("neutronFloatingIPs");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ this.containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", this.containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ this.containerName = "";
+ }
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for(Method toMethod: methods){
+ if(toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")){
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[])null);
+ if(value != null){
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // IfNBFloatingIPCRUD interface methods
+
+ public boolean floatingIPExists(String uuid) {
+ return floatingIPDB.containsKey(uuid);
+ }
+
+ public NeutronFloatingIP getFloatingIP(String uuid) {
+ if (!floatingIPExists(uuid))
+ return null;
+ return floatingIPDB.get(uuid);
+ }
+
+ public List<NeutronFloatingIP> getAllFloatingIPs() {
+ Set<NeutronFloatingIP> allIPs = new HashSet<NeutronFloatingIP>();
+ for (Entry<String, NeutronFloatingIP> entry : floatingIPDB.entrySet()) {
+ NeutronFloatingIP floatingip = entry.getValue();
+ allIPs.add(floatingip);
+ }
+ logger.debug("Exiting getAllFloatingIPs, Found {} FloatingIPs", allIPs.size());
+ List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();
+ ans.addAll(allIPs);
+ return ans;
+ }
+
+ public boolean addFloatingIP(NeutronFloatingIP input) {
+ INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+ INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+
+ if (floatingIPExists(input.getID()))
+ return false;
+ //if floating_ip_address isn't there, allocate from the subnet pool
+ NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(input.getFloatingNetworkUUID()).getSubnets().get(0));
+ if (input.getFloatingIPAddress() == null)
+ input.setFloatingIPAddress(subnet.getLowAddr());
+ subnet.allocateIP(input.getFloatingIPAddress());
+
+ //if port_id is there, bind port to this floating ip
+ if (input.getPortUUID() != null) {
+ NeutronPort port = portCRUD.getPort(input.getPortUUID());
+ port.addFloatingIP(input.getFixedIPAddress(), input);
+ }
+
+ floatingIPDB.putIfAbsent(input.getID(), input);
+ return true;
+ }
+
+ public boolean removeFloatingIP(String uuid) {
+ INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+ INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+
+ if (!floatingIPExists(uuid))
+ return false;
+ NeutronFloatingIP floatIP = getFloatingIP(uuid);
+ //if floating_ip_address isn't there, allocate from the subnet pool
+ NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(floatIP.getFloatingNetworkUUID()).getSubnets().get(0));
+ subnet.releaseIP(floatIP.getFloatingIPAddress());
+ if (floatIP.getPortUUID() != null) {
+ NeutronPort port = portCRUD.getPort(floatIP.getPortUUID());
+ port.removeFloatingIP(floatIP.getFixedIPAddress());
+ }
+ floatingIPDB.remove(uuid);
+ return true;
+ }
+
+ public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta) {
+ INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+
+ if (!floatingIPExists(uuid))
+ return false;
+ NeutronFloatingIP target = floatingIPDB.get(uuid);
+ if (target.getPortUUID() != null) {
+ NeutronPort port = portCRUD.getPort(target.getPortUUID());
+ port.removeFloatingIP(target.getFixedIPAddress());
+ }
+
+ //if port_id is there, bind port to this floating ip
+ if (delta.getPortUUID() != null) {
+ NeutronPort port = portCRUD.getPort(delta.getPortUUID());
+ port.addFloatingIP(delta.getFixedIPAddress(), delta);
+ }
+
+ target.setPortUUID(delta.getPortUUID());
+ target.setFixedIPAddress(delta.getFixedIPAddress());
+ return true;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronNetworkInterface implements INeutronNetworkCRUD {\r
- private static final Logger logger = LoggerFactory.getLogger(NeutronNetworkInterface.class);\r
- private String containerName = null;\r
-\r
- private ConcurrentMap<String, NeutronNetwork> networkDB;\r
- private IClusterContainerServices clusterContainerService = null;\r
-\r
- // methods needed for creating caches\r
-\r
- void setClusterContainerService(IClusterContainerServices s) {\r
- logger.debug("Cluster Service set");\r
- this.clusterContainerService = s;\r
- }\r
-\r
- void unsetClusterContainerService(IClusterContainerServices s) {\r
- if (this.clusterContainerService == s) {\r
- logger.debug("Cluster Service removed!");\r
- this.clusterContainerService = null;\r
- }\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void allocateCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't create cache");\r
- return;\r
- }\r
- logger.debug("Creating Cache for Neutron Networks");\r
- try {\r
- // neutron caches\r
- this.clusterContainerService.createCache("neutronNetworks",\r
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
- } catch (CacheConfigException cce) {\r
- logger.error("Cache couldn't be created for Neutron Networks - check cache mode");\r
- } catch (CacheExistException cce) {\r
- logger.error("Cache for Neutron Networks already exists, destroy and recreate");\r
- }\r
- logger.debug("Cache successfully created for Neutron Networks");\r
- }\r
-\r
- @SuppressWarnings({ "unchecked", "deprecation" })\r
- private void retrieveCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
- return;\r
- }\r
- logger.debug("Retrieving cache for Neutron Networks");\r
- networkDB = (ConcurrentMap<String, NeutronNetwork>) this.clusterContainerService.getCache("neutronNetworks");\r
- if (networkDB == null) {\r
- logger.error("Cache couldn't be retrieved for Neutron Networks");\r
- }\r
- logger.debug("Cache was successfully retrieved for Neutron Networks");\r
- }\r
-\r
- private void startUp() {\r
- allocateCache();\r
- retrieveCache();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when all the required\r
- * dependencies are satisfied\r
- *\r
- */\r
- void init(Component c) {\r
- Dictionary<?, ?> props = c.getServiceProperties();\r
- if (props != null) {\r
- this.containerName = (String) props.get("containerName");\r
- logger.debug("Running containerName: {}", this.containerName);\r
- } else {\r
- // In the Global instance case the containerName is empty\r
- this.containerName = "";\r
- }\r
- startUp();\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void destroyCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterMger, can't destroy cache");\r
- return;\r
- }\r
- logger.debug("Destroying Cache for Neutron Networks");\r
- this.clusterContainerService.destroyCache("Neutron Networks");\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when at least one dependency\r
- * become unsatisfied or when the component is shutting down because for\r
- * example bundle is being stopped.\r
- *\r
- */\r
- void destroy() {\r
- destroyCache();\r
- }\r
-\r
- /**\r
- * Function called by dependency manager after "init ()" is called and after\r
- * the services provided by the class are registered in the service registry\r
- *\r
- */\r
- void start() {\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager before the services exported by\r
- * the component are unregistered, this will be followed by a "destroy ()"\r
- * calls\r
- *\r
- */\r
- void stop() {\r
- }\r
-\r
- // this method uses reflection to update an object from it's delta.\r
-\r
- private boolean overwrite(Object target, Object delta) {\r
- Method[] methods = target.getClass().getMethods();\r
-\r
- for(Method toMethod: methods){\r
- if(toMethod.getDeclaringClass().equals(target.getClass())\r
- && toMethod.getName().startsWith("set")){\r
-\r
- String toName = toMethod.getName();\r
- String fromName = toName.replace("set", "get");\r
-\r
- try {\r
- Method fromMethod = delta.getClass().getMethod(fromName);\r
- Object value = fromMethod.invoke(delta, (Object[])null);\r
- if(value != null){\r
- toMethod.invoke(target, value);\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- // IfNBNetworkCRUD methods\r
-\r
- public boolean networkExists(String uuid) {\r
- return networkDB.containsKey(uuid);\r
- }\r
-\r
- public NeutronNetwork getNetwork(String uuid) {\r
- if (!networkExists(uuid))\r
- return null;\r
- return networkDB.get(uuid);\r
- }\r
-\r
- public List<NeutronNetwork> getAllNetworks() {\r
- Set<NeutronNetwork> allNetworks = new HashSet<NeutronNetwork>();\r
- for (Entry<String, NeutronNetwork> entry : networkDB.entrySet()) {\r
- NeutronNetwork network = entry.getValue();\r
- allNetworks.add(network);\r
- }\r
- logger.debug("Exiting getAllNetworks, Found {} OpenStackNetworks", allNetworks.size());\r
- List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();\r
- ans.addAll(allNetworks);\r
- return ans;\r
- }\r
-\r
- public boolean addNetwork(NeutronNetwork input) {\r
- if (networkExists(input.getID()))\r
- return false;\r
- networkDB.putIfAbsent(input.getID(), input);\r
- //TODO: add code to find INeutronNetworkAware services and call newtorkCreated on them\r
- return true;\r
- }\r
-\r
- public boolean removeNetwork(String uuid) {\r
- if (!networkExists(uuid))\r
- return false;\r
- networkDB.remove(uuid);\r
- //TODO: add code to find INeutronNetworkAware services and call newtorkDeleted on them\r
- return true;\r
- }\r
-\r
- public boolean updateNetwork(String uuid, NeutronNetwork delta) {\r
- if (!networkExists(uuid))\r
- return false;\r
- NeutronNetwork target = networkDB.get(uuid);\r
- return overwrite(target, delta);\r
- }\r
-\r
- public boolean networkInUse(String netUUID) {\r
- if (!networkExists(netUUID))\r
- return true;\r
- NeutronNetwork target = networkDB.get(netUUID);\r
- if (target.getPortsOnNetwork().size() > 0)\r
- return true;\r
- return false;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronNetworkInterface implements INeutronNetworkCRUD {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronNetworkInterface.class);
+ private String containerName = null;
+
+ private ConcurrentMap<String, NeutronNetwork> networkDB;
+ private IClusterContainerServices clusterContainerService = null;
+
+ // methods needed for creating caches
+
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ this.clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (this.clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ this.clusterContainerService = null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron Networks");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronNetworks",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron Networks - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron Networks already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron Networks");
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+ logger.debug("Retrieving cache for Neutron Networks");
+ networkDB = (ConcurrentMap<String, NeutronNetwork>) this.clusterContainerService.getCache("neutronNetworks");
+ if (networkDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron Networks");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron Networks");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ this.containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", this.containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ this.containerName = "";
+ }
+ startUp();
+ }
+
+ @SuppressWarnings("deprecation")
+ private void destroyCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for Neutron Networks");
+ this.clusterContainerService.destroyCache("Neutron Networks");
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for(Method toMethod: methods){
+ if(toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")){
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[])null);
+ if(value != null){
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // IfNBNetworkCRUD methods
+
+ public boolean networkExists(String uuid) {
+ return networkDB.containsKey(uuid);
+ }
+
+ public NeutronNetwork getNetwork(String uuid) {
+ if (!networkExists(uuid))
+ return null;
+ return networkDB.get(uuid);
+ }
+
+ public List<NeutronNetwork> getAllNetworks() {
+ Set<NeutronNetwork> allNetworks = new HashSet<NeutronNetwork>();
+ for (Entry<String, NeutronNetwork> entry : networkDB.entrySet()) {
+ NeutronNetwork network = entry.getValue();
+ allNetworks.add(network);
+ }
+ logger.debug("Exiting getAllNetworks, Found {} OpenStackNetworks", allNetworks.size());
+ List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();
+ ans.addAll(allNetworks);
+ return ans;
+ }
+
+ public boolean addNetwork(NeutronNetwork input) {
+ if (networkExists(input.getID()))
+ return false;
+ networkDB.putIfAbsent(input.getID(), input);
+ //TODO: add code to find INeutronNetworkAware services and call newtorkCreated on them
+ return true;
+ }
+
+ public boolean removeNetwork(String uuid) {
+ if (!networkExists(uuid))
+ return false;
+ networkDB.remove(uuid);
+ //TODO: add code to find INeutronNetworkAware services and call newtorkDeleted on them
+ return true;
+ }
+
+ public boolean updateNetwork(String uuid, NeutronNetwork delta) {
+ if (!networkExists(uuid))
+ return false;
+ NeutronNetwork target = networkDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ public boolean networkInUse(String netUUID) {
+ if (!networkExists(netUUID))
+ return true;
+ NeutronNetwork target = networkDB.get(netUUID);
+ if (target.getPortsOnNetwork().size() > 0)
+ return true;
+ return false;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronPortInterface implements INeutronPortCRUD {\r
- private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class);\r
- private String containerName = null;\r
-\r
- private IClusterContainerServices clusterContainerService = null;\r
- private ConcurrentMap<String, NeutronPort> portDB;\r
-\r
- // methods needed for creating caches\r
-\r
- void setClusterContainerService(IClusterContainerServices s) {\r
- logger.debug("Cluster Service set");\r
- this.clusterContainerService = s;\r
- }\r
-\r
- void unsetClusterContainerService(IClusterContainerServices s) {\r
- if (this.clusterContainerService == s) {\r
- logger.debug("Cluster Service removed!");\r
- this.clusterContainerService = null;\r
- }\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void allocateCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't create cache");\r
- return;\r
- }\r
- logger.debug("Creating Cache for OpenDOVE");\r
- try {\r
- // neutron caches\r
- this.clusterContainerService.createCache("neutronPorts",\r
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
- } catch (CacheConfigException cce) {\r
- logger.error("Cache couldn't be created for OpenDOVE - check cache mode");\r
- } catch (CacheExistException cce) {\r
- logger.error("Cache for OpenDOVE already exists, destroy and recreate");\r
- }\r
- logger.debug("Cache successfully created for OpenDOVE");\r
- }\r
-\r
- @SuppressWarnings({ "unchecked", "deprecation" })\r
- private void retrieveCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
- return;\r
- }\r
-\r
- logger.debug("Retrieving cache for Neutron Ports");\r
- portDB = (ConcurrentMap<String, NeutronPort>) this.clusterContainerService\r
- .getCache("neutronPorts");\r
- if (portDB == null) {\r
- logger.error("Cache couldn't be retrieved for Neutron Ports");\r
- }\r
- logger.debug("Cache was successfully retrieved for Neutron Ports");\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void destroyCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterMger, can't destroy cache");\r
- return;\r
- }\r
- logger.debug("Destroying Cache for HostTracker");\r
- this.clusterContainerService.destroyCache("neutronPorts");\r
- }\r
-\r
- private void startUp() {\r
- allocateCache();\r
- retrieveCache();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when all the required\r
- * dependencies are satisfied\r
- *\r
- */\r
- void init(Component c) {\r
- Dictionary<?, ?> props = c.getServiceProperties();\r
- if (props != null) {\r
- this.containerName = (String) props.get("containerName");\r
- logger.debug("Running containerName: {}", this.containerName);\r
- } else {\r
- // In the Global instance case the containerName is empty\r
- this.containerName = "";\r
- }\r
- startUp();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when at least one dependency\r
- * become unsatisfied or when the component is shutting down because for\r
- * example bundle is being stopped.\r
- *\r
- */\r
- void destroy() {\r
- destroyCache();\r
- }\r
-\r
- /**\r
- * Function called by dependency manager after "init ()" is called and after\r
- * the services provided by the class are registered in the service registry\r
- *\r
- */\r
- void start() {\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager before the services exported by\r
- * the component are unregistered, this will be followed by a "destroy ()"\r
- * calls\r
- *\r
- */\r
- void stop() {\r
- }\r
-\r
- // this method uses reflection to update an object from it's delta.\r
-\r
- private boolean overwrite(Object target, Object delta) {\r
- Method[] methods = target.getClass().getMethods();\r
-\r
- for(Method toMethod: methods){\r
- if(toMethod.getDeclaringClass().equals(target.getClass())\r
- && toMethod.getName().startsWith("set")){\r
-\r
- String toName = toMethod.getName();\r
- String fromName = toName.replace("set", "get");\r
-\r
- try {\r
- Method fromMethod = delta.getClass().getMethod(fromName);\r
- Object value = fromMethod.invoke(delta, (Object[])null);\r
- if(value != null){\r
- toMethod.invoke(target, value);\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- // IfNBPortCRUD methods\r
-\r
- public boolean portExists(String uuid) {\r
- return portDB.containsKey(uuid);\r
- }\r
-\r
- public NeutronPort getPort(String uuid) {\r
- if (!portExists(uuid))\r
- return null;\r
- return portDB.get(uuid);\r
- }\r
-\r
- public List<NeutronPort> getAllPorts() {\r
- Set<NeutronPort> allPorts = new HashSet<NeutronPort>();\r
- for (Entry<String, NeutronPort> entry : portDB.entrySet()) {\r
- NeutronPort port = entry.getValue();\r
- allPorts.add(port);\r
- }\r
- logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size());\r
- List<NeutronPort> ans = new ArrayList<NeutronPort>();\r
- ans.addAll(allPorts);\r
- return ans;\r
- }\r
-\r
- public boolean addPort(NeutronPort input) {\r
- if (portExists(input.getID()))\r
- return false;\r
- portDB.putIfAbsent(input.getID(), input);\r
- // if there are no fixed IPs, allocate one for each subnet in the network\r
- INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- if (input.getFixedIPs().size() == 0) {\r
- List<Neutron_IPs> list = input.getFixedIPs();\r
- Iterator<NeutronSubnet> subnetIterator = systemCRUD.getAllSubnets().iterator();\r
- while (subnetIterator.hasNext()) {\r
- NeutronSubnet subnet = subnetIterator.next();\r
- if (subnet.getNetworkUUID().equals(input.getNetworkUUID()))\r
- list.add(new Neutron_IPs(subnet.getID()));\r
- }\r
- }\r
- Iterator<Neutron_IPs> fixedIPIterator = input.getFixedIPs().iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
- if (ip.getIpAddress() == null)\r
- ip.setIpAddress(subnet.getLowAddr());\r
- if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
- subnet.allocateIP(ip.getIpAddress());\r
- }\r
- else {\r
- subnet.setGatewayIPAllocated();\r
- }\r
- subnet.addPort(input);\r
- }\r
- INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-\r
- NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());\r
- network.addPort(input);\r
- return true;\r
- }\r
-\r
- public boolean removePort(String uuid) {\r
- if (!portExists(uuid))\r
- return false;\r
- NeutronPort port = getPort(uuid);\r
- portDB.remove(uuid);\r
- INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
- INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
-\r
- NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());\r
- network.removePort(port);\r
- Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
- if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
- subnet.releaseIP(ip.getIpAddress());\r
- }\r
- else {\r
- subnet.resetGatewayIPAllocated();\r
- }\r
- subnet.removePort(port);\r
- }\r
- return true;\r
- }\r
-\r
- public boolean updatePort(String uuid, NeutronPort delta) {\r
- if (!portExists(uuid))\r
- return false;\r
- NeutronPort target = portDB.get(uuid);\r
- // remove old Fixed_IPs\r
- NeutronPort port = getPort(uuid);\r
- INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
- subnet.releaseIP(ip.getIpAddress());\r
- }\r
-\r
- // allocate new Fixed_IPs\r
- fixedIPIterator = delta.getFixedIPs().iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
- if (ip.getIpAddress() == null)\r
- ip.setIpAddress(subnet.getLowAddr());\r
- subnet.allocateIP(ip.getIpAddress());\r
- }\r
- return overwrite(target, delta);\r
- }\r
-\r
- public boolean macInUse(String macAddress) {\r
- List<NeutronPort> ports = getAllPorts();\r
- Iterator<NeutronPort> portIterator = ports.iterator();\r
- while (portIterator.hasNext()) {\r
- NeutronPort port = portIterator.next();\r
- if (macAddress.equalsIgnoreCase(port.getMacAddress()))\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- public NeutronPort getGatewayPort(String subnetUUID) {\r
- INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);\r
- Iterator<NeutronPort> portIterator = getAllPorts().iterator();\r
- while (portIterator.hasNext()) {\r
- NeutronPort port = portIterator.next();\r
- List<Neutron_IPs> fixedIPs = port.getFixedIPs();\r
- if (fixedIPs.size() == 1) {\r
- if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress()))\r
- return port;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronPortInterface implements INeutronPortCRUD {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class);
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private ConcurrentMap<String, NeutronPort> portDB;
+
+ // methods needed for creating caches
+
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ clusterContainerService = null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void allocateCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for OpenDOVE");
+ try {
+ // neutron caches
+ clusterContainerService.createCache("neutronPorts",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for OpenDOVE - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for OpenDOVE already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for OpenDOVE");
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron Ports");
+ portDB = (ConcurrentMap<String, NeutronPort>) clusterContainerService
+ .getCache("neutronPorts");
+ if (portDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron Ports");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron Ports");
+ }
+
+ @SuppressWarnings("deprecation")
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for HostTracker");
+ clusterContainerService.destroyCache("neutronPorts");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ containerName = "";
+ }
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for(Method toMethod: methods){
+ if(toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")){
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[])null);
+ if(value != null){
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // IfNBPortCRUD methods
+
+ @Override
+ public boolean portExists(String uuid) {
+ return portDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronPort getPort(String uuid) {
+ if (!portExists(uuid)) {
+ return null;
+ }
+ return portDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronPort> getAllPorts() {
+ Set<NeutronPort> allPorts = new HashSet<NeutronPort>();
+ for (Entry<String, NeutronPort> entry : portDB.entrySet()) {
+ NeutronPort port = entry.getValue();
+ allPorts.add(port);
+ }
+ logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size());
+ List<NeutronPort> ans = new ArrayList<NeutronPort>();
+ ans.addAll(allPorts);
+ return ans;
+ }
+
+ @Override
+ public boolean addPort(NeutronPort input) {
+ if (portExists(input.getID())) {
+ return false;
+ }
+ portDB.putIfAbsent(input.getID(), input);
+ // if there are no fixed IPs, allocate one for each subnet in the network
+ INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (input.getFixedIPs().size() == 0) {
+ List<Neutron_IPs> list = input.getFixedIPs();
+ Iterator<NeutronSubnet> subnetIterator = systemCRUD.getAllSubnets().iterator();
+ while (subnetIterator.hasNext()) {
+ NeutronSubnet subnet = subnetIterator.next();
+ if (subnet.getNetworkUUID().equals(input.getNetworkUUID())) {
+ list.add(new Neutron_IPs(subnet.getID()));
+ }
+ }
+ }
+ Iterator<Neutron_IPs> fixedIPIterator = input.getFixedIPs().iterator();
+ while (fixedIPIterator.hasNext()) {
+ Neutron_IPs ip = fixedIPIterator.next();
+ NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+ if (ip.getIpAddress() == null) {
+ ip.setIpAddress(subnet.getLowAddr());
+ }
+ if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {
+ subnet.allocateIP(ip.getIpAddress());
+ }
+ else {
+ subnet.setGatewayIPAllocated();
+ }
+ subnet.addPort(input);
+ }
+ INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+
+ NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());
+ network.addPort(input);
+ return true;
+ }
+
+ @Override
+ public boolean removePort(String uuid) {
+ if (!portExists(uuid)) {
+ return false;
+ }
+ NeutronPort port = getPort(uuid);
+ portDB.remove(uuid);
+ INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+ INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+
+ NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());
+ network.removePort(port);
+ Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();
+ while (fixedIPIterator.hasNext()) {
+ Neutron_IPs ip = fixedIPIterator.next();
+ NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+ if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {
+ subnet.releaseIP(ip.getIpAddress());
+ }
+ else {
+ subnet.resetGatewayIPAllocated();
+ }
+ subnet.removePort(port);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updatePort(String uuid, NeutronPort delta) {
+ if (!portExists(uuid)) {
+ return false;
+ }
+ NeutronPort target = portDB.get(uuid);
+ // remove old Fixed_IPs
+ if (delta.getFixedIPs() != null) {
+ NeutronPort port = getPort(uuid);
+ INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ for (Neutron_IPs ip: port.getFixedIPs()) {
+ NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+ subnet.releaseIP(ip.getIpAddress());
+ }
+
+ // allocate new Fixed_IPs
+ for (Neutron_IPs ip: delta.getFixedIPs()) {
+ NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());
+ if (ip.getIpAddress() == null) {
+ ip.setIpAddress(subnet.getLowAddr());
+ }
+ subnet.allocateIP(ip.getIpAddress());
+ }
+ }
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean macInUse(String macAddress) {
+ List<NeutronPort> ports = getAllPorts();
+ Iterator<NeutronPort> portIterator = ports.iterator();
+ while (portIterator.hasNext()) {
+ NeutronPort port = portIterator.next();
+ if (macAddress.equalsIgnoreCase(port.getMacAddress())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public NeutronPort getGatewayPort(String subnetUUID) {
+ INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);
+ Iterator<NeutronPort> portIterator = getAllPorts().iterator();
+ while (portIterator.hasNext()) {
+ NeutronPort port = portIterator.next();
+ List<Neutron_IPs> fixedIPs = port.getFixedIPs();
+ if (fixedIPs.size() == 1) {
+ if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress())) {
+ return port;
+ }
+ }
+ }
+ return null;
+ }
+
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronRouterInterface implements INeutronRouterCRUD {\r
- private static final Logger logger = LoggerFactory.getLogger(NeutronRouterInterface.class);\r
- private String containerName = null;\r
-\r
- private IClusterContainerServices clusterContainerService = null;\r
- private ConcurrentMap<String, NeutronRouter> routerDB;\r
- // methods needed for creating caches\r
-\r
- void setClusterContainerService(IClusterContainerServices s) {\r
- logger.debug("Cluster Service set");\r
- this.clusterContainerService = s;\r
- }\r
-\r
- void unsetClusterContainerService(IClusterContainerServices s) {\r
- if (this.clusterContainerService == s) {\r
- logger.debug("Cluster Service removed!");\r
- this.clusterContainerService = null;\r
- }\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void allocateCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't create cache");\r
- return;\r
- }\r
- logger.debug("Creating Cache for Neutron Routers");\r
- try {\r
- // neutron caches\r
- this.clusterContainerService.createCache("neutronRouters",\r
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
- } catch (CacheConfigException cce) {\r
- logger.error("Cache couldn't be created for Neutron Routers - check cache mode");\r
- } catch (CacheExistException cce) {\r
- logger.error("Cache for Neutron Routers already exists, destroy and recreate");\r
- }\r
- logger.debug("Cache successfully created for Neutron Routers");\r
- }\r
-\r
- @SuppressWarnings({ "unchecked", "deprecation" })\r
- private void retrieveCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
- return;\r
- }\r
-\r
- logger.debug("Retrieving cache for Neutron Routers");\r
- routerDB = (ConcurrentMap<String, NeutronRouter>) this.clusterContainerService\r
- .getCache("neutronRouters");\r
- if (routerDB == null) {\r
- logger.error("Cache couldn't be retrieved for Neutron Routers");\r
- }\r
- logger.debug("Cache was successfully retrieved for Neutron Routers");\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void destroyCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterMger, can't destroy cache");\r
- return;\r
- }\r
- logger.debug("Destroying Cache for HostTracker");\r
- this.clusterContainerService.destroyCache("neutronRouters");\r
- }\r
-\r
- private void startUp() {\r
- allocateCache();\r
- retrieveCache();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when all the required\r
- * dependencies are satisfied\r
- *\r
- */\r
- void init(Component c) {\r
- Dictionary<?, ?> props = c.getServiceProperties();\r
- if (props != null) {\r
- this.containerName = (String) props.get("containerName");\r
- logger.debug("Running containerName: {}", this.containerName);\r
- } else {\r
- // In the Global instance case the containerName is empty\r
- this.containerName = "";\r
- }\r
- startUp();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when at least one dependency\r
- * become unsatisfied or when the component is shutting down because for\r
- * example bundle is being stopped.\r
- *\r
- */\r
- void destroy() {\r
- destroyCache();\r
- }\r
-\r
- /**\r
- * Function called by dependency manager after "init ()" is called and after\r
- * the services provided by the class are registered in the service registry\r
- *\r
- */\r
- void start() {\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager before the services exported by\r
- * the component are unregistered, this will be followed by a "destroy ()"\r
- * calls\r
- *\r
- */\r
- void stop() {\r
- }\r
-\r
- // this method uses reflection to update an object from it's delta.\r
-\r
- private boolean overwrite(Object target, Object delta) {\r
- Method[] methods = target.getClass().getMethods();\r
-\r
- for(Method toMethod: methods){\r
- if(toMethod.getDeclaringClass().equals(target.getClass())\r
- && toMethod.getName().startsWith("set")){\r
-\r
- String toName = toMethod.getName();\r
- String fromName = toName.replace("set", "get");\r
-\r
- try {\r
- Method fromMethod = delta.getClass().getMethod(fromName);\r
- Object value = fromMethod.invoke(delta, (Object[])null);\r
- if(value != null){\r
- toMethod.invoke(target, value);\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
-\r
-\r
- // IfNBRouterCRUD Interface methods\r
-\r
- public boolean routerExists(String uuid) {\r
- return routerDB.containsKey(uuid);\r
- }\r
-\r
- public NeutronRouter getRouter(String uuid) {\r
- if (!routerExists(uuid))\r
- return null;\r
- return routerDB.get(uuid);\r
- }\r
-\r
- public List<NeutronRouter> getAllRouters() {\r
- Set<NeutronRouter> allRouters = new HashSet<NeutronRouter>();\r
- for (Entry<String, NeutronRouter> entry : routerDB.entrySet()) {\r
- NeutronRouter router = entry.getValue();\r
- allRouters.add(router);\r
- }\r
- logger.debug("Exiting getAllRouters, Found {} Routers", allRouters.size());\r
- List<NeutronRouter> ans = new ArrayList<NeutronRouter>();\r
- ans.addAll(allRouters);\r
- return ans;\r
- }\r
-\r
- public boolean addRouter(NeutronRouter input) {\r
- if (routerExists(input.getID()))\r
- return false;\r
- routerDB.putIfAbsent(input.getID(), input);\r
- return true;\r
- }\r
-\r
- public boolean removeRouter(String uuid) {\r
- if (!routerExists(uuid))\r
- return false;\r
- routerDB.remove(uuid);\r
- return true;\r
- }\r
-\r
- public boolean updateRouter(String uuid, NeutronRouter delta) {\r
- if (!routerExists(uuid))\r
- return false;\r
- NeutronRouter target = routerDB.get(uuid);\r
- return overwrite(target, delta);\r
- }\r
-\r
- public boolean routerInUse(String routerUUID) {\r
- if (!routerExists(routerUUID))\r
- return true;\r
- NeutronRouter target = routerDB.get(routerUUID);\r
- return (target.getInterfaces().size() > 0);\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronRouterInterface implements INeutronRouterCRUD {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronRouterInterface.class);
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private ConcurrentMap<String, NeutronRouter> routerDB;
+ // methods needed for creating caches
+
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ this.clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (this.clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ this.clusterContainerService = null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron Routers");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronRouters",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron Routers - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron Routers already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron Routers");
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron Routers");
+ routerDB = (ConcurrentMap<String, NeutronRouter>) this.clusterContainerService
+ .getCache("neutronRouters");
+ if (routerDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron Routers");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron Routers");
+ }
+
+ @SuppressWarnings("deprecation")
+ private void destroyCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for HostTracker");
+ this.clusterContainerService.destroyCache("neutronRouters");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ this.containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", this.containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ this.containerName = "";
+ }
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for(Method toMethod: methods){
+ if(toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")){
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[])null);
+ if(value != null){
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+ // IfNBRouterCRUD Interface methods
+
+ public boolean routerExists(String uuid) {
+ return routerDB.containsKey(uuid);
+ }
+
+ public NeutronRouter getRouter(String uuid) {
+ if (!routerExists(uuid))
+ return null;
+ return routerDB.get(uuid);
+ }
+
+ public List<NeutronRouter> getAllRouters() {
+ Set<NeutronRouter> allRouters = new HashSet<NeutronRouter>();
+ for (Entry<String, NeutronRouter> entry : routerDB.entrySet()) {
+ NeutronRouter router = entry.getValue();
+ allRouters.add(router);
+ }
+ logger.debug("Exiting getAllRouters, Found {} Routers", allRouters.size());
+ List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
+ ans.addAll(allRouters);
+ return ans;
+ }
+
+ public boolean addRouter(NeutronRouter input) {
+ if (routerExists(input.getID()))
+ return false;
+ routerDB.putIfAbsent(input.getID(), input);
+ return true;
+ }
+
+ public boolean removeRouter(String uuid) {
+ if (!routerExists(uuid))
+ return false;
+ routerDB.remove(uuid);
+ return true;
+ }
+
+ public boolean updateRouter(String uuid, NeutronRouter delta) {
+ if (!routerExists(uuid))
+ return false;
+ NeutronRouter target = routerDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ public boolean routerInUse(String routerUUID) {
+ if (!routerExists(routerUUID))
+ return true;
+ NeutronRouter target = routerDB.get(routerUUID);
+ return (target.getInterfaces().size() > 0);
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.implementation;\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.ArrayList;\r
-import java.util.Dictionary;\r
-import java.util.EnumSet;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ConcurrentMap;\r
-\r
-import org.apache.felix.dm.Component;\r
-import org.opendaylight.controller.clustering.services.CacheConfigException;\r
-import org.opendaylight.controller.clustering.services.CacheExistException;\r
-import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
-import org.opendaylight.controller.clustering.services.IClusterServices;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class NeutronSubnetInterface implements INeutronSubnetCRUD {\r
- private static final Logger logger = LoggerFactory.getLogger(NeutronSubnetInterface.class);\r
- private String containerName = null;\r
-\r
- private IClusterContainerServices clusterContainerService = null;\r
- private ConcurrentMap<String, NeutronSubnet> subnetDB;\r
-\r
- // methods needed for creating caches\r
-\r
- void setClusterContainerService(IClusterContainerServices s) {\r
- logger.debug("Cluster Service set");\r
- this.clusterContainerService = s;\r
- }\r
-\r
- void unsetClusterContainerService(IClusterContainerServices s) {\r
- if (this.clusterContainerService == s) {\r
- logger.debug("Cluster Service removed!");\r
- this.clusterContainerService = null;\r
- }\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void allocateCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't create cache");\r
- return;\r
- }\r
- logger.debug("Creating Cache for Neutron Subnets");\r
- try {\r
- // neutron caches\r
- this.clusterContainerService.createCache("neutronSubnets",\r
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
- } catch (CacheConfigException cce) {\r
- logger.error("Cache couldn't be created for Neutron Subnets - check cache mode");\r
- } catch (CacheExistException cce) {\r
- logger.error("Cache for Neutron Subnets already exists, destroy and recreate");\r
- }\r
- logger.debug("Cache successfully created for Neutron Subnets");\r
- }\r
-\r
- @SuppressWarnings({ "unchecked", "deprecation" })\r
- private void retrieveCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
- return;\r
- }\r
-\r
- logger.debug("Retrieving cache for Neutron Subnets");\r
- subnetDB = (ConcurrentMap<String, NeutronSubnet>) this.clusterContainerService\r
- .getCache("neutronSubnets");\r
- if (subnetDB == null) {\r
- logger.error("Cache couldn't be retrieved for Neutron Subnets");\r
- }\r
- logger.debug("Cache was successfully retrieved for Neutron Subnets");\r
- }\r
-\r
- @SuppressWarnings("deprecation")\r
- private void destroyCache() {\r
- if (this.clusterContainerService == null) {\r
- logger.error("un-initialized clusterMger, can't destroy cache");\r
- return;\r
- }\r
- logger.debug("Destroying Cache for HostTracker");\r
- this.clusterContainerService.destroyCache("neutronSubnets");\r
- }\r
-\r
- private void startUp() {\r
- allocateCache();\r
- retrieveCache();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when all the required\r
- * dependencies are satisfied\r
- *\r
- */\r
- void init(Component c) {\r
- Dictionary<?, ?> props = c.getServiceProperties();\r
- if (props != null) {\r
- this.containerName = (String) props.get("containerName");\r
- logger.debug("Running containerName: {}", this.containerName);\r
- } else {\r
- // In the Global instance case the containerName is empty\r
- this.containerName = "";\r
- }\r
- startUp();\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager when at least one dependency\r
- * become unsatisfied or when the component is shutting down because for\r
- * example bundle is being stopped.\r
- *\r
- */\r
- void destroy() {\r
- destroyCache();\r
- }\r
-\r
- /**\r
- * Function called by dependency manager after "init ()" is called and after\r
- * the services provided by the class are registered in the service registry\r
- *\r
- */\r
- void start() {\r
- }\r
-\r
- /**\r
- * Function called by the dependency manager before the services exported by\r
- * the component are unregistered, this will be followed by a "destroy ()"\r
- * calls\r
- *\r
- */\r
- void stop() {\r
- }\r
-\r
- // this method uses reflection to update an object from it's delta.\r
-\r
- private boolean overwrite(Object target, Object delta) {\r
- Method[] methods = target.getClass().getMethods();\r
-\r
- for(Method toMethod: methods){\r
- if(toMethod.getDeclaringClass().equals(target.getClass())\r
- && toMethod.getName().startsWith("set")){\r
-\r
- String toName = toMethod.getName();\r
- String fromName = toName.replace("set", "get");\r
-\r
- try {\r
- Method fromMethod = delta.getClass().getMethod(fromName);\r
- Object value = fromMethod.invoke(delta, (Object[])null);\r
- if(value != null){\r
- toMethod.invoke(target, value);\r
- }\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
-\r
-\r
- // IfNBSubnetCRUD methods\r
-\r
- public boolean subnetExists(String uuid) {\r
- return subnetDB.containsKey(uuid);\r
- }\r
-\r
- public NeutronSubnet getSubnet(String uuid) {\r
- if (!subnetExists(uuid))\r
- return null;\r
- return subnetDB.get(uuid);\r
- }\r
-\r
- public List<NeutronSubnet> getAllSubnets() {\r
- Set<NeutronSubnet> allSubnets = new HashSet<NeutronSubnet>();\r
- for (Entry<String, NeutronSubnet> entry : subnetDB.entrySet()) {\r
- NeutronSubnet subnet = entry.getValue();\r
- allSubnets.add(subnet);\r
- }\r
- logger.debug("Exiting getAllSubnets, Found {} OpenStackSubnets", allSubnets.size());\r
- List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();\r
- ans.addAll(allSubnets);\r
- return ans;\r
- }\r
-\r
- public boolean addSubnet(NeutronSubnet input) {\r
- String id = input.getID();\r
- if (subnetExists(id))\r
- return false;\r
- subnetDB.putIfAbsent(id, input);\r
- INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-\r
- NeutronNetwork targetNet = networkIf.getNetwork(input.getNetworkUUID());\r
- targetNet.addSubnet(id);\r
- return true;\r
- }\r
-\r
- public boolean removeSubnet(String uuid) {\r
- if (!subnetExists(uuid))\r
- return false;\r
- NeutronSubnet target = subnetDB.get(uuid);\r
- INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
-\r
- NeutronNetwork targetNet = networkIf.getNetwork(target.getNetworkUUID());\r
- targetNet.removeSubnet(uuid);\r
- subnetDB.remove(uuid);\r
- return true;\r
- }\r
-\r
- public boolean updateSubnet(String uuid, NeutronSubnet delta) {\r
- if (!subnetExists(uuid))\r
- return false;\r
- NeutronSubnet target = subnetDB.get(uuid);\r
- return overwrite(target, delta);\r
- }\r
-\r
- public boolean subnetInUse(String subnetUUID) {\r
- if (!subnetExists(subnetUUID))\r
- return true;\r
- NeutronSubnet target = subnetDB.get(subnetUUID);\r
- return (target.getPortsInSubnet().size() > 0);\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.implementation;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronSubnetInterface implements INeutronSubnetCRUD {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronSubnetInterface.class);
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private ConcurrentMap<String, NeutronSubnet> subnetDB;
+
+ // methods needed for creating caches
+
+ void setClusterContainerService(IClusterContainerServices s) {
+ logger.debug("Cluster Service set");
+ this.clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (this.clusterContainerService == s) {
+ logger.debug("Cluster Service removed!");
+ this.clusterContainerService = null;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron Subnets");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronSubnets",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron Subnets - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron Subnets already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron Subnets");
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron Subnets");
+ subnetDB = (ConcurrentMap<String, NeutronSubnet>) this.clusterContainerService
+ .getCache("neutronSubnets");
+ if (subnetDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron Subnets");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron Subnets");
+ }
+
+ @SuppressWarnings("deprecation")
+ private void destroyCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for HostTracker");
+ this.clusterContainerService.destroyCache("neutronSubnets");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ this.containerName = (String) props.get("containerName");
+ logger.debug("Running containerName: {}", this.containerName);
+ } else {
+ // In the Global instance case the containerName is empty
+ this.containerName = "";
+ }
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ destroyCache();
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ }
+
+ // this method uses reflection to update an object from it's delta.
+
+ private boolean overwrite(Object target, Object delta) {
+ Method[] methods = target.getClass().getMethods();
+
+ for(Method toMethod: methods){
+ if(toMethod.getDeclaringClass().equals(target.getClass())
+ && toMethod.getName().startsWith("set")){
+
+ String toName = toMethod.getName();
+ String fromName = toName.replace("set", "get");
+
+ try {
+ Method fromMethod = delta.getClass().getMethod(fromName);
+ Object value = fromMethod.invoke(delta, (Object[])null);
+ if(value != null){
+ toMethod.invoke(target, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+ // IfNBSubnetCRUD methods
+
+ public boolean subnetExists(String uuid) {
+ return subnetDB.containsKey(uuid);
+ }
+
+ public NeutronSubnet getSubnet(String uuid) {
+ if (!subnetExists(uuid))
+ return null;
+ return subnetDB.get(uuid);
+ }
+
+ public List<NeutronSubnet> getAllSubnets() {
+ Set<NeutronSubnet> allSubnets = new HashSet<NeutronSubnet>();
+ for (Entry<String, NeutronSubnet> entry : subnetDB.entrySet()) {
+ NeutronSubnet subnet = entry.getValue();
+ allSubnets.add(subnet);
+ }
+ logger.debug("Exiting getAllSubnets, Found {} OpenStackSubnets", allSubnets.size());
+ List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();
+ ans.addAll(allSubnets);
+ return ans;
+ }
+
+ public boolean addSubnet(NeutronSubnet input) {
+ String id = input.getID();
+ if (subnetExists(id))
+ return false;
+ subnetDB.putIfAbsent(id, input);
+ INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+
+ NeutronNetwork targetNet = networkIf.getNetwork(input.getNetworkUUID());
+ targetNet.addSubnet(id);
+ return true;
+ }
+
+ public boolean removeSubnet(String uuid) {
+ if (!subnetExists(uuid))
+ return false;
+ NeutronSubnet target = subnetDB.get(uuid);
+ INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
+
+ NeutronNetwork targetNet = networkIf.getNetwork(target.getNetworkUUID());
+ targetNet.removeSubnet(uuid);
+ subnetDB.remove(uuid);
+ return true;
+ }
+
+ public boolean updateSubnet(String uuid, NeutronSubnet delta) {
+ if (!subnetExists(uuid))
+ return false;
+ NeutronSubnet target = subnetDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ public boolean subnetInUse(String subnetUUID) {
+ if (!subnetExists(subnetUUID))
+ return true;
+ NeutronSubnet target = subnetDB.get(subnetUUID);
+ return (target.getPortsInSubnet().size() > 0);
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron FloatingIPs needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronFloatingIPAware {\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified floatingIP can be created\r
- *\r
- * @param floatingIP\r
- * instance of proposed new Neutron FloatingIP object\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the create operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canCreateFloatingIP(NeutronFloatingIP floatingIP);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a floatingIP has been created\r
- *\r
- * @param floatingIP\r
- * instance of new Neutron FloatingIP object\r
- * @return void\r
- */\r
- public void neutronFloatingIPCreated(NeutronFloatingIP floatingIP);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified floatingIP can be changed using the specified\r
- * delta\r
- *\r
- * @param delta\r
- * updates to the floatingIP object using patch semantics\r
- * @param floatingIP\r
- * instance of the Neutron FloatingIP object to be updated\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the update operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canUpdateFloatingIP(NeutronFloatingIP delta, NeutronFloatingIP original);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a floatingIP has been updated\r
- *\r
- * @param floatingIP\r
- * instance of modified Neutron FloatingIP object\r
- * @return void\r
- */\r
- public void neutronFloatingIPUpdated(NeutronFloatingIP floatingIP);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified floatingIP can be deleted\r
- *\r
- * @param floatingIP\r
- * instance of the Neutron FloatingIP object to be deleted\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the delete operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canDeleteFloatingIP(NeutronFloatingIP floatingIP);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a floatingIP has been deleted\r
- *\r
- * @param floatingIP\r
- * instance of deleted Neutron FloatingIP object\r
- * @return void\r
- */\r
- public void neutronFloatingIPDeleted(NeutronFloatingIP floatingIP);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron FloatingIPs needs to implement
+ *
+ */
+
+public interface INeutronFloatingIPAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified floatingIP can be created
+ *
+ * @param floatingIP
+ * instance of proposed new Neutron FloatingIP object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreateFloatingIP(NeutronFloatingIP floatingIP);
+
+ /**
+ * Services provide this interface method for taking action after a floatingIP has been created
+ *
+ * @param floatingIP
+ * instance of new Neutron FloatingIP object
+ * @return void
+ */
+ public void neutronFloatingIPCreated(NeutronFloatingIP floatingIP);
+
+ /**
+ * Services provide this interface method to indicate if the specified floatingIP can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the floatingIP object using patch semantics
+ * @param floatingIP
+ * instance of the Neutron FloatingIP object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdateFloatingIP(NeutronFloatingIP delta, NeutronFloatingIP original);
+
+ /**
+ * Services provide this interface method for taking action after a floatingIP has been updated
+ *
+ * @param floatingIP
+ * instance of modified Neutron FloatingIP object
+ * @return void
+ */
+ public void neutronFloatingIPUpdated(NeutronFloatingIP floatingIP);
+
+ /**
+ * Services provide this interface method to indicate if the specified floatingIP can be deleted
+ *
+ * @param floatingIP
+ * instance of the Neutron FloatingIP object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeleteFloatingIP(NeutronFloatingIP floatingIP);
+
+ /**
+ * Services provide this interface method for taking action after a floatingIP has been deleted
+ *
+ * @param floatingIP
+ * instance of deleted Neutron FloatingIP object
+ * @return void
+ */
+ public void neutronFloatingIPDeleted(NeutronFloatingIP floatingIP);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB FloatingIP objects\r
- *\r
- */\r
-\r
-public interface INeutronFloatingIPCRUD {\r
- /**\r
- * Applications call this interface method to determine if a particular\r
- * FloatingIP object exists\r
- *\r
- * @param uuid\r
- * UUID of the FloatingIP object\r
- * @return boolean\r
- */\r
-\r
- public boolean floatingIPExists(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return if a particular\r
- * FloatingIP object exists\r
- *\r
- * @param uuid\r
- * UUID of the FloatingIP object\r
- * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP.OpenStackFloatingIPs}\r
- * OpenStack FloatingIP class\r
- */\r
-\r
- public NeutronFloatingIP getFloatingIP(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return all FloatingIP objects\r
- *\r
- * @return a Set of OpenStackFloatingIPs objects\r
- */\r
-\r
- public List<NeutronFloatingIP> getAllFloatingIPs();\r
-\r
- /**\r
- * Applications call this interface method to add a FloatingIP object to the\r
- * concurrent map\r
- *\r
- * @param input\r
- * OpenStackFloatingIP object\r
- * @return boolean on whether the object was added or not\r
- */\r
-\r
- public boolean addFloatingIP(NeutronFloatingIP input);\r
-\r
- /**\r
- * Applications call this interface method to remove a FloatingIP object to the\r
- * concurrent map\r
- *\r
- * @param uuid\r
- * identifier for the FloatingIP object\r
- * @return boolean on whether the object was removed or not\r
- */\r
-\r
- public boolean removeFloatingIP(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to edit a FloatingIP object\r
- *\r
- * @param uuid\r
- * identifier of the FloatingIP object\r
- * @param delta\r
- * OpenStackFloatingIP object containing changes to apply\r
- * @return boolean on whether the object was updated or not\r
- */\r
-\r
- public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB FloatingIP objects
+ *
+ */
+
+public interface INeutronFloatingIPCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * FloatingIP object exists
+ *
+ * @param uuid
+ * UUID of the FloatingIP object
+ * @return boolean
+ */
+
+ public boolean floatingIPExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * FloatingIP object exists
+ *
+ * @param uuid
+ * UUID of the FloatingIP object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP.OpenStackFloatingIPs}
+ * OpenStack FloatingIP class
+ */
+
+ public NeutronFloatingIP getFloatingIP(String uuid);
+
+ /**
+ * Applications call this interface method to return all FloatingIP objects
+ *
+ * @return a Set of OpenStackFloatingIPs objects
+ */
+
+ public List<NeutronFloatingIP> getAllFloatingIPs();
+
+ /**
+ * Applications call this interface method to add a FloatingIP object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackFloatingIP object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addFloatingIP(NeutronFloatingIP input);
+
+ /**
+ * Applications call this interface method to remove a FloatingIP object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the FloatingIP object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeFloatingIP(String uuid);
+
+ /**
+ * Applications call this interface method to edit a FloatingIP object
+ *
+ * @param uuid
+ * identifier of the FloatingIP object
+ * @param delta
+ * OpenStackFloatingIP object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Networks needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronNetworkAware {\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified network can be created\r
- *\r
- * @param network\r
- * instance of proposed new Neutron Network object\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the create operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canCreateNetwork(NeutronNetwork network);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a network has been created\r
- *\r
- * @param network\r
- * instance of new Neutron Network object\r
- * @return void\r
- */\r
- public void neutronNetworkCreated(NeutronNetwork network);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified network can be changed using the specified\r
- * delta\r
- *\r
- * @param delta\r
- * updates to the network object using patch semantics\r
- * @param network\r
- * instance of the Neutron Network object to be updated\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the update operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a network has been updated\r
- *\r
- * @param network\r
- * instance of modified Neutron Network object\r
- * @return void\r
- */\r
- public void neutronNetworkUpdated(NeutronNetwork network);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified network can be deleted\r
- *\r
- * @param network\r
- * instance of the Neutron Network object to be deleted\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the delete operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canDeleteNetwork(NeutronNetwork network);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a network has been deleted\r
- *\r
- * @param network\r
- * instance of deleted Neutron Network object\r
- * @return void\r
- */\r
- public void neutronNetworkDeleted(NeutronNetwork network);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Networks needs to implement
+ *
+ */
+
+public interface INeutronNetworkAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified network can be created
+ *
+ * @param network
+ * instance of proposed new Neutron Network object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreateNetwork(NeutronNetwork network);
+
+ /**
+ * Services provide this interface method for taking action after a network has been created
+ *
+ * @param network
+ * instance of new Neutron Network object
+ * @return void
+ */
+ public void neutronNetworkCreated(NeutronNetwork network);
+
+ /**
+ * Services provide this interface method to indicate if the specified network can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the network object using patch semantics
+ * @param network
+ * instance of the Neutron Network object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original);
+
+ /**
+ * Services provide this interface method for taking action after a network has been updated
+ *
+ * @param network
+ * instance of modified Neutron Network object
+ * @return void
+ */
+ public void neutronNetworkUpdated(NeutronNetwork network);
+
+ /**
+ * Services provide this interface method to indicate if the specified network can be deleted
+ *
+ * @param network
+ * instance of the Neutron Network object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeleteNetwork(NeutronNetwork network);
+
+ /**
+ * Services provide this interface method for taking action after a network has been deleted
+ *
+ * @param network
+ * instance of deleted Neutron Network object
+ * @return void
+ */
+ public void neutronNetworkDeleted(NeutronNetwork network);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB network objects\r
- *\r
- */\r
-\r
-public interface INeutronNetworkCRUD {\r
- /**\r
- * Applications call this interface method to determine if a particular\r
- * Network object exists\r
- *\r
- * @param uuid\r
- * UUID of the Network object\r
- * @return boolean\r
- */\r
-\r
- public boolean networkExists(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return if a particular\r
- * Network object exists\r
- *\r
- * @param uuid\r
- * UUID of the Network object\r
- * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronNetwork.OpenStackNetworks}\r
- * OpenStack Network class\r
- */\r
-\r
- public NeutronNetwork getNetwork(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return all Network objects\r
- *\r
- * @return List of OpenStackNetworks objects\r
- */\r
-\r
- public List<NeutronNetwork> getAllNetworks();\r
-\r
- /**\r
- * Applications call this interface method to add a Network object to the\r
- * concurrent map\r
- *\r
- * @param input\r
- * OpenStackNetwork object\r
- * @return boolean on whether the object was added or not\r
- */\r
-\r
- public boolean addNetwork(NeutronNetwork input);\r
-\r
- /**\r
- * Applications call this interface method to remove a Network object to the\r
- * concurrent map\r
- *\r
- * @param uuid\r
- * identifier for the network object\r
- * @return boolean on whether the object was removed or not\r
- */\r
-\r
- public boolean removeNetwork(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to edit a Network object\r
- *\r
- * @param uuid\r
- * identifier of the network object\r
- * @param delta\r
- * OpenStackNetwork object containing changes to apply\r
- * @return boolean on whether the object was updated or not\r
- */\r
-\r
- public boolean updateNetwork(String uuid, NeutronNetwork delta);\r
-\r
- /**\r
- * Applications call this interface method to determine if a Network object\r
- * is use\r
- *\r
- * @param netUUID\r
- * identifier of the network object\r
- *\r
- * @return boolean on whether the network is in use or not\r
- */\r
-\r
- public boolean networkInUse(String netUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB network objects
+ *
+ */
+
+public interface INeutronNetworkCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * Network object exists
+ *
+ * @param uuid
+ * UUID of the Network object
+ * @return boolean
+ */
+
+ public boolean networkExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * Network object exists
+ *
+ * @param uuid
+ * UUID of the Network object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronNetwork.OpenStackNetworks}
+ * OpenStack Network class
+ */
+
+ public NeutronNetwork getNetwork(String uuid);
+
+ /**
+ * Applications call this interface method to return all Network objects
+ *
+ * @return List of OpenStackNetworks objects
+ */
+
+ public List<NeutronNetwork> getAllNetworks();
+
+ /**
+ * Applications call this interface method to add a Network object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackNetwork object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNetwork(NeutronNetwork input);
+
+ /**
+ * Applications call this interface method to remove a Network object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the network object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNetwork(String uuid);
+
+ /**
+ * Applications call this interface method to edit a Network object
+ *
+ * @param uuid
+ * identifier of the network object
+ * @param delta
+ * OpenStackNetwork object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNetwork(String uuid, NeutronNetwork delta);
+
+ /**
+ * Applications call this interface method to determine if a Network object
+ * is use
+ *
+ * @param netUUID
+ * identifier of the network object
+ *
+ * @return boolean on whether the network is in use or not
+ */
+
+ public boolean networkInUse(String netUUID);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Ports needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronPortAware {\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified port can be created\r
- *\r
- * @param port\r
- * instance of proposed new Neutron Port object\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the create operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canCreatePort(NeutronPort port);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a port has been created\r
- *\r
- * @param port\r
- * instance of new Neutron Port object\r
- * @return void\r
- */\r
- public void neutronPortCreated(NeutronPort port);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified port can be changed using the specified\r
- * delta\r
- *\r
- * @param delta\r
- * updates to the port object using patch semantics\r
- * @param port\r
- * instance of the Neutron Port object to be updated\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the update operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canUpdatePort(NeutronPort delta, NeutronPort original);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a port has been updated\r
- *\r
- * @param port\r
- * instance of modified Neutron Port object\r
- * @return void\r
- */\r
- public void neutronPortUpdated(NeutronPort port);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified port can be deleted\r
- *\r
- * @param port\r
- * instance of the Neutron Port object to be deleted\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the delete operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canDeletePort(NeutronPort port);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a port has been deleted\r
- *\r
- * @param port\r
- * instance of deleted Port Network object\r
- * @return void\r
- */\r
- public void neutronPortDeleted(NeutronPort port);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Ports needs to implement
+ *
+ */
+
+public interface INeutronPortAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified port can be created
+ *
+ * @param port
+ * instance of proposed new Neutron Port object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreatePort(NeutronPort port);
+
+ /**
+ * Services provide this interface method for taking action after a port has been created
+ *
+ * @param port
+ * instance of new Neutron Port object
+ * @return void
+ */
+ public void neutronPortCreated(NeutronPort port);
+
+ /**
+ * Services provide this interface method to indicate if the specified port can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the port object using patch semantics
+ * @param port
+ * instance of the Neutron Port object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdatePort(NeutronPort delta, NeutronPort original);
+
+ /**
+ * Services provide this interface method for taking action after a port has been updated
+ *
+ * @param port
+ * instance of modified Neutron Port object
+ * @return void
+ */
+ public void neutronPortUpdated(NeutronPort port);
+
+ /**
+ * Services provide this interface method to indicate if the specified port can be deleted
+ *
+ * @param port
+ * instance of the Neutron Port object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeletePort(NeutronPort port);
+
+ /**
+ * Services provide this interface method for taking action after a port has been deleted
+ *
+ * @param port
+ * instance of deleted Port Network object
+ * @return void
+ */
+ public void neutronPortDeleted(NeutronPort port);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB Port objects\r
- *\r
- */\r
-\r
-public interface INeutronPortCRUD {\r
- /**\r
- * Applications call this interface method to determine if a particular\r
- * Port object exists\r
- *\r
- * @param uuid\r
- * UUID of the Port object\r
- * @return boolean\r
- */\r
-\r
- public boolean portExists(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return if a particular\r
- * Port object exists\r
- *\r
- * @param uuid\r
- * UUID of the Port object\r
- * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronPort.OpenStackPorts}\r
- * OpenStack Port class\r
- */\r
-\r
- public NeutronPort getPort(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return all Port objects\r
- *\r
- * @return List of OpenStackPorts objects\r
- */\r
-\r
- public List<NeutronPort> getAllPorts();\r
-\r
- /**\r
- * Applications call this interface method to add a Port object to the\r
- * concurrent map\r
- *\r
- * @param input\r
- * OpenStackPort object\r
- * @return boolean on whether the object was added or not\r
- */\r
-\r
- public boolean addPort(NeutronPort input);\r
-\r
- /**\r
- * Applications call this interface method to remove a Port object to the\r
- * concurrent map\r
- *\r
- * @param uuid\r
- * identifier for the Port object\r
- * @return boolean on whether the object was removed or not\r
- */\r
-\r
- public boolean removePort(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to edit a Port object\r
- *\r
- * @param uuid\r
- * identifier of the Port object\r
- * @param delta\r
- * OpenStackPort object containing changes to apply\r
- * @return boolean on whether the object was updated or not\r
- */\r
-\r
- public boolean updatePort(String uuid, NeutronPort delta);\r
-\r
- /**\r
- * Applications call this interface method to see if a MAC address is in use\r
- *\r
- * @param macAddress\r
- * mac Address to be tested\r
- * @return boolean on whether the macAddress is already associated with a\r
- * port or not\r
- */\r
-\r
- public boolean macInUse(String macAddress);\r
-\r
- /**\r
- * Applications call this interface method to retrieve the port associated with\r
- * the gateway address of a subnet\r
- *\r
- * @param subnetUUID\r
- * identifier of the subnet\r
- * @return OpenStackPorts object if the port exists and null if it does not\r
- */\r
-\r
- public NeutronPort getGatewayPort(String subnetUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB Port objects
+ *
+ */
+
+public interface INeutronPortCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * Port object exists
+ *
+ * @param uuid
+ * UUID of the Port object
+ * @return boolean
+ */
+
+ public boolean portExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * Port object exists
+ *
+ * @param uuid
+ * UUID of the Port object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronPort.OpenStackPorts}
+ * OpenStack Port class
+ */
+
+ public NeutronPort getPort(String uuid);
+
+ /**
+ * Applications call this interface method to return all Port objects
+ *
+ * @return List of OpenStackPorts objects
+ */
+
+ public List<NeutronPort> getAllPorts();
+
+ /**
+ * Applications call this interface method to add a Port object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackPort object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addPort(NeutronPort input);
+
+ /**
+ * Applications call this interface method to remove a Port object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the Port object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removePort(String uuid);
+
+ /**
+ * Applications call this interface method to edit a Port object
+ *
+ * @param uuid
+ * identifier of the Port object
+ * @param delta
+ * OpenStackPort object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updatePort(String uuid, NeutronPort delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param macAddress
+ * mac Address to be tested
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean macInUse(String macAddress);
+
+ /**
+ * Applications call this interface method to retrieve the port associated with
+ * the gateway address of a subnet
+ *
+ * @param subnetUUID
+ * identifier of the subnet
+ * @return OpenStackPorts object if the port exists and null if it does not
+ */
+
+ public NeutronPort getGatewayPort(String subnetUUID);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Routers needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronRouterAware {\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified router can be created\r
- *\r
- * @param router\r
- * instance of proposed new Neutron Router object\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the create operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canCreateRouter(NeutronRouter router);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a router has been created\r
- *\r
- * @param router\r
- * instance of new Neutron Router object\r
- * @return void\r
- */\r
- public void neutronRouterCreated(NeutronRouter router);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified router can be changed using the specified\r
- * delta\r
- *\r
- * @param delta\r
- * updates to the router object using patch semantics\r
- * @param router\r
- * instance of the Neutron Router object to be updated\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the update operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canUpdateRouter(NeutronRouter delta, NeutronRouter original);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a router has been updated\r
- *\r
- * @param router\r
- * instance of modified Neutron Router object\r
- * @return void\r
- */\r
- public void neutronRouterUpdated(NeutronRouter router);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified router can be deleted\r
- *\r
- * @param router\r
- * instance of the Neutron Router object to be deleted\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the delete operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canDeleteRouter(NeutronRouter router);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a router has been deleted\r
- *\r
- * @param router\r
- * instance of deleted Router Network object\r
- * @return void\r
- */\r
- public void neutronRouterDeleted(NeutronRouter router);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified interface can be attached to the specified route\r
- *\r
- * @param router\r
- * instance of the base Neutron Router object\r
- * @param routerInterface\r
- * instance of the NeutronRouter_Interface to be attached to the router\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the attach operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canAttachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-\r
- /**\r
- * Services provide this interface method for taking action after an interface has been added to a router\r
- *\r
- * @param router\r
- * instance of the base Neutron Router object\r
- * @param routerInterface\r
- * instance of the NeutronRouter_Interface being attached to the router\r
- * @return void\r
- */\r
- public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified interface can be detached from the specified router\r
- *\r
- * @param router\r
- * instance of the base Neutron Router object\r
- * @param routerInterface\r
- * instance of the NeutronRouter_Interface to be detached to the router\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the detach operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canDetachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-\r
- /**\r
- * Services provide this interface method for taking action after an interface has been removed from a router\r
- *\r
- * @param router\r
- * instance of the base Neutron Router object\r
- * @param routerInterface\r
- * instance of the NeutronRouter_Interface being detached from the router\r
- * @return void\r
- */\r
- public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Routers needs to implement
+ *
+ */
+
+public interface INeutronRouterAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified router can be created
+ *
+ * @param router
+ * instance of proposed new Neutron Router object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreateRouter(NeutronRouter router);
+
+ /**
+ * Services provide this interface method for taking action after a router has been created
+ *
+ * @param router
+ * instance of new Neutron Router object
+ * @return void
+ */
+ public void neutronRouterCreated(NeutronRouter router);
+
+ /**
+ * Services provide this interface method to indicate if the specified router can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the router object using patch semantics
+ * @param router
+ * instance of the Neutron Router object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdateRouter(NeutronRouter delta, NeutronRouter original);
+
+ /**
+ * Services provide this interface method for taking action after a router has been updated
+ *
+ * @param router
+ * instance of modified Neutron Router object
+ * @return void
+ */
+ public void neutronRouterUpdated(NeutronRouter router);
+
+ /**
+ * Services provide this interface method to indicate if the specified router can be deleted
+ *
+ * @param router
+ * instance of the Neutron Router object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeleteRouter(NeutronRouter router);
+
+ /**
+ * Services provide this interface method for taking action after a router has been deleted
+ *
+ * @param router
+ * instance of deleted Router Network object
+ * @return void
+ */
+ public void neutronRouterDeleted(NeutronRouter router);
+
+ /**
+ * Services provide this interface method to indicate if the specified interface can be attached to the specified route
+ *
+ * @param router
+ * instance of the base Neutron Router object
+ * @param routerInterface
+ * instance of the NeutronRouter_Interface to be attached to the router
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the attach operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canAttachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);
+
+ /**
+ * Services provide this interface method for taking action after an interface has been added to a router
+ *
+ * @param router
+ * instance of the base Neutron Router object
+ * @param routerInterface
+ * instance of the NeutronRouter_Interface being attached to the router
+ * @return void
+ */
+ public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface);
+
+ /**
+ * Services provide this interface method to indicate if the specified interface can be detached from the specified router
+ *
+ * @param router
+ * instance of the base Neutron Router object
+ * @param routerInterface
+ * instance of the NeutronRouter_Interface to be detached to the router
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the detach operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDetachInterface(NeutronRouter router, NeutronRouter_Interface routerInterface);
+
+ /**
+ * Services provide this interface method for taking action after an interface has been removed from a router
+ *
+ * @param router
+ * instance of the base Neutron Router object
+ * @param routerInterface
+ * instance of the NeutronRouter_Interface being detached from the router
+ * @return void
+ */
+ public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB Router objects\r
- *\r
- */\r
-\r
-public interface INeutronRouterCRUD {\r
- /**\r
- * Applications call this interface method to determine if a particular\r
- * Router object exists\r
- *\r
- * @param uuid\r
- * UUID of the Router object\r
- * @return boolean\r
- */\r
-\r
- public boolean routerExists(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return if a particular\r
- * Router object exists\r
- *\r
- * @param uuid\r
- * UUID of the Router object\r
- * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronRouter.OpenStackRouters}\r
- * OpenStack Router class\r
- */\r
-\r
- public NeutronRouter getRouter(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return all Router objects\r
- *\r
- * @return List of OpenStackRouters objects\r
- */\r
-\r
- public List<NeutronRouter> getAllRouters();\r
-\r
- /**\r
- * Applications call this interface method to add a Router object to the\r
- * concurrent map\r
- *\r
- * @param input\r
- * OpenStackRouter object\r
- * @return boolean on whether the object was added or not\r
- */\r
-\r
- public boolean addRouter(NeutronRouter input);\r
-\r
- /**\r
- * Applications call this interface method to remove a Router object to the\r
- * concurrent map\r
- *\r
- * @param uuid\r
- * identifier for the Router object\r
- * @return boolean on whether the object was removed or not\r
- */\r
-\r
- public boolean removeRouter(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to edit a Router object\r
- *\r
- * @param uuid\r
- * identifier of the Router object\r
- * @param delta\r
- * OpenStackRouter object containing changes to apply\r
- * @return boolean on whether the object was updated or not\r
- */\r
-\r
- public boolean updateRouter(String uuid, NeutronRouter delta);\r
-\r
- /**\r
- * Applications call this interface method to check if a router is in use\r
- *\r
- * @param uuid\r
- * identifier of the Router object\r
- * @return boolean on whether the router is in use or not\r
- */\r
-\r
- public boolean routerInUse(String routerUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB Router objects
+ *
+ */
+
+public interface INeutronRouterCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * Router object exists
+ *
+ * @param uuid
+ * UUID of the Router object
+ * @return boolean
+ */
+
+ public boolean routerExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * Router object exists
+ *
+ * @param uuid
+ * UUID of the Router object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronRouter.OpenStackRouters}
+ * OpenStack Router class
+ */
+
+ public NeutronRouter getRouter(String uuid);
+
+ /**
+ * Applications call this interface method to return all Router objects
+ *
+ * @return List of OpenStackRouters objects
+ */
+
+ public List<NeutronRouter> getAllRouters();
+
+ /**
+ * Applications call this interface method to add a Router object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackRouter object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addRouter(NeutronRouter input);
+
+ /**
+ * Applications call this interface method to remove a Router object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the Router object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeRouter(String uuid);
+
+ /**
+ * Applications call this interface method to edit a Router object
+ *
+ * @param uuid
+ * identifier of the Router object
+ * @param delta
+ * OpenStackRouter object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateRouter(String uuid, NeutronRouter delta);
+
+ /**
+ * Applications call this interface method to check if a router is in use
+ *
+ * @param uuid
+ * identifier of the Router object
+ * @return boolean on whether the router is in use or not
+ */
+
+ public boolean routerInUse(String routerUUID);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-/**\r
- * This interface defines the methods a service that wishes to be aware of Neutron Subnets needs to implement\r
- *\r
- */\r
-\r
-public interface INeutronSubnetAware {\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified subnet can be created\r
- *\r
- * @param subnet\r
- * instance of proposed new Neutron Subnet object\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the create operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canCreateSubnet(NeutronSubnet subnet);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a subnet has been created\r
- *\r
- * @param subnet\r
- * instance of new Neutron Subnet object\r
- * @return void\r
- */\r
- public void neutronSubnetCreated(NeutronSubnet subnet);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified subnet can be changed using the specified\r
- * delta\r
- *\r
- * @param delta\r
- * updates to the subnet object using patch semantics\r
- * @param subnet\r
- * instance of the Neutron Subnet object to be updated\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the update operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a subnet has been updated\r
- *\r
- * @param subnet\r
- * instance of modified Neutron Subnet object\r
- * @return void\r
- */\r
- public void neutronSubnetUpdated(NeutronSubnet subnet);\r
-\r
- /**\r
- * Services provide this interface method to indicate if the specified subnet can be deleted\r
- *\r
- * @param subnet\r
- * instance of the Subnet Router object to be deleted\r
- * @return integer\r
- * the return value is understood to be a HTTP status code. A return value outside of 200 through 299\r
- * results in the delete operation being interrupted and the returned status value reflected in the\r
- * HTTP response.\r
- */\r
- public int canDeleteSubnet(NeutronSubnet subnet);\r
-\r
- /**\r
- * Services provide this interface method for taking action after a subnet has been deleted\r
- *\r
- * @param subnet\r
- * instance of deleted Router Subnet object\r
- * @return void\r
- */\r
- public void neutronSubnetDeleted(NeutronSubnet subnet);\r
-\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+/**
+ * This interface defines the methods a service that wishes to be aware of Neutron Subnets needs to implement
+ *
+ */
+
+public interface INeutronSubnetAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified subnet can be created
+ *
+ * @param subnet
+ * instance of proposed new Neutron Subnet object
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the create operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canCreateSubnet(NeutronSubnet subnet);
+
+ /**
+ * Services provide this interface method for taking action after a subnet has been created
+ *
+ * @param subnet
+ * instance of new Neutron Subnet object
+ * @return void
+ */
+ public void neutronSubnetCreated(NeutronSubnet subnet);
+
+ /**
+ * Services provide this interface method to indicate if the specified subnet can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the subnet object using patch semantics
+ * @param subnet
+ * instance of the Neutron Subnet object to be updated
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the update operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original);
+
+ /**
+ * Services provide this interface method for taking action after a subnet has been updated
+ *
+ * @param subnet
+ * instance of modified Neutron Subnet object
+ * @return void
+ */
+ public void neutronSubnetUpdated(NeutronSubnet subnet);
+
+ /**
+ * Services provide this interface method to indicate if the specified subnet can be deleted
+ *
+ * @param subnet
+ * instance of the Subnet Router object to be deleted
+ * @return integer
+ * the return value is understood to be a HTTP status code. A return value outside of 200 through 299
+ * results in the delete operation being interrupted and the returned status value reflected in the
+ * HTTP response.
+ */
+ public int canDeleteSubnet(NeutronSubnet subnet);
+
+ /**
+ * Services provide this interface method for taking action after a subnet has been deleted
+ *
+ * @param subnet
+ * instance of deleted Router Subnet object
+ * @return void
+ */
+ public void neutronSubnetDeleted(NeutronSubnet subnet);
+
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * This interface defines the methods for CRUD of NB Subnet objects\r
- *\r
- */\r
-\r
-public interface INeutronSubnetCRUD {\r
- /**\r
- * Applications call this interface method to determine if a particular\r
- * Subnet object exists\r
- *\r
- * @param uuid\r
- * UUID of the Subnet object\r
- * @return boolean\r
- */\r
-\r
- public boolean subnetExists(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return if a particular\r
- * Subnet object exists\r
- *\r
- * @param uuid\r
- * UUID of the Subnet object\r
- * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSubnet.OpenStackSubnets}\r
- * OpenStack Subnet class\r
- */\r
-\r
- public NeutronSubnet getSubnet(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to return all Subnet objects\r
- *\r
- * @return List of OpenStackSubnets objects\r
- */\r
-\r
- public List<NeutronSubnet> getAllSubnets();\r
-\r
- /**\r
- * Applications call this interface method to add a Subnet object to the\r
- * concurrent map\r
- *\r
- * @param input\r
- * OpenStackSubnet object\r
- * @return boolean on whether the object was added or not\r
- */\r
-\r
- public boolean addSubnet(NeutronSubnet input);\r
-\r
- /**\r
- * Applications call this interface method to remove a Subnet object to the\r
- * concurrent map\r
- *\r
- * @param uuid\r
- * identifier for the Subnet object\r
- * @return boolean on whether the object was removed or not\r
- */\r
-\r
- public boolean removeSubnet(String uuid);\r
-\r
- /**\r
- * Applications call this interface method to edit a Subnet object\r
- *\r
- * @param uuid\r
- * identifier of the Subnet object\r
- * @param delta\r
- * OpenStackSubnet object containing changes to apply\r
- * @return boolean on whether the object was updated or not\r
- */\r
-\r
- public boolean updateSubnet(String uuid, NeutronSubnet delta);\r
-\r
- /**\r
- * Applications call this interface method to determine if a Subnet object\r
- * is use\r
- *\r
- * @param subnetUUID\r
- * identifier of the subnet object\r
- *\r
- * @return boolean on whether the subnet is in use or not\r
- */\r
-\r
- public boolean subnetInUse(String subnetUUID);\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.List;
+
+/**
+ * This interface defines the methods for CRUD of NB Subnet objects
+ *
+ */
+
+public interface INeutronSubnetCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ * Subnet object exists
+ *
+ * @param uuid
+ * UUID of the Subnet object
+ * @return boolean
+ */
+
+ public boolean subnetExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * Subnet object exists
+ *
+ * @param uuid
+ * UUID of the Subnet object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSubnet.OpenStackSubnets}
+ * OpenStack Subnet class
+ */
+
+ public NeutronSubnet getSubnet(String uuid);
+
+ /**
+ * Applications call this interface method to return all Subnet objects
+ *
+ * @return List of OpenStackSubnets objects
+ */
+
+ public List<NeutronSubnet> getAllSubnets();
+
+ /**
+ * Applications call this interface method to add a Subnet object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackSubnet object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addSubnet(NeutronSubnet input);
+
+ /**
+ * Applications call this interface method to remove a Subnet object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the Subnet object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeSubnet(String uuid);
+
+ /**
+ * Applications call this interface method to edit a Subnet object
+ *
+ * @param uuid
+ * identifier of the Subnet object
+ * @param delta
+ * OpenStackSubnet object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateSubnet(String uuid, NeutronSubnet delta);
+
+ /**
+ * Applications call this interface method to determine if a Subnet object
+ * is use
+ *
+ * @param subnetUUID
+ * identifier of the subnet object
+ *
+ * @return boolean on whether the subnet is in use or not
+ */
+
+ public boolean subnetInUse(String subnetUUID);
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-public class NeutronCRUDInterfaces {\r
-\r
- public static INeutronNetworkCRUD getINeutronNetworkCRUD(Object o) {\r
- INeutronNetworkCRUD answer = (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, o);\r
- return answer;\r
- }\r
-\r
- public static INeutronSubnetCRUD getINeutronSubnetCRUD(Object o) {\r
- INeutronSubnetCRUD answer = (INeutronSubnetCRUD) ServiceHelper.getGlobalInstance(INeutronSubnetCRUD.class, o);\r
- return answer;\r
- }\r
-\r
- public static INeutronPortCRUD getINeutronPortCRUD(Object o) {\r
- INeutronPortCRUD answer = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, o);\r
- return answer;\r
- }\r
-\r
- public static INeutronRouterCRUD getINeutronRouterCRUD(Object o) {\r
- INeutronRouterCRUD answer = (INeutronRouterCRUD) ServiceHelper.getGlobalInstance(INeutronRouterCRUD.class, o);\r
- return answer;\r
- }\r
-\r
- public static INeutronFloatingIPCRUD getINeutronFloatingIPCRUD(Object o) {\r
- INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o);\r
- return answer;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+public class NeutronCRUDInterfaces {
+
+ public static INeutronNetworkCRUD getINeutronNetworkCRUD(Object o) {
+ INeutronNetworkCRUD answer = (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronSubnetCRUD getINeutronSubnetCRUD(Object o) {
+ INeutronSubnetCRUD answer = (INeutronSubnetCRUD) ServiceHelper.getGlobalInstance(INeutronSubnetCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronPortCRUD getINeutronPortCRUD(Object o) {
+ INeutronPortCRUD answer = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronRouterCRUD getINeutronRouterCRUD(Object o) {
+ INeutronRouterCRUD answer = (INeutronRouterCRUD) ServiceHelper.getGlobalInstance(INeutronRouterCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronFloatingIPCRUD getINeutronFloatingIPCRUD(Object o) {
+ INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o);
+ return answer;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronFloatingIP {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement (name="id")\r
- String floatingIPUUID;\r
-\r
- @XmlElement (name="floating_network_id")\r
- String floatingNetworkUUID;\r
-\r
- @XmlElement (name="port_id")\r
- String portUUID;\r
-\r
- @XmlElement (name="fixed_ip_address")\r
- String fixedIPAddress;\r
-\r
- @XmlElement (name="floating_ip_address")\r
- String floatingIPAddress;\r
-\r
- @XmlElement (name="tenant_id")\r
- String tenantUUID;\r
-\r
- public NeutronFloatingIP() {\r
- }\r
-\r
- public String getID() { return floatingIPUUID; }\r
-\r
- public String getFloatingIPUUID() {\r
- return floatingIPUUID;\r
- }\r
-\r
- public void setFloatingIPUUID(String floatingIPUUID) {\r
- this.floatingIPUUID = floatingIPUUID;\r
- }\r
-\r
- public String getFloatingNetworkUUID() {\r
- return floatingNetworkUUID;\r
- }\r
-\r
- public void setFloatingNetworkUUID(String floatingNetworkUUID) {\r
- this.floatingNetworkUUID = floatingNetworkUUID;\r
- }\r
-\r
- public String getPortUUID() {\r
- return portUUID;\r
- }\r
-\r
- public void setPortUUID(String portUUID) {\r
- this.portUUID = portUUID;\r
- }\r
-\r
- public String getFixedIPAddress() {\r
- return fixedIPAddress;\r
- }\r
-\r
- public void setFixedIPAddress(String fixedIPAddress) {\r
- this.fixedIPAddress = fixedIPAddress;\r
- }\r
-\r
- public String getFloatingIPAddress() {\r
- return floatingIPAddress;\r
- }\r
-\r
- public void setFloatingIPAddress(String floatingIPAddress) {\r
- this.floatingIPAddress = floatingIPAddress;\r
- }\r
-\r
- public String getTenantUUID() {\r
- return tenantUUID;\r
- }\r
-\r
- public void setTenantUUID(String tenantUUID) {\r
- this.tenantUUID = tenantUUID;\r
- }\r
-\r
- /**\r
- * This method copies selected fields from the object and returns them\r
- * as a new object, suitable for marshaling.\r
- *\r
- * @param fields\r
- * List of attributes to be extracted\r
- * @return an OpenStackFloatingIPs object with only the selected fields\r
- * populated\r
- */\r
-\r
- public NeutronFloatingIP extractFields(List<String> fields) {\r
- NeutronFloatingIP ans = new NeutronFloatingIP();\r
- Iterator<String> i = fields.iterator();\r
- while (i.hasNext()) {\r
- String s = i.next();\r
- if (s.equals("id"))\r
- ans.setFloatingIPUUID(this.getFloatingIPUUID());\r
- if (s.equals("floating_network_id"))\r
- ans.setFloatingNetworkUUID(this.getFloatingNetworkUUID());\r
- if (s.equals("port_id"))\r
- ans.setPortUUID(this.getPortUUID());\r
- if (s.equals("fixed_ip_address"))\r
- ans.setFixedIPAddress(this.getFixedIPAddress());\r
- if (s.equals("floating_ip_address"))\r
- ans.setFloatingIPAddress(this.getFloatingIPAddress());\r
- if (s.equals("tenant_id"))\r
- ans.setTenantUUID(this.getTenantUUID());\r
- }\r
- return ans;\r
- }\r
-\r
- public void initDefaults() {\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronFloatingIP {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement (name="id")
+ String floatingIPUUID;
+
+ @XmlElement (name="floating_network_id")
+ String floatingNetworkUUID;
+
+ @XmlElement (name="port_id")
+ String portUUID;
+
+ @XmlElement (name="fixed_ip_address")
+ String fixedIPAddress;
+
+ @XmlElement (name="floating_ip_address")
+ String floatingIPAddress;
+
+ @XmlElement (name="tenant_id")
+ String tenantUUID;
+
+ public NeutronFloatingIP() {
+ }
+
+ public String getID() { return floatingIPUUID; }
+
+ public String getFloatingIPUUID() {
+ return floatingIPUUID;
+ }
+
+ public void setFloatingIPUUID(String floatingIPUUID) {
+ this.floatingIPUUID = floatingIPUUID;
+ }
+
+ public String getFloatingNetworkUUID() {
+ return floatingNetworkUUID;
+ }
+
+ public void setFloatingNetworkUUID(String floatingNetworkUUID) {
+ this.floatingNetworkUUID = floatingNetworkUUID;
+ }
+
+ public String getPortUUID() {
+ return portUUID;
+ }
+
+ public void setPortUUID(String portUUID) {
+ this.portUUID = portUUID;
+ }
+
+ public String getFixedIPAddress() {
+ return fixedIPAddress;
+ }
+
+ public void setFixedIPAddress(String fixedIPAddress) {
+ this.fixedIPAddress = fixedIPAddress;
+ }
+
+ public String getFloatingIPAddress() {
+ return floatingIPAddress;
+ }
+
+ public void setFloatingIPAddress(String floatingIPAddress) {
+ this.floatingIPAddress = floatingIPAddress;
+ }
+
+ public String getTenantUUID() {
+ return tenantUUID;
+ }
+
+ public void setTenantUUID(String tenantUUID) {
+ this.tenantUUID = tenantUUID;
+ }
+
+ /**
+ * This method copies selected fields from the object and returns them
+ * as a new object, suitable for marshaling.
+ *
+ * @param fields
+ * List of attributes to be extracted
+ * @return an OpenStackFloatingIPs object with only the selected fields
+ * populated
+ */
+
+ public NeutronFloatingIP extractFields(List<String> fields) {
+ NeutronFloatingIP ans = new NeutronFloatingIP();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setFloatingIPUUID(this.getFloatingIPUUID());
+ }
+ if (s.equals("floating_network_id")) {
+ ans.setFloatingNetworkUUID(this.getFloatingNetworkUUID());
+ }
+ if (s.equals("port_id")) {
+ ans.setPortUUID(this.getPortUUID());
+ }
+ if (s.equals("fixed_ip_address")) {
+ ans.setFixedIPAddress(this.getFixedIPAddress());
+ }
+ if (s.equals("floating_ip_address")) {
+ ans.setFloatingIPAddress(this.getFloatingIPAddress());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setTenantUUID(this.getTenantUUID());
+ }
+ }
+ return ans;
+ }
+
+ public void initDefaults() {
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement(name = "network")\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronNetwork {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement (name="id")\r
- String networkUUID; // network UUID\r
-\r
- @XmlElement (name="name")\r
- String networkName; // name\r
-\r
- @XmlElement (defaultValue="true", name="admin_state_up")\r
- Boolean adminStateUp; // admin state up (true/false)\r
-\r
- @XmlElement (defaultValue="false", name="shared")\r
- Boolean shared; // shared network or not\r
-\r
- @XmlElement (name="tenant_id")\r
- String tenantID; // tenant for this network\r
-\r
- @XmlElement (defaultValue="false", namespace="router", name="external")\r
- Boolean routerExternal; // network external or not\r
-\r
- @XmlElement (defaultValue="flat", namespace="provider", name="network_type")\r
- String providerNetworkType; // provider network type (flat or vlan)\r
-\r
- @XmlElement (namespace="provider", name="physical_network")\r
- String providerPhysicalNetwork; // provider physical network (name)\r
-\r
- @XmlElement (namespace="provider", name="segmentation_id")\r
- String providerSegmentationID; // provide segmentation ID (vlan ID)\r
-\r
- @XmlElement (name="status")\r
- String status; // status (read-only)\r
-\r
- @XmlElement (name="subnets")\r
- List<String> subnets; // subnets (read-only)\r
-\r
- /* This attribute lists the ports associated with an instance\r
- * which is needed for determining if that instance can be deleted\r
- */\r
-\r
- List<NeutronPort> myPorts;\r
-\r
- public NeutronNetwork() {\r
- myPorts = new ArrayList<NeutronPort>();\r
- }\r
-\r
- public void initDefaults() {\r
- subnets = new ArrayList<String>();\r
- if (this.status == null)\r
- this.status = "ACTIVE";\r
- if (this.adminStateUp == null)\r
- this.adminStateUp = true;\r
- if (this.shared == null)\r
- this.shared = false;\r
- if (this.routerExternal == null)\r
- this.routerExternal = false;\r
- if (this.providerNetworkType == null)\r
- this.providerNetworkType = "flat";\r
- }\r
-\r
- public String getID() { return networkUUID; }\r
-\r
- public String getNetworkUUID() {\r
- return networkUUID;\r
- }\r
-\r
- public void setNetworkUUID(String networkUUID) {\r
- this.networkUUID = networkUUID;\r
- }\r
-\r
- public String getNetworkName() {\r
- return networkName;\r
- }\r
-\r
- public void setNetworkName(String networkName) {\r
- this.networkName = networkName;\r
- }\r
-\r
- public boolean isAdminStateUp() {\r
- return adminStateUp;\r
- }\r
-\r
- public Boolean getAdminStateUp() { return adminStateUp; }\r
-\r
- public void setAdminStateUp(boolean newValue) {\r
- this.adminStateUp = newValue;\r
- }\r
-\r
- public boolean isShared() { return shared; }\r
-\r
- public Boolean getShared() { return shared; }\r
-\r
- public void setShared(boolean newValue) {\r
- this.shared = newValue;\r
- }\r
-\r
- public String getTenantID() {\r
- return tenantID;\r
- }\r
-\r
- public void setTenantID(String tenantID) {\r
- this.tenantID = tenantID;\r
- }\r
-\r
- public boolean isRouterExternal() { return routerExternal; }\r
-\r
- public Boolean getRouterExternal() { return routerExternal; }\r
-\r
- public void setRouterExternal(boolean newValue) {\r
- this.routerExternal = newValue;\r
- }\r
-\r
- public String getProviderNetworkType() {\r
- return providerNetworkType;\r
- }\r
-\r
- public void setProviderNetworkType(String providerNetworkType) {\r
- this.providerNetworkType = providerNetworkType;\r
- }\r
-\r
- public String getProviderPhysicalNetwork() {\r
- return providerPhysicalNetwork;\r
- }\r
-\r
- public void setProviderPhysicalNetwork(String providerPhysicalNetwork) {\r
- this.providerPhysicalNetwork = providerPhysicalNetwork;\r
- }\r
-\r
- public String getProviderSegmentationID() {\r
- return providerSegmentationID;\r
- }\r
-\r
- public void setProviderSegmentationID(String providerSegmentationID) {\r
- this.providerSegmentationID = providerSegmentationID;\r
- }\r
-\r
- public String getStatus() {\r
- return status;\r
- }\r
-\r
- public void setStatus(String status) {\r
- this.status = status;\r
- }\r
-\r
- public List<String> getSubnets() {\r
- return subnets;\r
- }\r
-\r
- public void setSubnets(List<String> subnets) {\r
- this.subnets = subnets;\r
- }\r
-\r
- public void addSubnet(String uuid) {\r
- this.subnets.add(uuid);\r
- }\r
-\r
- public void removeSubnet(String uuid) {\r
- this.subnets.remove(uuid);\r
- }\r
-\r
- public List<NeutronPort> getPortsOnNetwork() {\r
- return myPorts;\r
- }\r
-\r
- public void addPort(NeutronPort port) {\r
- myPorts.add(port);\r
- }\r
-\r
- public void removePort(NeutronPort port) {\r
- myPorts.remove(port);\r
- }\r
-\r
- /**\r
- * This method copies selected fields from the object and returns them\r
- * as a new object, suitable for marshaling.\r
- *\r
- * @param fields\r
- * List of attributes to be extracted\r
- * @return an OpenStackNetworks object with only the selected fields\r
- * populated\r
- */\r
-\r
- public NeutronNetwork extractFields(List<String> fields) {\r
- NeutronNetwork ans = new NeutronNetwork();\r
- Iterator<String> i = fields.iterator();\r
- while (i.hasNext()) {\r
- String s = i.next();\r
- if (s.equals("id"))\r
- ans.setNetworkUUID(this.getNetworkUUID());\r
- if (s.equals("name"))\r
- ans.setNetworkName(this.getNetworkName());\r
- if (s.equals("admin_state_up"))\r
- ans.setAdminStateUp(this.adminStateUp);\r
- if (s.equals("status"))\r
- ans.setStatus(this.getStatus());\r
- if (s.equals("subnets")) {\r
- List<String> subnetList = new ArrayList<String>();\r
- subnetList.addAll(this.getSubnets());\r
- ans.setSubnets(subnetList);\r
- }\r
- if (s.equals("shared"))\r
- ans.setShared(this.shared);\r
- if (s.equals("tenant_id"))\r
- ans.setTenantID(this.getTenantID());\r
- }\r
- return ans;\r
- }\r
-\r
-}\r
-\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "network")
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronNetwork {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement (name="id")
+ String networkUUID; // network UUID
+
+ @XmlElement (name="name")
+ String networkName; // name
+
+ @XmlElement (defaultValue="true", name="admin_state_up")
+ Boolean adminStateUp; // admin state up (true/false)
+
+ @XmlElement (defaultValue="false", name="shared")
+ Boolean shared; // shared network or not
+
+ @XmlElement (name="tenant_id")
+ String tenantID; // tenant for this network
+
+ @XmlElement (defaultValue="false", namespace="router", name="external")
+ Boolean routerExternal; // network external or not
+
+ @XmlElement (defaultValue="flat", namespace="provider", name="network_type")
+ String providerNetworkType; // provider network type (flat or vlan)
+
+ @XmlElement (namespace="provider", name="physical_network")
+ String providerPhysicalNetwork; // provider physical network (name)
+
+ @XmlElement (namespace="provider", name="segmentation_id")
+ String providerSegmentationID; // provide segmentation ID (vlan ID)
+
+ @XmlElement (name="status")
+ String status; // status (read-only)
+
+ @XmlElement (name="subnets")
+ List<String> subnets; // subnets (read-only)
+
+ /* This attribute lists the ports associated with an instance
+ * which is needed for determining if that instance can be deleted
+ */
+
+ List<NeutronPort> myPorts;
+
+ public NeutronNetwork() {
+ myPorts = new ArrayList<NeutronPort>();
+ }
+
+ public void initDefaults() {
+ subnets = new ArrayList<String>();
+ if (status == null) {
+ status = "ACTIVE";
+ }
+ if (adminStateUp == null) {
+ adminStateUp = true;
+ }
+ if (shared == null) {
+ shared = false;
+ }
+ if (routerExternal == null) {
+ routerExternal = false;
+ }
+ if (providerNetworkType == null) {
+ providerNetworkType = "flat";
+ }
+ }
+
+ public String getID() { return networkUUID; }
+
+ public String getNetworkUUID() {
+ return networkUUID;
+ }
+
+ public void setNetworkUUID(String networkUUID) {
+ this.networkUUID = networkUUID;
+ }
+
+ public String getNetworkName() {
+ return networkName;
+ }
+
+ public void setNetworkName(String networkName) {
+ this.networkName = networkName;
+ }
+
+ public boolean isAdminStateUp() {
+ return adminStateUp;
+ }
+
+ public Boolean getAdminStateUp() { return adminStateUp; }
+
+ public void setAdminStateUp(boolean newValue) {
+ adminStateUp = newValue;
+ }
+
+ public boolean isShared() { return shared; }
+
+ public Boolean getShared() { return shared; }
+
+ public void setShared(boolean newValue) {
+ shared = newValue;
+ }
+
+ public String getTenantID() {
+ return tenantID;
+ }
+
+ public void setTenantID(String tenantID) {
+ this.tenantID = tenantID;
+ }
+
+ public boolean isRouterExternal() { return routerExternal; }
+
+ public Boolean getRouterExternal() { return routerExternal; }
+
+ public void setRouterExternal(boolean newValue) {
+ routerExternal = newValue;
+ }
+
+ public String getProviderNetworkType() {
+ return providerNetworkType;
+ }
+
+ public void setProviderNetworkType(String providerNetworkType) {
+ this.providerNetworkType = providerNetworkType;
+ }
+
+ public String getProviderPhysicalNetwork() {
+ return providerPhysicalNetwork;
+ }
+
+ public void setProviderPhysicalNetwork(String providerPhysicalNetwork) {
+ this.providerPhysicalNetwork = providerPhysicalNetwork;
+ }
+
+ public String getProviderSegmentationID() {
+ return providerSegmentationID;
+ }
+
+ public void setProviderSegmentationID(String providerSegmentationID) {
+ this.providerSegmentationID = providerSegmentationID;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public List<String> getSubnets() {
+ return subnets;
+ }
+
+ public void setSubnets(List<String> subnets) {
+ this.subnets = subnets;
+ }
+
+ public void addSubnet(String uuid) {
+ subnets.add(uuid);
+ }
+
+ public void removeSubnet(String uuid) {
+ subnets.remove(uuid);
+ }
+
+ public List<NeutronPort> getPortsOnNetwork() {
+ return myPorts;
+ }
+
+ public void addPort(NeutronPort port) {
+ myPorts.add(port);
+ }
+
+ public void removePort(NeutronPort port) {
+ myPorts.remove(port);
+ }
+
+ /**
+ * This method copies selected fields from the object and returns them
+ * as a new object, suitable for marshaling.
+ *
+ * @param fields
+ * List of attributes to be extracted
+ * @return an OpenStackNetworks object with only the selected fields
+ * populated
+ */
+
+ public NeutronNetwork extractFields(List<String> fields) {
+ NeutronNetwork ans = new NeutronNetwork();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setNetworkUUID(this.getNetworkUUID());
+ }
+ if (s.equals("name")) {
+ ans.setNetworkName(this.getNetworkName());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setAdminStateUp(adminStateUp);
+ }
+ if (s.equals("status")) {
+ ans.setStatus(this.getStatus());
+ }
+ if (s.equals("subnets")) {
+ List<String> subnetList = new ArrayList<String>();
+ subnetList.addAll(this.getSubnets());
+ ans.setSubnets(subnetList);
+ }
+ if (s.equals("shared")) {
+ ans.setShared(shared);
+ }
+ if (s.equals("tenant_id")) {
+ ans.setTenantID(this.getTenantID());
+ }
+ }
+ return ans;
+ }
+
+}
+
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronPort {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement (name="id")\r
- String portUUID;\r
-\r
- @XmlElement (name="network_id")\r
- String networkUUID;\r
-\r
- @XmlElement (name="name")\r
- String name;\r
-\r
- @XmlElement (defaultValue="true", name="admin_state_up")\r
- Boolean adminStateUp;\r
-\r
- @XmlElement (name="status")\r
- String status;\r
-\r
- @XmlElement (name="mac_address")\r
- String macAddress;\r
-\r
- @XmlElement (name="fixed_ips")\r
- List<Neutron_IPs> fixedIPs;\r
-\r
- @XmlElement (name="device_id")\r
- String deviceID;\r
-\r
- @XmlElement (name="device_owner")\r
- String deviceOwner;\r
-\r
- @XmlElement (name="tenant_id")\r
- String tenantID;\r
-\r
- // TODO: add security groups\r
- // @XmlElement (name="security_groups")\r
- // List<String> securityGroups;\r
-\r
- /* this attribute stores the floating IP address assigned to\r
- * each fixed IP address\r
- */\r
-\r
- HashMap<String, NeutronFloatingIP> floatingIPMap;\r
-\r
- public NeutronPort() {\r
- floatingIPMap = new HashMap<String, NeutronFloatingIP>();\r
- }\r
-\r
- public String getID() { return portUUID; }\r
-\r
- public String getPortUUID() {\r
- return portUUID;\r
- }\r
-\r
- public void setPortUUID(String portUUID) {\r
- this.portUUID = portUUID;\r
- }\r
-\r
- public String getNetworkUUID() {\r
- return networkUUID;\r
- }\r
-\r
- public void setNetworkUUID(String networkUUID) {\r
- this.networkUUID = networkUUID;\r
- }\r
-\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
-\r
- public boolean isAdminStateUp() {\r
- if (adminStateUp == null)\r
- return true;\r
- return adminStateUp;\r
- }\r
-\r
- public Boolean getAdminStateUp() { return adminStateUp; }\r
-\r
- public void setAdminStateUp(Boolean newValue) {\r
- this.adminStateUp = newValue;\r
- }\r
-\r
- public String getStatus() {\r
- return status;\r
- }\r
-\r
- public void setStatus(String status) {\r
- this.status = status;\r
- }\r
-\r
- public String getMacAddress() {\r
- return macAddress;\r
- }\r
-\r
- public void setMacAddress(String macAddress) {\r
- this.macAddress = macAddress;\r
- }\r
-\r
- public List<Neutron_IPs> getFixedIPs() {\r
- return fixedIPs;\r
- }\r
-\r
- public void setFixedIPs(List<Neutron_IPs> fixedIPs) {\r
- this.fixedIPs = fixedIPs;\r
- }\r
-\r
- public String getDeviceID() {\r
- return deviceID;\r
- }\r
-\r
- public void setDeviceID(String deviceID) {\r
- this.deviceID = deviceID;\r
- }\r
-\r
- public String getDeviceOwner() {\r
- return deviceOwner;\r
- }\r
-\r
- public void setDeviceOwner(String deviceOwner) {\r
- this.deviceOwner = deviceOwner;\r
- }\r
-\r
- public String getTenantID() {\r
- return tenantID;\r
- }\r
-\r
- public void setTenantID(String tenantID) {\r
- this.tenantID = tenantID;\r
- }\r
-\r
- public NeutronFloatingIP getFloatingIP(String key) {\r
- if (!floatingIPMap.containsKey(key))\r
- return null;\r
- return floatingIPMap.get(key);\r
- }\r
-\r
- public void removeFloatingIP(String key) {\r
- floatingIPMap.remove(key);\r
- }\r
-\r
- public void addFloatingIP(String key, NeutronFloatingIP floatingIP) {\r
- if (!floatingIPMap.containsKey(key))\r
- floatingIPMap.put(key, floatingIP);\r
- }\r
-\r
- /**\r
- * This method copies selected fields from the object and returns them\r
- * as a new object, suitable for marshaling.\r
- *\r
- * @param fields\r
- * List of attributes to be extracted\r
- * @return an OpenStackPorts object with only the selected fields\r
- * populated\r
- */\r
-\r
- public NeutronPort extractFields(List<String> fields) {\r
- NeutronPort ans = new NeutronPort();\r
- Iterator<String> i = fields.iterator();\r
- while (i.hasNext()) {\r
- String s = i.next();\r
- if (s.equals("id"))\r
- ans.setPortUUID(this.getPortUUID());\r
- if (s.equals("network_id"))\r
- ans.setNetworkUUID(this.getNetworkUUID());\r
- if (s.equals("name"))\r
- ans.setName(this.getName());\r
- if (s.equals("admin_state_up"))\r
- ans.setAdminStateUp(this.getAdminStateUp());\r
- if (s.equals("status"))\r
- ans.setStatus(this.getStatus());\r
- if (s.equals("mac_address"))\r
- ans.setMacAddress(this.getMacAddress());\r
- if (s.equals("fixed_ips")) {\r
- List<Neutron_IPs> fixedIPs = new ArrayList<Neutron_IPs>();\r
- fixedIPs.addAll(this.getFixedIPs());\r
- ans.setFixedIPs(fixedIPs);\r
- }\r
- if (s.equals("device_id")) {\r
- ans.setDeviceID(this.getDeviceID());\r
- }\r
- if (s.equals("device_owner")) {\r
- ans.setDeviceOwner(this.getDeviceOwner());\r
- }\r
- if (s.equals("tenant_id"))\r
- ans.setTenantID(this.getTenantID());\r
- }\r
- return ans;\r
- }\r
-\r
- public void initDefaults() {\r
- adminStateUp = true;\r
- if (status == null)\r
- status = "ACTIVE";\r
- if (fixedIPs == null)\r
- fixedIPs = new ArrayList<Neutron_IPs>();\r
- }\r
-\r
- /**\r
- * This method checks to see if the port has a floating IPv4 address\r
- * associated with the supplied fixed IPv4 address\r
- *\r
- * @param fixedIP\r
- * fixed IPv4 address in dotted decimal format\r
- * @return a boolean indicating if there is a floating IPv4 address bound\r
- * to the fixed IPv4 address\r
- */\r
-\r
- public boolean isBoundToFloatingIP(String fixedIP) {\r
- return floatingIPMap.containsKey(fixedIP);\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronPort {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement (name="id")
+ String portUUID;
+
+ @XmlElement (name="network_id")
+ String networkUUID;
+
+ @XmlElement (name="name")
+ String name;
+
+ @XmlElement (defaultValue="true", name="admin_state_up")
+ Boolean adminStateUp;
+
+ @XmlElement (name="status")
+ String status;
+
+ @XmlElement (name="mac_address")
+ String macAddress;
+
+ @XmlElement (name="fixed_ips")
+ List<Neutron_IPs> fixedIPs;
+
+ @XmlElement (name="device_id")
+ String deviceID;
+
+ @XmlElement (name="device_owner")
+ String deviceOwner;
+
+ @XmlElement (name="tenant_id")
+ String tenantID;
+
+ // TODO: add security groups
+ // @XmlElement (name="security_groups")
+ // List<String> securityGroups;
+
+ /* this attribute stores the floating IP address assigned to
+ * each fixed IP address
+ */
+
+ HashMap<String, NeutronFloatingIP> floatingIPMap;
+
+ public NeutronPort() {
+ floatingIPMap = new HashMap<String, NeutronFloatingIP>();
+ }
+
+ public String getID() { return portUUID; }
+
+ public String getPortUUID() {
+ return portUUID;
+ }
+
+ public void setPortUUID(String portUUID) {
+ this.portUUID = portUUID;
+ }
+
+ public String getNetworkUUID() {
+ return networkUUID;
+ }
+
+ public void setNetworkUUID(String networkUUID) {
+ this.networkUUID = networkUUID;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isAdminStateUp() {
+ if (adminStateUp == null) {
+ return true;
+ }
+ return adminStateUp;
+ }
+
+ public Boolean getAdminStateUp() { return adminStateUp; }
+
+ public void setAdminStateUp(Boolean newValue) {
+ adminStateUp = newValue;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ public void setMacAddress(String macAddress) {
+ this.macAddress = macAddress;
+ }
+
+ public List<Neutron_IPs> getFixedIPs() {
+ return fixedIPs;
+ }
+
+ public void setFixedIPs(List<Neutron_IPs> fixedIPs) {
+ this.fixedIPs = fixedIPs;
+ }
+
+ public String getDeviceID() {
+ return deviceID;
+ }
+
+ public void setDeviceID(String deviceID) {
+ this.deviceID = deviceID;
+ }
+
+ public String getDeviceOwner() {
+ return deviceOwner;
+ }
+
+ public void setDeviceOwner(String deviceOwner) {
+ this.deviceOwner = deviceOwner;
+ }
+
+ public String getTenantID() {
+ return tenantID;
+ }
+
+ public void setTenantID(String tenantID) {
+ this.tenantID = tenantID;
+ }
+
+ public NeutronFloatingIP getFloatingIP(String key) {
+ if (!floatingIPMap.containsKey(key)) {
+ return null;
+ }
+ return floatingIPMap.get(key);
+ }
+
+ public void removeFloatingIP(String key) {
+ floatingIPMap.remove(key);
+ }
+
+ public void addFloatingIP(String key, NeutronFloatingIP floatingIP) {
+ if (!floatingIPMap.containsKey(key)) {
+ floatingIPMap.put(key, floatingIP);
+ }
+ }
+
+ /**
+ * This method copies selected fields from the object and returns them
+ * as a new object, suitable for marshaling.
+ *
+ * @param fields
+ * List of attributes to be extracted
+ * @return an OpenStackPorts object with only the selected fields
+ * populated
+ */
+
+ public NeutronPort extractFields(List<String> fields) {
+ NeutronPort ans = new NeutronPort();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setPortUUID(this.getPortUUID());
+ }
+ if (s.equals("network_id")) {
+ ans.setNetworkUUID(this.getNetworkUUID());
+ }
+ if (s.equals("name")) {
+ ans.setName(this.getName());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setAdminStateUp(this.getAdminStateUp());
+ }
+ if (s.equals("status")) {
+ ans.setStatus(this.getStatus());
+ }
+ if (s.equals("mac_address")) {
+ ans.setMacAddress(this.getMacAddress());
+ }
+ if (s.equals("fixed_ips")) {
+ List<Neutron_IPs> fixedIPs = new ArrayList<Neutron_IPs>();
+ fixedIPs.addAll(this.getFixedIPs());
+ ans.setFixedIPs(fixedIPs);
+ }
+ if (s.equals("device_id")) {
+ ans.setDeviceID(this.getDeviceID());
+ }
+ if (s.equals("device_owner")) {
+ ans.setDeviceOwner(this.getDeviceOwner());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setTenantID(this.getTenantID());
+ }
+ }
+ return ans;
+ }
+
+ public void initDefaults() {
+ adminStateUp = true;
+ if (status == null) {
+ status = "ACTIVE";
+ }
+ if (fixedIPs == null) {
+ fixedIPs = new ArrayList<Neutron_IPs>();
+ }
+ }
+
+ /**
+ * This method checks to see if the port has a floating IPv4 address
+ * associated with the supplied fixed IPv4 address
+ *
+ * @param fixedIP
+ * fixed IPv4 address in dotted decimal format
+ * @return a boolean indicating if there is a floating IPv4 address bound
+ * to the fixed IPv4 address
+ */
+
+ public boolean isBoundToFloatingIP(String fixedIP) {
+ return floatingIPMap.containsKey(fixedIP);
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronRouter {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
- @XmlElement (name="id")\r
- String routerUUID;\r
-\r
- @XmlElement (name="name")\r
- String name;\r
-\r
- @XmlElement (defaultValue="true", name="admin_state_up")\r
- Boolean adminStateUp;\r
-\r
- @XmlElement (name="status")\r
- String status;\r
-\r
- @XmlElement (name="tenant_id")\r
- String tenantID;\r
-\r
- @XmlElement (name="external_gateway_info")\r
- NeutronRouter_NetworkReference externalGatewayInfo;\r
-\r
- /* Holds a map of OpenStackRouterInterfaces by subnet UUID\r
- * used for internal mapping to DOVE\r
- */\r
- HashMap<String, NeutronRouter_Interface> interfaces;\r
-\r
- public NeutronRouter() {\r
- interfaces = new HashMap<String, NeutronRouter_Interface>();\r
- }\r
-\r
- public String getID() { return routerUUID; }\r
-\r
- public String getRouterUUID() {\r
- return routerUUID;\r
- }\r
-\r
- public void setRouterUUID(String routerUUID) {\r
- this.routerUUID = routerUUID;\r
- }\r
-\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
-\r
- public boolean isAdminStateUp() {\r
- if (adminStateUp == null)\r
- return true;\r
- return adminStateUp;\r
- }\r
-\r
- public Boolean getAdminStateUp() { return adminStateUp; }\r
-\r
- public void setAdminStateUp(Boolean newValue) {\r
- this.adminStateUp = newValue;\r
- }\r
-\r
- public String getStatus() {\r
- return status;\r
- }\r
-\r
- public void setStatus(String status) {\r
- this.status = status;\r
- }\r
-\r
- public String getTenantID() {\r
- return tenantID;\r
- }\r
-\r
- public void setTenantID(String tenantID) {\r
- this.tenantID = tenantID;\r
- }\r
-\r
- public NeutronRouter_NetworkReference getExternalGatewayInfo() {\r
- return externalGatewayInfo;\r
- }\r
-\r
- public void setExternalGatewayInfo(NeutronRouter_NetworkReference externalGatewayInfo) {\r
- this.externalGatewayInfo = externalGatewayInfo;\r
- }\r
-\r
- /**\r
- * This method copies selected fields from the object and returns them\r
- * as a new object, suitable for marshaling.\r
- *\r
- * @param fields\r
- * List of attributes to be extracted\r
- * @return an OpenStackRouters object with only the selected fields\r
- * populated\r
- */\r
-\r
- public NeutronRouter extractFields(List<String> fields) {\r
- NeutronRouter ans = new NeutronRouter();\r
- Iterator<String> i = fields.iterator();\r
- while (i.hasNext()) {\r
- String s = i.next();\r
- if (s.equals("id"))\r
- ans.setRouterUUID(this.getRouterUUID());\r
- if (s.equals("name"))\r
- ans.setName(this.getName());\r
- if (s.equals("admin_state_up"))\r
- ans.setAdminStateUp(this.getAdminStateUp());\r
- if (s.equals("status"))\r
- ans.setStatus(this.getStatus());\r
- if (s.equals("tenant_id"))\r
- ans.setTenantID(this.getTenantID());\r
- if (s.equals("external_gateway_info")) {\r
- ans.setExternalGatewayInfo(this.getExternalGatewayInfo());\r
- }\r
- }\r
- return ans;\r
- }\r
-\r
- public HashMap<String, NeutronRouter_Interface> getInterfaces() {\r
- return interfaces;\r
- }\r
-\r
- public void addInterface(String s, NeutronRouter_Interface i) {\r
- interfaces.put(s, i);\r
- }\r
-\r
- public void removeInterface(String s) {\r
- interfaces.remove(s);\r
- }\r
-\r
- public void initDefaults() {\r
- adminStateUp = true;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronRouter {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+ @XmlElement (name="id")
+ String routerUUID;
+
+ @XmlElement (name="name")
+ String name;
+
+ @XmlElement (defaultValue="true", name="admin_state_up")
+ Boolean adminStateUp;
+
+ @XmlElement (name="status")
+ String status;
+
+ @XmlElement (name="tenant_id")
+ String tenantID;
+
+ @XmlElement (name="external_gateway_info")
+ NeutronRouter_NetworkReference externalGatewayInfo;
+
+ /* Holds a map of OpenStackRouterInterfaces by subnet UUID
+ * used for internal mapping to DOVE
+ */
+ HashMap<String, NeutronRouter_Interface> interfaces;
+
+ public NeutronRouter() {
+ interfaces = new HashMap<String, NeutronRouter_Interface>();
+ }
+
+ public String getID() { return routerUUID; }
+
+ public String getRouterUUID() {
+ return routerUUID;
+ }
+
+ public void setRouterUUID(String routerUUID) {
+ this.routerUUID = routerUUID;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isAdminStateUp() {
+ if (adminStateUp == null) {
+ return true;
+ }
+ return adminStateUp;
+ }
+
+ public Boolean getAdminStateUp() { return adminStateUp; }
+
+ public void setAdminStateUp(Boolean newValue) {
+ adminStateUp = newValue;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getTenantID() {
+ return tenantID;
+ }
+
+ public void setTenantID(String tenantID) {
+ this.tenantID = tenantID;
+ }
+
+ public NeutronRouter_NetworkReference getExternalGatewayInfo() {
+ return externalGatewayInfo;
+ }
+
+ public void setExternalGatewayInfo(NeutronRouter_NetworkReference externalGatewayInfo) {
+ this.externalGatewayInfo = externalGatewayInfo;
+ }
+
+ /**
+ * This method copies selected fields from the object and returns them
+ * as a new object, suitable for marshaling.
+ *
+ * @param fields
+ * List of attributes to be extracted
+ * @return an OpenStackRouters object with only the selected fields
+ * populated
+ */
+
+ public NeutronRouter extractFields(List<String> fields) {
+ NeutronRouter ans = new NeutronRouter();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setRouterUUID(this.getRouterUUID());
+ }
+ if (s.equals("name")) {
+ ans.setName(this.getName());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setAdminStateUp(this.getAdminStateUp());
+ }
+ if (s.equals("status")) {
+ ans.setStatus(this.getStatus());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setTenantID(this.getTenantID());
+ }
+ if (s.equals("external_gateway_info")) {
+ ans.setExternalGatewayInfo(this.getExternalGatewayInfo());
+ }
+ }
+ return ans;
+ }
+
+ public HashMap<String, NeutronRouter_Interface> getInterfaces() {
+ return interfaces;
+ }
+
+ public void addInterface(String s, NeutronRouter_Interface i) {
+ interfaces.put(s, i);
+ }
+
+ public void removeInterface(String s) {
+ interfaces.remove(s);
+ }
+
+ public void initDefaults() {
+ adminStateUp = true;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronRouter_Interface {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement (name="subnet_id")\r
- String subnetUUID;\r
-\r
- @XmlElement (name="port_id")\r
- String portUUID;\r
-\r
- @XmlElement (name="id")\r
- String id;\r
-\r
- @XmlElement (name="tenant_id")\r
- String tenantID;\r
-\r
- public NeutronRouter_Interface() {\r
- }\r
-\r
- public NeutronRouter_Interface(String subnetUUID, String portUUID) {\r
- this.subnetUUID = subnetUUID;\r
- this.portUUID = portUUID;\r
- }\r
-\r
- public String getSubnetUUID() {\r
- return subnetUUID;\r
- }\r
-\r
- public void setSubnetUUID(String subnetUUID) {\r
- this.subnetUUID = subnetUUID;\r
- }\r
-\r
- public String getPortUUID() {\r
- return portUUID;\r
- }\r
-\r
- public void setPortUUID(String portUUID) {\r
- this.portUUID = portUUID;\r
- }\r
-\r
- public void setID(String id) {\r
- this.id = id;\r
- }\r
-\r
- public void setTenantID(String tenantID) {\r
- this.tenantID = tenantID;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronRouter_Interface {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement (name="subnet_id")
+ String subnetUUID;
+
+ @XmlElement (name="port_id")
+ String portUUID;
+
+ @XmlElement (name="id")
+ String id;
+
+ @XmlElement (name="tenant_id")
+ String tenantID;
+
+ public NeutronRouter_Interface() {
+ }
+
+ public NeutronRouter_Interface(String subnetUUID, String portUUID) {
+ this.subnetUUID = subnetUUID;
+ this.portUUID = portUUID;
+ }
+
+ public String getSubnetUUID() {
+ return subnetUUID;
+ }
+
+ public void setSubnetUUID(String subnetUUID) {
+ this.subnetUUID = subnetUUID;
+ }
+
+ public String getPortUUID() {
+ return portUUID;
+ }
+
+ public void setPortUUID(String portUUID) {
+ this.portUUID = portUUID;
+ }
+
+ public void setID(String id) {
+ this.id = id;
+ }
+
+ public void setTenantID(String tenantID) {
+ this.tenantID = tenantID;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronRouter_NetworkReference {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="network_id")\r
- String networkID;\r
-\r
- public NeutronRouter_NetworkReference() {\r
- }\r
-\r
- public String getNetworkID() {\r
- return networkID;\r
- }\r
-\r
- public void setNetworkID(String networkID) {\r
- this.networkID = networkID;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronRouter_NetworkReference {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="network_id")
+ String networkID;
+
+ public NeutronRouter_NetworkReference() {
+ }
+
+ public String getNetworkID() {
+ return networkID;
+ }
+
+ public void setNetworkID(String networkID) {
+ this.networkID = networkID;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.apache.commons.net.util.SubnetUtils;\r
-import org.apache.commons.net.util.SubnetUtils.SubnetInfo;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronSubnet {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement (name="id")\r
- String subnetUUID;\r
-\r
- @XmlElement (name="network_id")\r
- String networkUUID;\r
-\r
- @XmlElement (name="name")\r
- String name;\r
-\r
- @XmlElement (defaultValue="4", name="ip_version")\r
- Integer ipVersion;\r
-\r
- @XmlElement (name="cidr")\r
- String cidr;\r
-\r
- @XmlElement (name="gateway_ip")\r
- String gatewayIP;\r
-\r
- @XmlElement (name="dns_nameservers")\r
- List<String> dnsNameservers;\r
-\r
- @XmlElement (name="allocation_pools")\r
- List<NeutronSubnet_IPAllocationPool> allocationPools;\r
-\r
- @XmlElement (name="host_routes")\r
- List<NeutronSubnet_HostRoute> hostRoutes;\r
-\r
- @XmlElement (defaultValue="true", name="enable_dhcp")\r
- Boolean enableDHCP;\r
-\r
- @XmlElement (name="tenant_id")\r
- String tenantID;\r
-\r
- /* stores the OpenStackPorts associated with an instance\r
- * used to determine if that instance can be deleted.\r
- */\r
- List<NeutronPort> myPorts;\r
-\r
- boolean gatewayIPAssigned;\r
-\r
- public NeutronSubnet() {\r
- myPorts = new ArrayList<NeutronPort>();\r
- }\r
-\r
- public String getID() { return subnetUUID; }\r
-\r
- public String getSubnetUUID() {\r
- return subnetUUID;\r
- }\r
-\r
- public void setSubnetUUID(String subnetUUID) {\r
- this.subnetUUID = subnetUUID;\r
- }\r
-\r
- public String getNetworkUUID() {\r
- return networkUUID;\r
- }\r
-\r
- public void setNetworkUUID(String networkUUID) {\r
- this.networkUUID = networkUUID;\r
- }\r
-\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
-\r
- public Integer getIpVersion() {\r
- return ipVersion;\r
- }\r
-\r
- public void setIpVersion(Integer ipVersion) {\r
- this.ipVersion = ipVersion;\r
- }\r
-\r
- public String getCidr() {\r
- return cidr;\r
- }\r
-\r
- public void setCidr(String cidr) {\r
- this.cidr = cidr;\r
- }\r
-\r
- public String getGatewayIP() {\r
- return gatewayIP;\r
- }\r
-\r
- public void setGatewayIP(String gatewayIP) {\r
- this.gatewayIP = gatewayIP;\r
- }\r
-\r
- public List<String> getDnsNameservers() {\r
- return dnsNameservers;\r
- }\r
-\r
- public void setDnsNameservers(List<String> dnsNameservers) {\r
- this.dnsNameservers = dnsNameservers;\r
- }\r
-\r
- public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {\r
- return allocationPools;\r
- }\r
-\r
- public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {\r
- this.allocationPools = allocationPools;\r
- }\r
-\r
- public List<NeutronSubnet_HostRoute> getHostRoutes() {\r
- return hostRoutes;\r
- }\r
-\r
- public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {\r
- this.hostRoutes = hostRoutes;\r
- }\r
-\r
- public boolean isEnableDHCP() {\r
- if (enableDHCP == null) {\r
- return true;\r
- }\r
- return enableDHCP;\r
- }\r
-\r
- public Boolean getEnableDHCP() { return enableDHCP; }\r
-\r
- public void setEnableDHCP(Boolean newValue) {\r
- enableDHCP = newValue;\r
- }\r
-\r
- public String getTenantID() {\r
- return tenantID;\r
- }\r
-\r
- public void setTenantID(String tenantID) {\r
- this.tenantID = tenantID;\r
- }\r
-\r
- /**\r
- * This method copies selected fields from the object and returns them\r
- * as a new object, suitable for marshaling.\r
- *\r
- * @param fields\r
- * List of attributes to be extracted\r
- * @return an OpenStackSubnets object with only the selected fields\r
- * populated\r
- */\r
-\r
- public NeutronSubnet extractFields(List<String> fields) {\r
- NeutronSubnet ans = new NeutronSubnet();\r
- Iterator<String> i = fields.iterator();\r
- while (i.hasNext()) {\r
- String s = i.next();\r
- if (s.equals("id")) {\r
- ans.setSubnetUUID(this.getSubnetUUID());\r
- }\r
- if (s.equals("network_id")) {\r
- ans.setNetworkUUID(this.getNetworkUUID());\r
- }\r
- if (s.equals("name")) {\r
- ans.setName(this.getName());\r
- }\r
- if (s.equals("ip_version")) {\r
- ans.setIpVersion(this.getIpVersion());\r
- }\r
- if (s.equals("cidr")) {\r
- ans.setCidr(this.getCidr());\r
- }\r
- if (s.equals("gateway_ip")) {\r
- ans.setGatewayIP(this.getGatewayIP());\r
- }\r
- if (s.equals("dns_nameservers")) {\r
- List<String> nsList = new ArrayList<String>();\r
- nsList.addAll(this.getDnsNameservers());\r
- ans.setDnsNameservers(nsList);\r
- }\r
- if (s.equals("allocation_pools")) {\r
- List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
- aPools.addAll(this.getAllocationPools());\r
- ans.setAllocationPools(aPools);\r
- }\r
- if (s.equals("host_routes")) {\r
- List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
- hRoutes.addAll(this.getHostRoutes());\r
- ans.setHostRoutes(hRoutes);\r
- }\r
- if (s.equals("enable_dhcp")) {\r
- ans.setEnableDHCP(this.getEnableDHCP());\r
- }\r
- if (s.equals("tenant_id")) {\r
- ans.setTenantID(this.getTenantID());\r
- }\r
- }\r
- return ans;\r
- }\r
-\r
- /* test to see if the cidr address used to define this subnet\r
- * is a valid network address (an necessary condition when creating\r
- * a new subnet)\r
- */\r
- public boolean isValidCIDR() {\r
- try {\r
- SubnetUtils util = new SubnetUtils(cidr);\r
- SubnetInfo info = util.getInfo();\r
- if (!info.getNetworkAddress().equals(info.getAddress())) {\r
- return false;\r
- }\r
- } catch (Exception e) {\r
- return false;\r
- }\r
- return true;\r
- }\r
-\r
- /* test to see if the gateway IP specified overlaps with specified\r
- * allocation pools (an error condition when creating a new subnet\r
- * or assigning a gateway IP)\r
- */\r
- public boolean gatewayIP_Pool_overlap() {\r
- Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
- while (i.hasNext()) {\r
- NeutronSubnet_IPAllocationPool pool = i.next();\r
- if (pool.contains(gatewayIP)) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- public boolean initDefaults() {\r
- if (enableDHCP == null) {\r
- enableDHCP = true;\r
- }\r
- if (ipVersion == null) {\r
- ipVersion = 4;\r
- }\r
- gatewayIPAssigned = false;\r
- dnsNameservers = new ArrayList<String>();\r
- allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
- hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
- try {\r
- SubnetUtils util = new SubnetUtils(cidr);\r
- SubnetInfo info = util.getInfo();\r
- if (gatewayIP == null) {\r
- gatewayIP = info.getLowAddress();\r
- }\r
- if (allocationPools.size() < 1) {\r
- NeutronSubnet_IPAllocationPool source =\r
- new NeutronSubnet_IPAllocationPool(info.getLowAddress(),\r
- info.getHighAddress());\r
- allocationPools = source.splitPool(gatewayIP);\r
- }\r
- } catch (Exception e) {\r
- return false;\r
- }\r
- return true;\r
- }\r
-\r
- public List<NeutronPort> getPortsInSubnet() {\r
- return myPorts;\r
- }\r
-\r
- public void addPort(NeutronPort port) {\r
- myPorts.add(port);\r
- }\r
-\r
- public void removePort(NeutronPort port) {\r
- myPorts.remove(port);\r
- }\r
-\r
- /* this method tests to see if the supplied IPv4 address\r
- * is valid for this subnet or not\r
- */\r
- public boolean isValidIP(String ipAddress) {\r
- try {\r
- SubnetUtils util = new SubnetUtils(cidr);\r
- SubnetInfo info = util.getInfo();\r
- return info.isInRange(ipAddress);\r
- } catch (Exception e) {\r
- return false;\r
- }\r
- }\r
-\r
- /* test to see if the supplied IPv4 address is part of one of the\r
- * available allocation pools or not\r
- */\r
- public boolean isIPInUse(String ipAddress) {\r
- if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {\r
- return false;\r
- }\r
- Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
- while (i.hasNext()) {\r
- NeutronSubnet_IPAllocationPool pool = i.next();\r
- if (pool.contains(ipAddress)) {\r
- return false;\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- /* method to get the lowest available address of the subnet.\r
- * go through all the allocation pools and keep the lowest of their\r
- * low addresses.\r
- */\r
- public String getLowAddr() {\r
- String ans = null;\r
- Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
- while (i.hasNext()) {\r
- NeutronSubnet_IPAllocationPool pool = i.next();\r
- if (ans == null) {\r
- ans = pool.getPoolStart();\r
- }\r
- else\r
- if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <\r
- NeutronSubnet_IPAllocationPool.convert(ans)) {\r
- ans = pool.getPoolStart();\r
- }\r
- }\r
- return ans;\r
- }\r
-\r
- /*\r
- * allocate the parameter address. Because this uses an iterator to\r
- * check the instance's list of allocation pools and we want to modify\r
- * pools while the iterator is being used, it is necessary to\r
- * build a new list of allocation pools and replace the list when\r
- * finished (otherwise a split will cause undefined iterator behavior.\r
- */\r
- public void allocateIP(String ipAddress) {\r
- Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
- List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>(); // we have to modify a separate list\r
- while (i.hasNext()) {\r
- NeutronSubnet_IPAllocationPool pool = i.next();\r
- /* if the pool contains a single address element and we are allocating it\r
- * then we don't need to copy the pool over. Otherwise, we need to possibly\r
- * split the pool and add both pieces to the new list\r
- */\r
- if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&\r
- pool.getPoolStart().equalsIgnoreCase(ipAddress))) {\r
- if (pool.contains(ipAddress)) {\r
- List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);\r
- newList.addAll(pools);\r
- } else {\r
- newList.add(pool);\r
- }\r
- }\r
- }\r
- allocationPools = newList;\r
- }\r
-\r
- /*\r
- * release an IP address back to the subnet. Although an iterator\r
- * is used, the list is not modified until the iterator is complete, so\r
- * an extra list is not necessary.\r
- */\r
- public void releaseIP(String ipAddress) {\r
- NeutronSubnet_IPAllocationPool lPool = null;\r
- NeutronSubnet_IPAllocationPool hPool = null;\r
- Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
- long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
- //look for lPool where ipAddr - 1 is high address\r
- //look for hPool where ipAddr + 1 is low address\r
- while (i.hasNext()) {\r
- NeutronSubnet_IPAllocationPool pool = i.next();\r
- long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());\r
- long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());\r
- if (sIP+1 == lIP) {\r
- hPool = pool;\r
- }\r
- if (sIP-1 == hIP) {\r
- lPool = pool;\r
- }\r
- }\r
- //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high\r
- if (lPool == null && hPool == null) {\r
- allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));\r
- }\r
- //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr\r
- if (lPool == null && hPool != null) {\r
- hPool.setPoolStart(ipAddress);\r
- }\r
- //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr\r
- if (lPool != null && hPool == null) {\r
- lPool.setPoolEnd(ipAddress);\r
- }\r
- //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool\r
- // where low address = lPool.low address and high address = hPool.high Address\r
- if (lPool != null && hPool != null) {\r
- allocationPools.remove(lPool);\r
- allocationPools.remove(hPool);\r
- allocationPools.add(new NeutronSubnet_IPAllocationPool(\r
- lPool.getPoolStart(), hPool.getPoolEnd()));\r
- }\r
- }\r
-\r
- public void setGatewayIPAllocated() {\r
- gatewayIPAssigned = true;\r
- }\r
-\r
- public void resetGatewayIPAllocated() {\r
- gatewayIPAssigned = false;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSubnet {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement (name="id")
+ String subnetUUID;
+
+ @XmlElement (name="network_id")
+ String networkUUID;
+
+ @XmlElement (name="name")
+ String name;
+
+ @XmlElement (defaultValue="4", name="ip_version")
+ Integer ipVersion;
+
+ @XmlElement (name="cidr")
+ String cidr;
+
+ @XmlElement (name="gateway_ip")
+ String gatewayIP;
+
+ @XmlElement (name="dns_nameservers")
+ List<String> dnsNameservers;
+
+ @XmlElement (name="allocation_pools")
+ List<NeutronSubnet_IPAllocationPool> allocationPools;
+
+ @XmlElement (name="host_routes")
+ List<NeutronSubnet_HostRoute> hostRoutes;
+
+ @XmlElement (defaultValue="true", name="enable_dhcp")
+ Boolean enableDHCP;
+
+ @XmlElement (name="tenant_id")
+ String tenantID;
+
+ /* stores the OpenStackPorts associated with an instance
+ * used to determine if that instance can be deleted.
+ */
+ List<NeutronPort> myPorts;
+
+ boolean gatewayIPAssigned;
+
+ public NeutronSubnet() {
+ myPorts = new ArrayList<NeutronPort>();
+ }
+
+ public String getID() { return subnetUUID; }
+
+ public String getSubnetUUID() {
+ return subnetUUID;
+ }
+
+ public void setSubnetUUID(String subnetUUID) {
+ this.subnetUUID = subnetUUID;
+ }
+
+ public String getNetworkUUID() {
+ return networkUUID;
+ }
+
+ public void setNetworkUUID(String networkUUID) {
+ this.networkUUID = networkUUID;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getIpVersion() {
+ return ipVersion;
+ }
+
+ public void setIpVersion(Integer ipVersion) {
+ this.ipVersion = ipVersion;
+ }
+
+ public String getCidr() {
+ return cidr;
+ }
+
+ public void setCidr(String cidr) {
+ this.cidr = cidr;
+ }
+
+ public String getGatewayIP() {
+ return gatewayIP;
+ }
+
+ public void setGatewayIP(String gatewayIP) {
+ this.gatewayIP = gatewayIP;
+ }
+
+ public List<String> getDnsNameservers() {
+ return dnsNameservers;
+ }
+
+ public void setDnsNameservers(List<String> dnsNameservers) {
+ this.dnsNameservers = dnsNameservers;
+ }
+
+ public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {
+ return allocationPools;
+ }
+
+ public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {
+ this.allocationPools = allocationPools;
+ }
+
+ public List<NeutronSubnet_HostRoute> getHostRoutes() {
+ return hostRoutes;
+ }
+
+ public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {
+ this.hostRoutes = hostRoutes;
+ }
+
+ public boolean isEnableDHCP() {
+ if (enableDHCP == null) {
+ return true;
+ }
+ return enableDHCP;
+ }
+
+ public Boolean getEnableDHCP() { return enableDHCP; }
+
+ public void setEnableDHCP(Boolean newValue) {
+ enableDHCP = newValue;
+ }
+
+ public String getTenantID() {
+ return tenantID;
+ }
+
+ public void setTenantID(String tenantID) {
+ this.tenantID = tenantID;
+ }
+
+ /**
+ * This method copies selected fields from the object and returns them
+ * as a new object, suitable for marshaling.
+ *
+ * @param fields
+ * List of attributes to be extracted
+ * @return an OpenStackSubnets object with only the selected fields
+ * populated
+ */
+
+ public NeutronSubnet extractFields(List<String> fields) {
+ NeutronSubnet ans = new NeutronSubnet();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setSubnetUUID(this.getSubnetUUID());
+ }
+ if (s.equals("network_id")) {
+ ans.setNetworkUUID(this.getNetworkUUID());
+ }
+ if (s.equals("name")) {
+ ans.setName(this.getName());
+ }
+ if (s.equals("ip_version")) {
+ ans.setIpVersion(this.getIpVersion());
+ }
+ if (s.equals("cidr")) {
+ ans.setCidr(this.getCidr());
+ }
+ if (s.equals("gateway_ip")) {
+ ans.setGatewayIP(this.getGatewayIP());
+ }
+ if (s.equals("dns_nameservers")) {
+ List<String> nsList = new ArrayList<String>();
+ nsList.addAll(this.getDnsNameservers());
+ ans.setDnsNameservers(nsList);
+ }
+ if (s.equals("allocation_pools")) {
+ List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
+ aPools.addAll(this.getAllocationPools());
+ ans.setAllocationPools(aPools);
+ }
+ if (s.equals("host_routes")) {
+ List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();
+ hRoutes.addAll(this.getHostRoutes());
+ ans.setHostRoutes(hRoutes);
+ }
+ if (s.equals("enable_dhcp")) {
+ ans.setEnableDHCP(this.getEnableDHCP());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setTenantID(this.getTenantID());
+ }
+ }
+ return ans;
+ }
+
+ /* test to see if the cidr address used to define this subnet
+ * is a valid network address (an necessary condition when creating
+ * a new subnet)
+ */
+ public boolean isValidCIDR() {
+ try {
+ SubnetUtils util = new SubnetUtils(cidr);
+ SubnetInfo info = util.getInfo();
+ if (!info.getNetworkAddress().equals(info.getAddress())) {
+ return false;
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ /* test to see if the gateway IP specified overlaps with specified
+ * allocation pools (an error condition when creating a new subnet
+ * or assigning a gateway IP)
+ */
+ public boolean gatewayIP_Pool_overlap() {
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+ while (i.hasNext()) {
+ NeutronSubnet_IPAllocationPool pool = i.next();
+ if (pool.contains(gatewayIP)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean initDefaults() {
+ if (enableDHCP == null) {
+ enableDHCP = true;
+ }
+ if (ipVersion == null) {
+ ipVersion = 4;
+ }
+ gatewayIPAssigned = false;
+ dnsNameservers = new ArrayList<String>();
+ allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
+ hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();
+ try {
+ SubnetUtils util = new SubnetUtils(cidr);
+ SubnetInfo info = util.getInfo();
+ if (gatewayIP == null) {
+ gatewayIP = info.getLowAddress();
+ }
+ if (allocationPools.size() < 1) {
+ NeutronSubnet_IPAllocationPool source =
+ new NeutronSubnet_IPAllocationPool(info.getLowAddress(),
+ info.getHighAddress());
+ allocationPools = source.splitPool(gatewayIP);
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ public List<NeutronPort> getPortsInSubnet() {
+ return myPorts;
+ }
+
+ public void addPort(NeutronPort port) {
+ myPorts.add(port);
+ }
+
+ public void removePort(NeutronPort port) {
+ myPorts.remove(port);
+ }
+
+ /* this method tests to see if the supplied IPv4 address
+ * is valid for this subnet or not
+ */
+ public boolean isValidIP(String ipAddress) {
+ try {
+ SubnetUtils util = new SubnetUtils(cidr);
+ SubnetInfo info = util.getInfo();
+ return info.isInRange(ipAddress);
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /* test to see if the supplied IPv4 address is part of one of the
+ * available allocation pools or not
+ */
+ public boolean isIPInUse(String ipAddress) {
+ if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {
+ return false;
+ }
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+ while (i.hasNext()) {
+ NeutronSubnet_IPAllocationPool pool = i.next();
+ if (pool.contains(ipAddress)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* method to get the lowest available address of the subnet.
+ * go through all the allocation pools and keep the lowest of their
+ * low addresses.
+ */
+ public String getLowAddr() {
+ String ans = null;
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+ while (i.hasNext()) {
+ NeutronSubnet_IPAllocationPool pool = i.next();
+ if (ans == null) {
+ ans = pool.getPoolStart();
+ }
+ else
+ if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <
+ NeutronSubnet_IPAllocationPool.convert(ans)) {
+ ans = pool.getPoolStart();
+ }
+ }
+ return ans;
+ }
+
+ /*
+ * allocate the parameter address. Because this uses an iterator to
+ * check the instance's list of allocation pools and we want to modify
+ * pools while the iterator is being used, it is necessary to
+ * build a new list of allocation pools and replace the list when
+ * finished (otherwise a split will cause undefined iterator behavior.
+ */
+ public void allocateIP(String ipAddress) {
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+ List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>(); // we have to modify a separate list
+ while (i.hasNext()) {
+ NeutronSubnet_IPAllocationPool pool = i.next();
+ /* if the pool contains a single address element and we are allocating it
+ * then we don't need to copy the pool over. Otherwise, we need to possibly
+ * split the pool and add both pieces to the new list
+ */
+ if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&
+ pool.getPoolStart().equalsIgnoreCase(ipAddress))) {
+ if (pool.contains(ipAddress)) {
+ List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);
+ newList.addAll(pools);
+ } else {
+ newList.add(pool);
+ }
+ }
+ }
+ allocationPools = newList;
+ }
+
+ /*
+ * release an IP address back to the subnet. Although an iterator
+ * is used, the list is not modified until the iterator is complete, so
+ * an extra list is not necessary.
+ */
+ public void releaseIP(String ipAddress) {
+ NeutronSubnet_IPAllocationPool lPool = null;
+ NeutronSubnet_IPAllocationPool hPool = null;
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
+ long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);
+ //look for lPool where ipAddr - 1 is high address
+ //look for hPool where ipAddr + 1 is low address
+ while (i.hasNext()) {
+ NeutronSubnet_IPAllocationPool pool = i.next();
+ long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());
+ long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());
+ if (sIP+1 == lIP) {
+ hPool = pool;
+ }
+ if (sIP-1 == hIP) {
+ lPool = pool;
+ }
+ }
+ //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high
+ if (lPool == null && hPool == null) {
+ allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));
+ }
+ //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr
+ if (lPool == null && hPool != null) {
+ hPool.setPoolStart(ipAddress);
+ }
+ //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr
+ if (lPool != null && hPool == null) {
+ lPool.setPoolEnd(ipAddress);
+ }
+ //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool
+ // where low address = lPool.low address and high address = hPool.high Address
+ if (lPool != null && hPool != null) {
+ allocationPools.remove(lPool);
+ allocationPools.remove(hPool);
+ allocationPools.add(new NeutronSubnet_IPAllocationPool(
+ lPool.getPoolStart(), hPool.getPoolEnd()));
+ }
+ }
+
+ public void setGatewayIPAllocated() {
+ gatewayIPAssigned = true;
+ }
+
+ public void resetGatewayIPAllocated() {
+ gatewayIPAssigned = false;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronSubnet_HostRoute {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="destination")\r
- String destination;\r
-\r
- @XmlElement(name="nexthop")\r
- String nextHop;\r
-\r
- public NeutronSubnet_HostRoute() { }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronSubnet_HostRoute {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="destination")
+ String destination;
+
+ @XmlElement(name="nexthop")
+ String nextHop;
+
+ public NeutronSubnet_HostRoute() { }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronSubnet_IPAllocationPool {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="start")\r
- String poolStart;\r
-\r
- @XmlElement(name="end")\r
- String poolEnd;\r
-\r
- public NeutronSubnet_IPAllocationPool() { }\r
-\r
- public NeutronSubnet_IPAllocationPool(String lowAddress, String highAddress) {\r
- poolStart = lowAddress;\r
- poolEnd = highAddress;\r
- }\r
-\r
- public String getPoolStart() {\r
- return poolStart;\r
- }\r
-\r
- public void setPoolStart(String poolStart) {\r
- this.poolStart = poolStart;\r
- }\r
-\r
- public String getPoolEnd() {\r
- return poolEnd;\r
- }\r
-\r
- public void setPoolEnd(String poolEnd) {\r
- this.poolEnd = poolEnd;\r
- }\r
-\r
- /**\r
- * This method determines if this allocation pool contains the\r
- * input IPv4 address\r
- *\r
- * @param inputString\r
- * IPv4 address in dotted decimal format\r
- * @returns a boolean on whether the pool contains the address or not\r
- */\r
-\r
- public boolean contains(String inputString) {\r
- long inputIP = convert(inputString);\r
- long startIP = convert(poolStart);\r
- long endIP = convert(poolEnd);\r
- return (inputIP >= startIP && inputIP <= endIP);\r
- }\r
-\r
- /**\r
- * This static method converts the supplied IPv4 address to a long\r
- * integer for comparison\r
- *\r
- * @param inputString\r
- * IPv4 address in dotted decimal format\r
- * @returns high-endian representation of the IPv4 address as a long\r
- */\r
-\r
- static long convert(String inputString) {\r
- long ans = 0;\r
- String[] parts = inputString.split("\\.");\r
- for (String part: parts) {\r
- ans <<= 8;\r
- ans |= Integer.parseInt(part);\r
- }\r
- return ans;\r
- }\r
-\r
- /**\r
- * This static method converts the supplied high-ending long back\r
- * into a dotted decimal representation of an IPv4 address\r
- *\r
- * @param l\r
- * high-endian representation of the IPv4 address as a long\r
- * @returns IPv4 address in dotted decimal format\r
- */\r
- static String longtoIP(long l) {\r
- int i;\r
- String[] parts = new String[4];\r
- for (i=0; i<4; i++) {\r
- parts[3-i] = String.valueOf(l & 255);\r
- l >>= 8;\r
- }\r
- return join(parts,".");\r
- }\r
-\r
- /*\r
- * helper routine used by longtoIP\r
- */\r
- public static String join(String r[],String d)\r
- {\r
- if (r.length == 0) return "";\r
- StringBuilder sb = new StringBuilder();\r
- int i;\r
- for(i=0;i<r.length-1;i++) {\r
- sb.append(r[i]+d);\r
- }\r
- return sb.toString()+r[i];\r
- }\r
-\r
- /*\r
- * This method splits the current instance by removing the supplied\r
- * parameter.\r
- *\r
- * If the parameter is either the low or high address,\r
- * then that member is adjusted and a list containing just this instance\r
- * is returned.\r
- *\r
- * If the parameter is in the middle of the pool, then\r
- * create two new instances, one ranging from low to parameter-1\r
- * the other ranging from parameter+1 to high\r
- */\r
- public List<NeutronSubnet_IPAllocationPool> splitPool(String ipAddress) {\r
- List<NeutronSubnet_IPAllocationPool> ans = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
- long gIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
- long sIP = NeutronSubnet_IPAllocationPool.convert(poolStart);\r
- long eIP = NeutronSubnet_IPAllocationPool.convert(poolEnd);\r
- long i;\r
- NeutronSubnet_IPAllocationPool p = new NeutronSubnet_IPAllocationPool();\r
- boolean poolStarted = false;\r
- for (i=sIP; i<=eIP; i++) {\r
- if (i == sIP) {\r
- if (i != gIP) {\r
- p.setPoolStart(poolStart);\r
- poolStarted = true;\r
- }\r
- }\r
- if (i == eIP) {\r
- if (i != gIP) {\r
- p.setPoolEnd(poolEnd);\r
- } else {\r
- p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));\r
- }\r
- ans.add(p);\r
- }\r
- if (i != sIP && i != eIP) {\r
- if (i != gIP) {\r
- if (!poolStarted) {\r
- p.setPoolStart(NeutronSubnet_IPAllocationPool.longtoIP(i));\r
- poolStarted = true;\r
- }\r
- } else {\r
- p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));\r
- poolStarted = false;\r
- ans.add(p);\r
- p = new NeutronSubnet_IPAllocationPool();\r
- }\r
- }\r
- }\r
- return ans;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronSubnet_IPAllocationPool {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="start")
+ String poolStart;
+
+ @XmlElement(name="end")
+ String poolEnd;
+
+ public NeutronSubnet_IPAllocationPool() { }
+
+ public NeutronSubnet_IPAllocationPool(String lowAddress, String highAddress) {
+ poolStart = lowAddress;
+ poolEnd = highAddress;
+ }
+
+ public String getPoolStart() {
+ return poolStart;
+ }
+
+ public void setPoolStart(String poolStart) {
+ this.poolStart = poolStart;
+ }
+
+ public String getPoolEnd() {
+ return poolEnd;
+ }
+
+ public void setPoolEnd(String poolEnd) {
+ this.poolEnd = poolEnd;
+ }
+
+ /**
+ * This method determines if this allocation pool contains the
+ * input IPv4 address
+ *
+ * @param inputString
+ * IPv4 address in dotted decimal format
+ * @returns a boolean on whether the pool contains the address or not
+ */
+
+ public boolean contains(String inputString) {
+ long inputIP = convert(inputString);
+ long startIP = convert(poolStart);
+ long endIP = convert(poolEnd);
+ return (inputIP >= startIP && inputIP <= endIP);
+ }
+
+ /**
+ * This static method converts the supplied IPv4 address to a long
+ * integer for comparison
+ *
+ * @param inputString
+ * IPv4 address in dotted decimal format
+ * @returns high-endian representation of the IPv4 address as a long
+ */
+
+ static long convert(String inputString) {
+ long ans = 0;
+ String[] parts = inputString.split("\\.");
+ for (String part: parts) {
+ ans <<= 8;
+ ans |= Integer.parseInt(part);
+ }
+ return ans;
+ }
+
+ /**
+ * This static method converts the supplied high-ending long back
+ * into a dotted decimal representation of an IPv4 address
+ *
+ * @param l
+ * high-endian representation of the IPv4 address as a long
+ * @returns IPv4 address in dotted decimal format
+ */
+ static String longtoIP(long l) {
+ int i;
+ String[] parts = new String[4];
+ for (i=0; i<4; i++) {
+ parts[3-i] = String.valueOf(l & 255);
+ l >>= 8;
+ }
+ return join(parts,".");
+ }
+
+ /*
+ * helper routine used by longtoIP
+ */
+ public static String join(String r[],String d)
+ {
+ if (r.length == 0) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ int i;
+ for(i=0;i<r.length-1;i++) {
+ sb.append(r[i]+d);
+ }
+ return sb.toString()+r[i];
+ }
+
+ /*
+ * This method splits the current instance by removing the supplied
+ * parameter.
+ *
+ * If the parameter is either the low or high address,
+ * then that member is adjusted and a list containing just this instance
+ * is returned.
+ *
+ * If the parameter is in the middle of the pool, then
+ * create two new instances, one ranging from low to parameter-1
+ * the other ranging from parameter+1 to high
+ */
+ public List<NeutronSubnet_IPAllocationPool> splitPool(String ipAddress) {
+ List<NeutronSubnet_IPAllocationPool> ans = new ArrayList<NeutronSubnet_IPAllocationPool>();
+ long gIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);
+ long sIP = NeutronSubnet_IPAllocationPool.convert(poolStart);
+ long eIP = NeutronSubnet_IPAllocationPool.convert(poolEnd);
+ long i;
+ NeutronSubnet_IPAllocationPool p = new NeutronSubnet_IPAllocationPool();
+ boolean poolStarted = false;
+ for (i=sIP; i<=eIP; i++) {
+ if (i == sIP) {
+ if (i != gIP) {
+ p.setPoolStart(poolStart);
+ poolStarted = true;
+ }
+ }
+ if (i == eIP) {
+ if (i != gIP) {
+ p.setPoolEnd(poolEnd);
+ } else {
+ p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));
+ }
+ ans.add(p);
+ }
+ if (i != sIP && i != eIP) {
+ if (i != gIP) {
+ if (!poolStarted) {
+ p.setPoolStart(NeutronSubnet_IPAllocationPool.longtoIP(i));
+ poolStarted = true;
+ }
+ } else {
+ p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1));
+ poolStarted = false;
+ ans.add(p);
+ p = new NeutronSubnet_IPAllocationPool();
+ }
+ }
+ }
+ return ans;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class Neutron_IPs {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="ip_address")\r
- String ipAddress;\r
-\r
- @XmlElement(name="subnet_id")\r
- String subnetUUID;\r
-\r
- public Neutron_IPs() { }\r
-\r
- public Neutron_IPs(String uuid) {\r
- this.subnetUUID = uuid;\r
- }\r
-\r
- public String getIpAddress() {\r
- return ipAddress;\r
- }\r
-\r
- public void setIpAddress(String ipAddress) {\r
- this.ipAddress = ipAddress;\r
- }\r
-\r
- public String getSubnetUUID() {\r
- return subnetUUID;\r
- }\r
-\r
- public void setSubnetUUID(String subnetUUID) {\r
- this.subnetUUID = subnetUUID;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Neutron_IPs {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="ip_address")
+ String ipAddress;
+
+ @XmlElement(name="subnet_id")
+ String subnetUUID;
+
+ public Neutron_IPs() { }
+
+ public Neutron_IPs(String uuid) {
+ subnetUUID = uuid;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+ public String getSubnetUUID() {
+ return subnetUUID;
+ }
+
+ public void setSubnetUUID(String subnetUUID) {
+ this.subnetUUID = subnetUUID;
+ }
+}
xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
<services>
- <rest defaultRestSubcontext="/controller/nb/v2/host"/>
+ <rest defaultRestSubcontext="/controller/nb/v2/hosttracker"/>
</services>
<modules>
*  <nodeId>00:00:00:00:00:00:00:01</nodeId>
*  <nodeConnectorType>OF</nodeConnectorType>
*  <nodeConnectorId>9</nodeConnectorId>
- *  <vlan>0</vlan>
- *  <staticHost>false</staticHost>
+ *  <vlan>1</vlan>
+ *  <staticHost>true</staticHost>
* </hostConfig>
*
* Request body in JSON:
*  "nodeId":"00:00:00:00:00:00:00:01",
*  "nodeConnectorType":"OF",
*  "nodeConnectorId":"9",
- *  "vlan":"0",
- *  "staticHost":"false",
+ *  "vlan":"1",
+ *  "staticHost":"true",
*  "networkAddress":"1.1.1.1"
* }
* </pre>
JSONTokener jt = new JSONTokener(result);
JSONObject json = new JSONObject(jt);
JSONArray subnetConfigs = json.getJSONArray("subnetConfig");
- Assert.assertEquals(subnetConfigs.length(), 0);
+ Assert.assertEquals(subnetConfigs.length(), 1); // should only get the default subnet
// Test GET subnet1 expecting 404
result = getJsonResult(baseURL + "default/subnet/" + name1);
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronFloatingIPRequest {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="floatingip")\r
- NeutronFloatingIP singletonFloatingIP;\r
-\r
- @XmlElement(name="floatingips")\r
- List<NeutronFloatingIP> bulkRequest;\r
-\r
- NeutronFloatingIPRequest() {\r
- }\r
-\r
- NeutronFloatingIPRequest(List<NeutronFloatingIP> bulk) {\r
- bulkRequest = bulk;\r
- singletonFloatingIP = null;\r
- }\r
-\r
- NeutronFloatingIPRequest(NeutronFloatingIP singleton) {\r
- bulkRequest = null;\r
- singletonFloatingIP = singleton;\r
- }\r
-\r
- public NeutronFloatingIP getSingleton() {\r
- return singletonFloatingIP;\r
- }\r
-\r
- public boolean isSingleton() {\r
- return (singletonFloatingIP != null);\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronFloatingIPRequest {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="floatingip")
+ NeutronFloatingIP singletonFloatingIP;
+
+ @XmlElement(name="floatingips")
+ List<NeutronFloatingIP> bulkRequest;
+
+ NeutronFloatingIPRequest() {
+ }
+
+ NeutronFloatingIPRequest(List<NeutronFloatingIP> bulk) {
+ bulkRequest = bulk;
+ singletonFloatingIP = null;
+ }
+
+ NeutronFloatingIPRequest(NeutronFloatingIP singleton) {
+ bulkRequest = null;
+ singletonFloatingIP = singleton;
+ }
+
+ public NeutronFloatingIP getSingleton() {
+ return singletonFloatingIP;
+ }
+
+ public boolean isSingleton() {
+ return (singletonFloatingIP != null);
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing the open DOVE\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/floatingips")\r
-public class NeutronFloatingIPsNorthbound {\r
-\r
- private NeutronFloatingIP extractFields(NeutronFloatingIP o, List<String> fields) {\r
- return o.extractFields(fields);\r
- }\r
-\r
- /**\r
- * Returns a list of all FloatingIPs */\r
-\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response listFloatingIPs(\r
- // return fields\r
- @QueryParam("fields") List<String> fields,\r
- // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
- @QueryParam("id") String queryID,\r
- @QueryParam("floating_network_id") String queryFloatingNetworkId,\r
- @QueryParam("port_id") String queryPortId,\r
- @QueryParam("fixed_ip_address") String queryFixedIPAddress,\r
- @QueryParam("floating_ip_address") String queryFloatingIPAddress,\r
- @QueryParam("tenant_id") String queryTenantID,\r
- // pagination\r
- @QueryParam("limit") String limit,\r
- @QueryParam("marker") String marker,\r
- @QueryParam("page_reverse") String pageReverse\r
- // sorting not supported\r
- ) {\r
- INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
- if (floatingIPInterface == null) {\r
- throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- List<NeutronFloatingIP> allFloatingIPs = floatingIPInterface.getAllFloatingIPs();\r
- List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();\r
- Iterator<NeutronFloatingIP> i = allFloatingIPs.iterator();\r
- while (i.hasNext()) {\r
- NeutronFloatingIP oSS = i.next();\r
- //match filters: TODO provider extension and router extension\r
- if ((queryID == null || queryID.equals(oSS.getID())) &&\r
- (queryFloatingNetworkId == null || queryFloatingNetworkId.equals(oSS.getFloatingNetworkUUID())) &&\r
- (queryPortId == null || queryPortId.equals(oSS.getPortUUID())) &&\r
- (queryFixedIPAddress == null || queryFixedIPAddress.equals(oSS.getFixedIPAddress())) &&\r
- (queryFloatingIPAddress == null || queryFloatingIPAddress.equals(oSS.getFloatingIPAddress())) &&\r
- (queryTenantID == null || queryTenantID.equals(oSS.getTenantUUID()))) {\r
- if (fields.size() > 0)\r
- ans.add(extractFields(oSS,fields));\r
- else\r
- ans.add(oSS);\r
- }\r
- }\r
- //TODO: apply pagination to results\r
- return Response.status(200).entity(\r
- new NeutronFloatingIPRequest(ans)).build();\r
- }\r
-\r
- /**\r
- * Returns a specific FloatingIP */\r
-\r
- @Path("{floatingipUUID}")\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response showFloatingIP(\r
- @PathParam("floatingipUUID") String floatingipUUID,\r
- // return fields\r
- @QueryParam("fields") List<String> fields ) {\r
- INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
- if (floatingIPInterface == null) {\r
- throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!floatingIPInterface.floatingIPExists(floatingipUUID))\r
- return Response.status(404).build();\r
- if (fields.size() > 0) {\r
- NeutronFloatingIP ans = floatingIPInterface.getFloatingIP(floatingipUUID);\r
- return Response.status(200).entity(\r
- new NeutronFloatingIPRequest(extractFields(ans, fields))).build();\r
- } else\r
- return Response.status(200).entity(\r
- new NeutronFloatingIPRequest(floatingIPInterface.getFloatingIP(floatingipUUID))).build();\r
-\r
- }\r
-\r
- /**\r
- * Creates new FloatingIPs */\r
-\r
- @POST\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- @StatusCodes({\r
- @ResponseCode(code = 201, condition = "Created"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response createFloatingIPs(final NeutronFloatingIPRequest input) {\r
- INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
- if (floatingIPInterface == null) {\r
- throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (input.isSingleton()) {\r
- NeutronFloatingIP singleton = input.getSingleton();\r
- // check existence of id in cache and return badrequest if exists\r
- if (floatingIPInterface.floatingIPExists(singleton.getID()))\r
- return Response.status(400).build();\r
- // check if the external network is specified, exists, and is an external network\r
- String externalNetworkUUID = singleton.getFloatingNetworkUUID();\r
- if (externalNetworkUUID == null)\r
- return Response.status(400).build();\r
- if (!networkInterface.networkExists(externalNetworkUUID))\r
- return Response.status(400).build();\r
- NeutronNetwork externNetwork = networkInterface.getNetwork(externalNetworkUUID);\r
- if (!externNetwork.isRouterExternal())\r
- return Response.status(400).build();\r
- // if floating IP is specified, make sure it can come from the network\r
- String floatingIP = singleton.getFloatingIPAddress();\r
- if (floatingIP != null) {\r
- if (externNetwork.getSubnets().size() > 1)\r
- return Response.status(400).build();\r
- NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));\r
- if (!externSubnet.isValidIP(floatingIP))\r
- return Response.status(400).build();\r
- if (externSubnet.isIPInUse(floatingIP))\r
- return Response.status(409).build();\r
- }\r
- // if port_id is specified, then check that the port exists and has at least one IP\r
- String port_id = singleton.getPortUUID();\r
- if (port_id != null) {\r
- String fixedIP = null; // used for the fixedIP calculation\r
- if (!portInterface.portExists(port_id))\r
- return Response.status(404).build();\r
- NeutronPort port = portInterface.getPort(port_id);\r
- if (port.getFixedIPs().size() < 1)\r
- return Response.status(400).build();\r
- // if there is more than one fixed IP then check for fixed_ip_address\r
- // and that it is in the list of port addresses\r
- if (port.getFixedIPs().size() > 1) {\r
- fixedIP = singleton.getFixedIPAddress();\r
- if (fixedIP == null)\r
- return Response.status(400).build();\r
- Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();\r
- boolean validFixedIP = false;\r
- while (i.hasNext() && !validFixedIP) {\r
- Neutron_IPs ip = i.next();\r
- if (ip.getIpAddress().equals(fixedIP))\r
- validFixedIP = true;\r
- }\r
- if (!validFixedIP)\r
- return Response.status(400).build();\r
- } else {\r
- fixedIP = port.getFixedIPs().get(0).getIpAddress();\r
- if (singleton.getFixedIPAddress() != null && !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))\r
- return Response.status(400).build();\r
- }\r
- //lastly check that this fixed IP address isn't already used\r
- if (port.isBoundToFloatingIP(fixedIP))\r
- return Response.status(409).build();\r
- singleton.setFixedIPAddress(fixedIP);\r
- }\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
- int status = service.canCreateFloatingIP(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- floatingIPInterface.addFloatingIP(singleton);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
- service.neutronFloatingIPCreated(singleton);\r
- }\r
- }\r
- } else {\r
- return Response.status(400).build();\r
- }\r
- return Response.status(201).entity(input).build();\r
- }\r
-\r
- /**\r
- * Updates a FloatingIP */\r
-\r
- @Path("{floatingipUUID}")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response updateFloatingIP(\r
- @PathParam("floatingipUUID") String floatingipUUID,\r
- NeutronFloatingIPRequest input\r
- ) {\r
- INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
- if (floatingIPInterface == null) {\r
- throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!floatingIPInterface.floatingIPExists(floatingipUUID))\r
- return Response.status(404).build();\r
-\r
- NeutronFloatingIP sourceFloatingIP = floatingIPInterface.getFloatingIP(floatingipUUID);\r
- if (!input.isSingleton())\r
- return Response.status(400).build();\r
- NeutronFloatingIP singleton = input.getSingleton();\r
- if (singleton.getID() != null)\r
- return Response.status(400).build();\r
-\r
- NeutronNetwork externNetwork = networkInterface.getNetwork(\r
- sourceFloatingIP.getFloatingNetworkUUID());\r
-\r
- // if floating IP is specified, make sure it can come from the network\r
- String floatingIP = singleton.getFloatingIPAddress();\r
- if (floatingIP != null) {\r
- if (externNetwork.getSubnets().size() > 1)\r
- return Response.status(400).build();\r
- NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));\r
- if (!externSubnet.isValidIP(floatingIP))\r
- return Response.status(400).build();\r
- if (externSubnet.isIPInUse(floatingIP))\r
- return Response.status(409).build();\r
- }\r
-\r
- // if port_id is specified, then check that the port exists and has at least one IP\r
- String port_id = singleton.getPortUUID();\r
- if (port_id != null) {\r
- String fixedIP = null; // used for the fixedIP calculation\r
- if (!portInterface.portExists(port_id))\r
- return Response.status(404).build();\r
- NeutronPort port = portInterface.getPort(port_id);\r
- if (port.getFixedIPs().size() < 1)\r
- return Response.status(400).build();\r
- // if there is more than one fixed IP then check for fixed_ip_address\r
- // and that it is in the list of port addresses\r
- if (port.getFixedIPs().size() > 1) {\r
- fixedIP = singleton.getFixedIPAddress();\r
- if (fixedIP == null)\r
- return Response.status(400).build();\r
- Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();\r
- boolean validFixedIP = false;\r
- while (i.hasNext() && !validFixedIP) {\r
- Neutron_IPs ip = i.next();\r
- if (ip.getIpAddress().equals(fixedIP))\r
- validFixedIP = true;\r
- }\r
- if (!validFixedIP)\r
- return Response.status(400).build();\r
- } else {\r
- fixedIP = port.getFixedIPs().get(0).getIpAddress();\r
- if (singleton.getFixedIPAddress() != null &&\r
- !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))\r
- return Response.status(400).build();\r
- }\r
- //lastly check that this fixed IP address isn't already used\r
- if (port.isBoundToFloatingIP(fixedIP))\r
- return Response.status(409).build();\r
- singleton.setFixedIPAddress(fixedIP);\r
- }\r
- NeutronFloatingIP target = floatingIPInterface.getFloatingIP(floatingipUUID);\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
- int status = service.canUpdateFloatingIP(singleton, target);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- floatingIPInterface.updateFloatingIP(floatingipUUID, singleton);\r
- target = floatingIPInterface.getFloatingIP(floatingipUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
- service.neutronFloatingIPUpdated(target);\r
- }\r
- }\r
- return Response.status(200).entity(\r
- new NeutronFloatingIPRequest(target)).build();\r
-\r
- }\r
-\r
- /**\r
- * Deletes a FloatingIP */\r
-\r
- @Path("{floatingipUUID}")\r
- @DELETE\r
- @StatusCodes({\r
- @ResponseCode(code = 204, condition = "No Content"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response deleteFloatingIP(\r
- @PathParam("floatingipUUID") String floatingipUUID) {\r
- INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);\r
- if (floatingIPInterface == null) {\r
- throw new ServiceUnavailableException("Floating IP CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!floatingIPInterface.floatingIPExists(floatingipUUID))\r
- return Response.status(404).build();\r
- // TODO: need to undo port association if it exists\r
- NeutronFloatingIP singleton = floatingIPInterface.getFloatingIP(floatingipUUID);\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
- int status = service.canDeleteFloatingIP(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- floatingIPInterface.removeFloatingIP(floatingipUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;\r
- service.neutronFloatingIPDeleted(singleton);\r
- }\r
- }\r
- return Response.status(204).build();\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing the open DOVE
+ *
+ * <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. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/floatingips")
+public class NeutronFloatingIPsNorthbound {
+
+ private NeutronFloatingIP extractFields(NeutronFloatingIP o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all FloatingIPs */
+
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response listFloatingIPs(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // note: openstack isn't clear about filtering on lists, so we aren't handling them
+ @QueryParam("id") String queryID,
+ @QueryParam("floating_network_id") String queryFloatingNetworkId,
+ @QueryParam("port_id") String queryPortId,
+ @QueryParam("fixed_ip_address") String queryFixedIPAddress,
+ @QueryParam("floating_ip_address") String queryFloatingIPAddress,
+ @QueryParam("tenant_id") String queryTenantID,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+ if (floatingIPInterface == null) {
+ throw new ServiceUnavailableException("Floating IP CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronFloatingIP> allFloatingIPs = floatingIPInterface.getAllFloatingIPs();
+ List<NeutronFloatingIP> ans = new ArrayList<NeutronFloatingIP>();
+ Iterator<NeutronFloatingIP> i = allFloatingIPs.iterator();
+ while (i.hasNext()) {
+ NeutronFloatingIP oSS = i.next();
+ //match filters: TODO provider extension and router extension
+ if ((queryID == null || queryID.equals(oSS.getID())) &&
+ (queryFloatingNetworkId == null || queryFloatingNetworkId.equals(oSS.getFloatingNetworkUUID())) &&
+ (queryPortId == null || queryPortId.equals(oSS.getPortUUID())) &&
+ (queryFixedIPAddress == null || queryFixedIPAddress.equals(oSS.getFixedIPAddress())) &&
+ (queryFloatingIPAddress == null || queryFloatingIPAddress.equals(oSS.getFloatingIPAddress())) &&
+ (queryTenantID == null || queryTenantID.equals(oSS.getTenantUUID()))) {
+ if (fields.size() > 0)
+ ans.add(extractFields(oSS,fields));
+ else
+ ans.add(oSS);
+ }
+ }
+ //TODO: apply pagination to results
+ return Response.status(200).entity(
+ new NeutronFloatingIPRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific FloatingIP */
+
+ @Path("{floatingipUUID}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response showFloatingIP(
+ @PathParam("floatingipUUID") String floatingipUUID,
+ // return fields
+ @QueryParam("fields") List<String> fields ) {
+ INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+ if (floatingIPInterface == null) {
+ throw new ServiceUnavailableException("Floating IP CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!floatingIPInterface.floatingIPExists(floatingipUUID))
+ return Response.status(404).build();
+ if (fields.size() > 0) {
+ NeutronFloatingIP ans = floatingIPInterface.getFloatingIP(floatingipUUID);
+ return Response.status(200).entity(
+ new NeutronFloatingIPRequest(extractFields(ans, fields))).build();
+ } else
+ return Response.status(200).entity(
+ new NeutronFloatingIPRequest(floatingIPInterface.getFloatingIP(floatingipUUID))).build();
+
+ }
+
+ /**
+ * Creates new FloatingIPs */
+
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @StatusCodes({
+ @ResponseCode(code = 201, condition = "Created"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createFloatingIPs(final NeutronFloatingIPRequest input) {
+ INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+ if (floatingIPInterface == null) {
+ throw new ServiceUnavailableException("Floating IP CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronFloatingIP singleton = input.getSingleton();
+ // check existence of id in cache and return badrequest if exists
+ if (floatingIPInterface.floatingIPExists(singleton.getID()))
+ return Response.status(400).build();
+ // check if the external network is specified, exists, and is an external network
+ String externalNetworkUUID = singleton.getFloatingNetworkUUID();
+ if (externalNetworkUUID == null)
+ return Response.status(400).build();
+ if (!networkInterface.networkExists(externalNetworkUUID))
+ return Response.status(400).build();
+ NeutronNetwork externNetwork = networkInterface.getNetwork(externalNetworkUUID);
+ if (!externNetwork.isRouterExternal())
+ return Response.status(400).build();
+ // if floating IP is specified, make sure it can come from the network
+ String floatingIP = singleton.getFloatingIPAddress();
+ if (floatingIP != null) {
+ if (externNetwork.getSubnets().size() > 1)
+ return Response.status(400).build();
+ NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));
+ if (!externSubnet.isValidIP(floatingIP))
+ return Response.status(400).build();
+ if (externSubnet.isIPInUse(floatingIP))
+ return Response.status(409).build();
+ }
+ // if port_id is specified, then check that the port exists and has at least one IP
+ String port_id = singleton.getPortUUID();
+ if (port_id != null) {
+ String fixedIP = null; // used for the fixedIP calculation
+ if (!portInterface.portExists(port_id))
+ return Response.status(404).build();
+ NeutronPort port = portInterface.getPort(port_id);
+ if (port.getFixedIPs().size() < 1)
+ return Response.status(400).build();
+ // if there is more than one fixed IP then check for fixed_ip_address
+ // and that it is in the list of port addresses
+ if (port.getFixedIPs().size() > 1) {
+ fixedIP = singleton.getFixedIPAddress();
+ if (fixedIP == null)
+ return Response.status(400).build();
+ Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();
+ boolean validFixedIP = false;
+ while (i.hasNext() && !validFixedIP) {
+ Neutron_IPs ip = i.next();
+ if (ip.getIpAddress().equals(fixedIP))
+ validFixedIP = true;
+ }
+ if (!validFixedIP)
+ return Response.status(400).build();
+ } else {
+ fixedIP = port.getFixedIPs().get(0).getIpAddress();
+ if (singleton.getFixedIPAddress() != null && !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))
+ return Response.status(400).build();
+ }
+ //lastly check that this fixed IP address isn't already used
+ if (port.isBoundToFloatingIP(fixedIP))
+ return Response.status(409).build();
+ singleton.setFixedIPAddress(fixedIP);
+ }
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+ int status = service.canCreateFloatingIP(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ floatingIPInterface.addFloatingIP(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+ service.neutronFloatingIPCreated(singleton);
+ }
+ }
+ } else {
+ return Response.status(400).build();
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a FloatingIP */
+
+ @Path("{floatingipUUID}")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateFloatingIP(
+ @PathParam("floatingipUUID") String floatingipUUID,
+ NeutronFloatingIPRequest input
+ ) {
+ INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+ if (floatingIPInterface == null) {
+ throw new ServiceUnavailableException("Floating IP CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD( this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!floatingIPInterface.floatingIPExists(floatingipUUID))
+ return Response.status(404).build();
+
+ NeutronFloatingIP sourceFloatingIP = floatingIPInterface.getFloatingIP(floatingipUUID);
+ if (!input.isSingleton())
+ return Response.status(400).build();
+ NeutronFloatingIP singleton = input.getSingleton();
+ if (singleton.getID() != null)
+ return Response.status(400).build();
+
+ NeutronNetwork externNetwork = networkInterface.getNetwork(
+ sourceFloatingIP.getFloatingNetworkUUID());
+
+ // if floating IP is specified, make sure it can come from the network
+ String floatingIP = singleton.getFloatingIPAddress();
+ if (floatingIP != null) {
+ if (externNetwork.getSubnets().size() > 1)
+ return Response.status(400).build();
+ NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0));
+ if (!externSubnet.isValidIP(floatingIP))
+ return Response.status(400).build();
+ if (externSubnet.isIPInUse(floatingIP))
+ return Response.status(409).build();
+ }
+
+ // if port_id is specified, then check that the port exists and has at least one IP
+ String port_id = singleton.getPortUUID();
+ if (port_id != null) {
+ String fixedIP = null; // used for the fixedIP calculation
+ if (!portInterface.portExists(port_id))
+ return Response.status(404).build();
+ NeutronPort port = portInterface.getPort(port_id);
+ if (port.getFixedIPs().size() < 1)
+ return Response.status(400).build();
+ // if there is more than one fixed IP then check for fixed_ip_address
+ // and that it is in the list of port addresses
+ if (port.getFixedIPs().size() > 1) {
+ fixedIP = singleton.getFixedIPAddress();
+ if (fixedIP == null)
+ return Response.status(400).build();
+ Iterator<Neutron_IPs> i = port.getFixedIPs().iterator();
+ boolean validFixedIP = false;
+ while (i.hasNext() && !validFixedIP) {
+ Neutron_IPs ip = i.next();
+ if (ip.getIpAddress().equals(fixedIP))
+ validFixedIP = true;
+ }
+ if (!validFixedIP)
+ return Response.status(400).build();
+ } else {
+ fixedIP = port.getFixedIPs().get(0).getIpAddress();
+ if (singleton.getFixedIPAddress() != null &&
+ !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress()))
+ return Response.status(400).build();
+ }
+ //lastly check that this fixed IP address isn't already used
+ if (port.isBoundToFloatingIP(fixedIP))
+ return Response.status(409).build();
+ singleton.setFixedIPAddress(fixedIP);
+ }
+ NeutronFloatingIP target = floatingIPInterface.getFloatingIP(floatingipUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+ int status = service.canUpdateFloatingIP(singleton, target);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ floatingIPInterface.updateFloatingIP(floatingipUUID, singleton);
+ target = floatingIPInterface.getFloatingIP(floatingipUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+ service.neutronFloatingIPUpdated(target);
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronFloatingIPRequest(target)).build();
+
+ }
+
+ /**
+ * Deletes a FloatingIP */
+
+ @Path("{floatingipUUID}")
+ @DELETE
+ @StatusCodes({
+ @ResponseCode(code = 204, condition = "No Content"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response deleteFloatingIP(
+ @PathParam("floatingipUUID") String floatingipUUID) {
+ INeutronFloatingIPCRUD floatingIPInterface = NeutronCRUDInterfaces.getINeutronFloatingIPCRUD(this);
+ if (floatingIPInterface == null) {
+ throw new ServiceUnavailableException("Floating IP CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!floatingIPInterface.floatingIPExists(floatingipUUID))
+ return Response.status(404).build();
+ // TODO: need to undo port association if it exists
+ NeutronFloatingIP singleton = floatingIPInterface.getFloatingIP(floatingipUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+ int status = service.canDeleteFloatingIP(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ floatingIPInterface.removeFloatingIP(floatingipUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance;
+ service.neutronFloatingIPDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronNetworkRequest {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="network")\r
- NeutronNetwork singletonNetwork;\r
-\r
- @XmlElement(name="networks")\r
- List<NeutronNetwork> bulkRequest;\r
-\r
- NeutronNetworkRequest() {\r
- }\r
-\r
- NeutronNetworkRequest(List<NeutronNetwork> bulk) {\r
- bulkRequest = bulk;\r
- singletonNetwork = null;\r
- }\r
-\r
- NeutronNetworkRequest(NeutronNetwork net) {\r
- singletonNetwork = net;\r
- }\r
-\r
- public NeutronNetwork getSingleton() {\r
- return singletonNetwork;\r
- }\r
-\r
- public boolean isSingleton() {\r
- return (singletonNetwork != null);\r
- }\r
-\r
- public List<NeutronNetwork> getBulk() {\r
- return bulkRequest;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronNetworkRequest {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="network")
+ NeutronNetwork singletonNetwork;
+
+ @XmlElement(name="networks")
+ List<NeutronNetwork> bulkRequest;
+
+ NeutronNetworkRequest() {
+ }
+
+ NeutronNetworkRequest(List<NeutronNetwork> bulk) {
+ bulkRequest = bulk;
+ singletonNetwork = null;
+ }
+
+ NeutronNetworkRequest(NeutronNetwork net) {
+ singletonNetwork = net;
+ }
+
+ public NeutronNetwork getSingleton() {
+ return singletonNetwork;
+ }
+
+ public boolean isSingleton() {
+ return (singletonNetwork != null);
+ }
+
+ public List<NeutronNetwork> getBulk() {
+ return bulkRequest;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.codehaus.enunciate.jaxrs.TypeHint;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs for Network.<br>\r
- * This class provides REST APIs for managing open DOVE internals related to Networks\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/networks")\r
-public class NeutronNetworksNorthbound {\r
-\r
- private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {\r
- return o.extractFields(fields);\r
- }\r
-\r
- /**\r
- * Returns a list of all Networks */\r
-\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackNetworks.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized") })\r
- public Response listNetworks(\r
- // return fields\r
- @QueryParam("fields") List<String> fields,\r
- // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
- @QueryParam("id") String queryID,\r
- @QueryParam("name") String queryName,\r
- @QueryParam("admin_state_up") String queryAdminStateUp,\r
- @QueryParam("status") String queryStatus,\r
- @QueryParam("shared") String queryShared,\r
- @QueryParam("tenant_id") String queryTenantID,\r
- @QueryParam("router_external") String queryRouterExternal,\r
- @QueryParam("provider_network_type") String queryProviderNetworkType,\r
- @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,\r
- @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,\r
- // pagination\r
- @QueryParam("limit") String limit,\r
- @QueryParam("marker") String marker,\r
- @QueryParam("page_reverse") String pageReverse\r
- // sorting not supported\r
- ) {\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();\r
- List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();\r
- Iterator<NeutronNetwork> i = allNetworks.iterator();\r
- while (i.hasNext()) {\r
- NeutronNetwork oSN = i.next();\r
- //match filters: TODO provider extension\r
- Boolean bAdminStateUp = null;\r
- Boolean bShared = null;\r
- Boolean bRouterExternal = null;\r
- if (queryAdminStateUp != null)\r
- bAdminStateUp = Boolean.valueOf(queryAdminStateUp);\r
- if (queryShared != null)\r
- bShared = Boolean.valueOf(queryShared);\r
- if (queryRouterExternal != null)\r
- bRouterExternal = Boolean.valueOf(queryRouterExternal);\r
- if ((queryID == null || queryID.equals(oSN.getID())) &&\r
- (queryName == null || queryName.equals(oSN.getNetworkName())) &&\r
- (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&\r
- (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&\r
- (bShared == null || bShared.booleanValue() == oSN.isShared()) &&\r
- (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&\r
- (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {\r
- if (fields.size() > 0)\r
- ans.add(extractFields(oSN,fields));\r
- else\r
- ans.add(oSN);\r
- }\r
- }\r
- //TODO: apply pagination to results\r
- return Response.status(200).entity(\r
- new NeutronNetworkRequest(ans)).build();\r
- }\r
-\r
- /**\r
- * Returns a specific Network */\r
-\r
- @Path("{netUUID}")\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackNetworks.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found") })\r
- public Response showNetwork(\r
- @PathParam("netUUID") String netUUID,\r
- // return fields\r
- @QueryParam("fields") List<String> fields\r
- ) {\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!networkInterface.networkExists(netUUID))\r
- return Response.status(404).build();\r
- if (fields.size() > 0) {\r
- NeutronNetwork ans = networkInterface.getNetwork(netUUID);\r
- return Response.status(200).entity(\r
- new NeutronNetworkRequest(extractFields(ans, fields))).build();\r
- } else\r
- return Response.status(200).entity(\r
- new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
- }\r
-\r
- /**\r
- * Creates new Networks */\r
- @POST\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- @TypeHint(NeutronNetwork.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 201, condition = "Created"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized") })\r
- public Response createNetworks(final NeutronNetworkRequest input) {\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (input.isSingleton()) {\r
- NeutronNetwork singleton = input.getSingleton();\r
-\r
- /*\r
- * network ID can't already exist\r
- */\r
- if (networkInterface.networkExists(singleton.getID()))\r
- return Response.status(400).build();\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- int status = service.canCreateNetwork(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
-\r
- // add network to cache\r
- networkInterface.addNetwork(singleton);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- service.neutronNetworkCreated(singleton);\r
- }\r
- }\r
-\r
- } else {\r
- List<NeutronNetwork> bulk = input.getBulk();\r
- Iterator<NeutronNetwork> i = bulk.iterator();\r
- HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
- while (i.hasNext()) {\r
- NeutronNetwork test = i.next();\r
-\r
- /*\r
- * network ID can't already exist, nor can there be an entry for this UUID\r
- * already in this bulk request\r
- */\r
- if (networkInterface.networkExists(test.getID()))\r
- return Response.status(400).build();\r
- if (testMap.containsKey(test.getID()))\r
- return Response.status(400).build();\r
- if (instances != null) {\r
- for (Object instance: instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- int status = service.canCreateNetwork(test);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- testMap.put(test.getID(),test);\r
- }\r
-\r
- // now that everything passed, add items to the cache\r
- i = bulk.iterator();\r
- while (i.hasNext()) {\r
- NeutronNetwork test = i.next();\r
- test.initDefaults();\r
- networkInterface.addNetwork(test);\r
- if (instances != null) {\r
- for (Object instance: instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- service.neutronNetworkCreated(test);\r
- }\r
- }\r
- }\r
- }\r
- return Response.status(201).entity(input).build();\r
- }\r
-\r
- /**\r
- * Updates a Network */\r
- @Path("{netUUID}")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackNetworks.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"), })\r
- public Response updateNetwork(\r
- @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input\r
- ) {\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * network has to exist and only a single delta is supported\r
- */\r
- if (!networkInterface.networkExists(netUUID))\r
- return Response.status(404).build();\r
- if (!input.isSingleton())\r
- return Response.status(400).build();\r
- NeutronNetwork delta = input.getSingleton();\r
-\r
- /*\r
- * transitions forbidden by Neutron\r
- */\r
- if (delta.getID() != null || delta.getTenantID() != null ||\r
- delta.getStatus() != null)\r
- return Response.status(400).build();\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- NeutronNetwork original = networkInterface.getNetwork(netUUID);\r
- int status = service.canUpdateNetwork(delta, original);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
-\r
- // update network object and return the modified object\r
- networkInterface.updateNetwork(netUUID, delta);\r
- NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- service.neutronNetworkUpdated(updatedSingleton);\r
- }\r
- }\r
- return Response.status(200).entity(\r
- new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();\r
- }\r
-\r
- /**\r
- * Deletes a Network */\r
-\r
- @Path("{netUUID}")\r
- @DELETE\r
- @StatusCodes({\r
- @ResponseCode(code = 204, condition = "No Content"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Network In Use") })\r
- public Response deleteNetwork(\r
- @PathParam("netUUID") String netUUID) {\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * network has to exist and not be in use before it can be removed\r
- */\r
- if (!networkInterface.networkExists(netUUID))\r
- return Response.status(404).build();\r
- if (networkInterface.networkInUse(netUUID))\r
- return Response.status(409).build();\r
-\r
- NeutronNetwork singleton = networkInterface.getNetwork(netUUID);\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- int status = service.canDeleteNetwork(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- networkInterface.removeNetwork(netUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronNetworkAware service = (INeutronNetworkAware) instance;\r
- service.neutronNetworkDeleted(singleton);\r
- }\r
- }\r
- return Response.status(204).build();\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs for Network.<br>
+ * This class provides REST APIs for managing open DOVE internals related to Networks
+ *
+ * <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. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/networks")
+public class NeutronNetworksNorthbound {
+
+ private NeutronNetwork extractFields(NeutronNetwork o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all Networks */
+
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackNetworks.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized") })
+ public Response listNetworks(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // note: openstack isn't clear about filtering on lists, so we aren't handling them
+ @QueryParam("id") String queryID,
+ @QueryParam("name") String queryName,
+ @QueryParam("admin_state_up") String queryAdminStateUp,
+ @QueryParam("status") String queryStatus,
+ @QueryParam("shared") String queryShared,
+ @QueryParam("tenant_id") String queryTenantID,
+ @QueryParam("router_external") String queryRouterExternal,
+ @QueryParam("provider_network_type") String queryProviderNetworkType,
+ @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork,
+ @QueryParam("provider_segmentation_id") String queryProviderSegmentationID,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronNetwork> allNetworks = networkInterface.getAllNetworks();
+ List<NeutronNetwork> ans = new ArrayList<NeutronNetwork>();
+ Iterator<NeutronNetwork> i = allNetworks.iterator();
+ while (i.hasNext()) {
+ NeutronNetwork oSN = i.next();
+ //match filters: TODO provider extension
+ Boolean bAdminStateUp = null;
+ Boolean bShared = null;
+ Boolean bRouterExternal = null;
+ if (queryAdminStateUp != null)
+ bAdminStateUp = Boolean.valueOf(queryAdminStateUp);
+ if (queryShared != null)
+ bShared = Boolean.valueOf(queryShared);
+ if (queryRouterExternal != null)
+ bRouterExternal = Boolean.valueOf(queryRouterExternal);
+ if ((queryID == null || queryID.equals(oSN.getID())) &&
+ (queryName == null || queryName.equals(oSN.getNetworkName())) &&
+ (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) &&
+ (queryStatus == null || queryStatus.equals(oSN.getStatus())) &&
+ (bShared == null || bShared.booleanValue() == oSN.isShared()) &&
+ (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) &&
+ (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) {
+ if (fields.size() > 0)
+ ans.add(extractFields(oSN,fields));
+ else
+ ans.add(oSN);
+ }
+ }
+ //TODO: apply pagination to results
+ return Response.status(200).entity(
+ new NeutronNetworkRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific Network */
+
+ @Path("{netUUID}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackNetworks.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found") })
+ public Response showNetwork(
+ @PathParam("netUUID") String netUUID,
+ // return fields
+ @QueryParam("fields") List<String> fields
+ ) {
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!networkInterface.networkExists(netUUID))
+ return Response.status(404).build();
+ if (fields.size() > 0) {
+ NeutronNetwork ans = networkInterface.getNetwork(netUUID);
+ return Response.status(200).entity(
+ new NeutronNetworkRequest(extractFields(ans, fields))).build();
+ } else
+ return Response.status(200).entity(
+ new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
+ }
+
+ /**
+ * Creates new Networks */
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @TypeHint(NeutronNetwork.class)
+ @StatusCodes({
+ @ResponseCode(code = 201, condition = "Created"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized") })
+ public Response createNetworks(final NeutronNetworkRequest input) {
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronNetwork singleton = input.getSingleton();
+
+ /*
+ * network ID can't already exist
+ */
+ if (networkInterface.networkExists(singleton.getID()))
+ return Response.status(400).build();
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ int status = service.canCreateNetwork(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+
+ // add network to cache
+ networkInterface.addNetwork(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ service.neutronNetworkCreated(singleton);
+ }
+ }
+
+ } else {
+ List<NeutronNetwork> bulk = input.getBulk();
+ Iterator<NeutronNetwork> i = bulk.iterator();
+ HashMap<String, NeutronNetwork> testMap = new HashMap<String, NeutronNetwork>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronNetwork test = i.next();
+
+ /*
+ * network ID can't already exist, nor can there be an entry for this UUID
+ * already in this bulk request
+ */
+ if (networkInterface.networkExists(test.getID()))
+ return Response.status(400).build();
+ if (testMap.containsKey(test.getID()))
+ return Response.status(400).build();
+ if (instances != null) {
+ for (Object instance: instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ int status = service.canCreateNetwork(test);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ testMap.put(test.getID(),test);
+ }
+
+ // now that everything passed, add items to the cache
+ i = bulk.iterator();
+ while (i.hasNext()) {
+ NeutronNetwork test = i.next();
+ test.initDefaults();
+ networkInterface.addNetwork(test);
+ if (instances != null) {
+ for (Object instance: instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ service.neutronNetworkCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a Network */
+ @Path("{netUUID}")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackNetworks.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"), })
+ public Response updateNetwork(
+ @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input
+ ) {
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * network has to exist and only a single delta is supported
+ */
+ if (!networkInterface.networkExists(netUUID))
+ return Response.status(404).build();
+ if (!input.isSingleton())
+ return Response.status(400).build();
+ NeutronNetwork delta = input.getSingleton();
+
+ /*
+ * transitions forbidden by Neutron
+ */
+ if (delta.getID() != null || delta.getTenantID() != null ||
+ delta.getStatus() != null)
+ return Response.status(400).build();
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ NeutronNetwork original = networkInterface.getNetwork(netUUID);
+ int status = service.canUpdateNetwork(delta, original);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+
+ // update network object and return the modified object
+ networkInterface.updateNetwork(netUUID, delta);
+ NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ service.neutronNetworkUpdated(updatedSingleton);
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build();
+ }
+
+ /**
+ * Deletes a Network */
+
+ @Path("{netUUID}")
+ @DELETE
+ @StatusCodes({
+ @ResponseCode(code = 204, condition = "No Content"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Network In Use") })
+ public Response deleteNetwork(
+ @PathParam("netUUID") String netUUID) {
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * network has to exist and not be in use before it can be removed
+ */
+ if (!networkInterface.networkExists(netUUID))
+ return Response.status(404).build();
+ if (networkInterface.networkInUse(netUUID))
+ return Response.status(409).build();
+
+ NeutronNetwork singleton = networkInterface.getNetwork(netUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ int status = service.canDeleteNetwork(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ networkInterface.removeNetwork(netUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronNetworkAware service = (INeutronNetworkAware) instance;
+ service.neutronNetworkDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import javax.ws.rs.core.Application;\r
-import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;\r
-\r
-\r
-/**\r
- * This class is an instance of javax.ws.rs.core.Application and is used to return the classes\r
- * that will be instantiated for JAXRS processing. This is necessary\r
- * because package scanning in jersey doesn't yet work in OSGi environment.\r
- *\r
- */\r
-public class NeutronNorthboundRSApplication extends Application {\r
- @Override\r
- public Set<Class<?>> getClasses() {\r
- Set<Class<?>> classes = new HashSet<Class<?>>();\r
-// northbound URIs\r
- classes.add(NeutronNetworksNorthbound.class);\r
- classes.add(NeutronSubnetsNorthbound.class);\r
- classes.add(NeutronPortsNorthbound.class);\r
- classes.add(NeutronRoutersNorthbound.class);\r
- classes.add(NeutronFloatingIPsNorthbound.class);\r
- return classes;\r
- }\r
-\r
- @Override\r
- public Set<Object> getSingletons() {\r
- MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();\r
-\r
- moxyJsonProvider.setAttributePrefix("@");\r
- moxyJsonProvider.setFormattedOutput(true);\r
- moxyJsonProvider.setIncludeRoot(false);\r
- moxyJsonProvider.setMarshalEmptyCollections(true);\r
- moxyJsonProvider.setValueWrapper("$");\r
-\r
- Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);\r
- namespacePrefixMapper.put("router", "router"); // FIXME: fill in with XSD\r
- namespacePrefixMapper.put("provider", "provider"); // FIXME: fill in with XSD\r
- moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper);\r
- moxyJsonProvider.setNamespaceSeparator(':');\r
-\r
- HashSet<Object> set = new HashSet<Object>(1);\r
- set.add(moxyJsonProvider);\r
- return set;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.core.Application;
+import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
+
+
+/**
+ * This class is an instance of javax.ws.rs.core.Application and is used to return the classes
+ * that will be instantiated for JAXRS processing. This is necessary
+ * because package scanning in jersey doesn't yet work in OSGi environment.
+ *
+ */
+public class NeutronNorthboundRSApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+// northbound URIs
+ classes.add(NeutronNetworksNorthbound.class);
+ classes.add(NeutronSubnetsNorthbound.class);
+ classes.add(NeutronPortsNorthbound.class);
+ classes.add(NeutronRoutersNorthbound.class);
+ classes.add(NeutronFloatingIPsNorthbound.class);
+ return classes;
+ }
+
+ @Override
+ public Set<Object> getSingletons() {
+ MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
+
+ moxyJsonProvider.setAttributePrefix("@");
+ moxyJsonProvider.setFormattedOutput(true);
+ moxyJsonProvider.setIncludeRoot(false);
+ moxyJsonProvider.setMarshalEmptyCollections(true);
+ moxyJsonProvider.setValueWrapper("$");
+
+ Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);
+ namespacePrefixMapper.put("router", "router"); // FIXME: fill in with XSD
+ namespacePrefixMapper.put("provider", "provider"); // FIXME: fill in with XSD
+ moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper);
+ moxyJsonProvider.setNamespaceSeparator(':');
+
+ HashSet<Object> set = new HashSet<Object>(1);
+ set.add(moxyJsonProvider);
+ return set;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-public class NeutronPortRequest {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="port")\r
- NeutronPort singletonPort;\r
-\r
- @XmlElement(name="ports")\r
- List<NeutronPort> bulkRequest;\r
-\r
- NeutronPortRequest() {\r
- }\r
-\r
- NeutronPortRequest(List<NeutronPort> bulk) {\r
- bulkRequest = bulk;\r
- singletonPort = null;\r
- }\r
-\r
- NeutronPortRequest(NeutronPort port) {\r
- singletonPort = port;\r
- }\r
-\r
- public NeutronPort getSingleton() {\r
- return singletonPort;\r
- }\r
-\r
- public boolean isSingleton() {\r
- return (singletonPort != null);\r
- }\r
-\r
- public List<NeutronPort> getBulk() {\r
- return bulkRequest;\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class NeutronPortRequest {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="port")
+ NeutronPort singletonPort;
+
+ @XmlElement(name="ports")
+ List<NeutronPort> bulkRequest;
+
+ NeutronPortRequest() {
+ }
+
+ NeutronPortRequest(List<NeutronPort> bulk) {
+ bulkRequest = bulk;
+ singletonPort = null;
+ }
+
+ NeutronPortRequest(NeutronPort port) {
+ singletonPort = port;
+ }
+
+ public NeutronPort getSingleton() {
+ return singletonPort;
+ }
+
+ public boolean isSingleton() {
+ return (singletonPort != null);
+ }
+
+ public List<NeutronPort> getBulk() {
+ return bulkRequest;
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing the open DOVE\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/ports")\r
-public class NeutronPortsNorthbound {\r
-\r
- private NeutronPort extractFields(NeutronPort o, List<String> fields) {\r
- return o.extractFields(fields);\r
- }\r
-\r
- /**\r
- * Returns a list of all Ports */\r
-\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackPorts.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response listPorts(\r
- // return fields\r
- @QueryParam("fields") List<String> fields,\r
- // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
- @QueryParam("id") String queryID,\r
- @QueryParam("network_id") String queryNetworkID,\r
- @QueryParam("name") String queryName,\r
- @QueryParam("admin_state_up") String queryAdminStateUp,\r
- @QueryParam("status") String queryStatus,\r
- @QueryParam("mac_address") String queryMACAddress,\r
- @QueryParam("device_id") String queryDeviceID,\r
- @QueryParam("device_owner") String queryDeviceOwner,\r
- @QueryParam("tenant_id") String queryTenantID,\r
- // pagination\r
- @QueryParam("limit") String limit,\r
- @QueryParam("marker") String marker,\r
- @QueryParam("page_reverse") String pageReverse\r
- // sorting not supported\r
- ) {\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- List<NeutronPort> allPorts = portInterface.getAllPorts();\r
- List<NeutronPort> ans = new ArrayList<NeutronPort>();\r
- Iterator<NeutronPort> i = allPorts.iterator();\r
- while (i.hasNext()) {\r
- NeutronPort oSS = i.next();\r
- if ((queryID == null || queryID.equals(oSS.getID())) &&\r
- (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&\r
- (queryName == null || queryName.equals(oSS.getName())) &&\r
- (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&\r
- (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&\r
- (queryMACAddress == null || queryMACAddress.equals(oSS.getMacAddress())) &&\r
- (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) &&\r
- (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) &&\r
- (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
- if (fields.size() > 0)\r
- ans.add(extractFields(oSS,fields));\r
- else\r
- ans.add(oSS);\r
- }\r
- }\r
- //TODO: apply pagination to results\r
- return Response.status(200).entity(\r
- new NeutronPortRequest(ans)).build();\r
- }\r
-\r
- /**\r
- * Returns a specific Port */\r
-\r
- @Path("{portUUID}")\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackPorts.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response showPort(\r
- @PathParam("portUUID") String portUUID,\r
- // return fields\r
- @QueryParam("fields") List<String> fields ) {\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!portInterface.portExists(portUUID))\r
- return Response.status(404).build();\r
- if (fields.size() > 0) {\r
- NeutronPort ans = portInterface.getPort(portUUID);\r
- return Response.status(200).entity(\r
- new NeutronPortRequest(extractFields(ans, fields))).build();\r
- } else\r
- return Response.status(200).entity(\r
- new NeutronPortRequest(portInterface.getPort(portUUID))).build();\r
- }\r
-\r
- /**\r
- * Creates new Ports */\r
-\r
- @POST\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackPorts.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 201, condition = "Created"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented"),\r
- @ResponseCode(code = 503, condition = "MAC generation failure") })\r
- public Response createPorts(final NeutronPortRequest input) {\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (input.isSingleton()) {\r
- NeutronPort singleton = input.getSingleton();\r
-\r
- /*\r
- * the port must be part of an existing network, must not already exist,\r
- * have a valid MAC and the MAC not be in use\r
- */\r
- if (singleton.getNetworkUUID() == null)\r
- return Response.status(400).build();\r
- if (portInterface.portExists(singleton.getID()))\r
- return Response.status(400).build();\r
- if (!networkInterface.networkExists(singleton.getNetworkUUID()))\r
- return Response.status(404).build();\r
- if (singleton.getMacAddress() == null ||\r
- !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))\r
- return Response.status(400).build();\r
- if (portInterface.macInUse(singleton.getMacAddress()))\r
- return Response.status(409).build();\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- int status = service.canCreatePort(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- /*\r
- * if fixed IPs are specified, each one has to have an existing subnet ID\r
- * that is in the same scoping network as the port. In addition, if an IP\r
- * address is specified it has to be a valid address for the subnet and not\r
- * already in use\r
- */\r
- List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();\r
- if (fixedIPs != null && fixedIPs.size() > 0) {\r
- Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- if (ip.getSubnetUUID() == null)\r
- return Response.status(400).build();\r
- if (!subnetInterface.subnetExists(ip.getSubnetUUID()))\r
- return Response.status(400).build();\r
- NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());\r
- if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))\r
- return Response.status(400).build();\r
- if (ip.getIpAddress() != null) {\r
- if (!subnet.isValidIP(ip.getIpAddress()))\r
- return Response.status(400).build();\r
- if (subnet.isIPInUse(ip.getIpAddress()))\r
- return Response.status(409).build();\r
- }\r
- }\r
- }\r
-\r
- // add the port to the cache\r
- portInterface.addPort(singleton);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- service.neutronPortCreated(singleton);\r
- }\r
- }\r
- } else {\r
- List<NeutronPort> bulk = input.getBulk();\r
- Iterator<NeutronPort> i = bulk.iterator();\r
- HashMap<String, NeutronPort> testMap = new HashMap<String, NeutronPort>();\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
- while (i.hasNext()) {\r
- NeutronPort test = i.next();\r
-\r
- /*\r
- * the port must be part of an existing network, must not already exist,\r
- * have a valid MAC and the MAC not be in use. Further the bulk request\r
- * can't already contain a new port with the same UUID\r
- */\r
- if (portInterface.portExists(test.getID()))\r
- return Response.status(400).build();\r
- if (testMap.containsKey(test.getID()))\r
- return Response.status(400).build();\r
- for (NeutronPort check : testMap.values()) {\r
- if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress()))\r
- return Response.status(409).build();\r
- for (Neutron_IPs test_fixedIP : test.getFixedIPs()) {\r
- for (Neutron_IPs check_fixedIP : check.getFixedIPs()) {\r
- if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress()))\r
- return Response.status(409).build();\r
- }\r
- }\r
- }\r
- testMap.put(test.getID(), test);\r
- if (!networkInterface.networkExists(test.getNetworkUUID()))\r
- return Response.status(404).build();\r
- if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))\r
- return Response.status(400).build();\r
- if (portInterface.macInUse(test.getMacAddress()))\r
- return Response.status(409).build();\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- int status = service.canCreatePort(test);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- /*\r
- * if fixed IPs are specified, each one has to have an existing subnet ID\r
- * that is in the same scoping network as the port. In addition, if an IP\r
- * address is specified it has to be a valid address for the subnet and not\r
- * already in use (or be the gateway IP address of the subnet)\r
- */\r
- List<Neutron_IPs> fixedIPs = test.getFixedIPs();\r
- if (fixedIPs != null && fixedIPs.size() > 0) {\r
- Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- if (ip.getSubnetUUID() == null)\r
- return Response.status(400).build();\r
- if (!subnetInterface.subnetExists(ip.getSubnetUUID()))\r
- return Response.status(400).build();\r
- NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());\r
- if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))\r
- return Response.status(400).build();\r
- if (ip.getIpAddress() != null) {\r
- if (!subnet.isValidIP(ip.getIpAddress()))\r
- return Response.status(400).build();\r
- //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the\r
- //same bulk create\r
- if (subnet.isIPInUse(ip.getIpAddress()))\r
- return Response.status(409).build();\r
- }\r
- }\r
- }\r
- }\r
-\r
- //once everything has passed, then we can add to the cache\r
- i = bulk.iterator();\r
- while (i.hasNext()) {\r
- NeutronPort test = i.next();\r
- portInterface.addPort(test);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- service.neutronPortCreated(test);\r
- }\r
- }\r
- }\r
- }\r
- return Response.status(201).entity(input).build();\r
- }\r
-\r
- /**\r
- * Updates a Port */\r
-\r
- @Path("{portUUID}")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackPorts.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response updatePort(\r
- @PathParam("portUUID") String portUUID,\r
- NeutronPortRequest input\r
- ) {\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- // port has to exist and only a single delta is supported\r
- if (!portInterface.portExists(portUUID))\r
- return Response.status(404).build();\r
- NeutronPort target = portInterface.getPort(portUUID);\r
- if (!input.isSingleton())\r
- return Response.status(400).build();\r
- NeutronPort singleton = input.getSingleton();\r
- NeutronPort original = portInterface.getPort(portUUID);\r
-\r
- // deltas restricted by Neutron\r
- if (singleton.getID() != null || singleton.getTenantID() != null ||\r
- singleton.getStatus() != null)\r
- return Response.status(400).build();\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- int status = service.canUpdatePort(singleton, original);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
-\r
- // Verify the new fixed ips are valid\r
- List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();\r
- if (fixedIPs != null && fixedIPs.size() > 0) {\r
- Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();\r
- while (fixedIPIterator.hasNext()) {\r
- Neutron_IPs ip = fixedIPIterator.next();\r
- if (ip.getSubnetUUID() == null)\r
- return Response.status(400).build();\r
- if (!subnetInterface.subnetExists(ip.getSubnetUUID()))\r
- return Response.status(400).build();\r
- NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());\r
- if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))\r
- return Response.status(400).build();\r
- if (ip.getIpAddress() != null) {\r
- if (!subnet.isValidIP(ip.getIpAddress()))\r
- return Response.status(400).build();\r
- if (subnet.isIPInUse(ip.getIpAddress()))\r
- return Response.status(409).build();\r
- }\r
- }\r
- }\r
-\r
-// TODO: Support change of security groups\r
- // update the port and return the modified object\r
- portInterface.updatePort(portUUID, singleton);\r
- NeutronPort updatedPort = portInterface.getPort(portUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- service.neutronPortUpdated(updatedPort);\r
- }\r
- }\r
- return Response.status(200).entity(\r
- new NeutronPortRequest(updatedPort)).build();\r
-\r
- }\r
-\r
- /**\r
- * Deletes a Port */\r
-\r
- @Path("{portUUID}")\r
- @DELETE\r
- @StatusCodes({\r
- @ResponseCode(code = 204, condition = "No Content"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response deletePort(\r
- @PathParam("portUUID") String portUUID) {\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- // port has to exist and not be owned by anyone. then it can be removed from the cache\r
- if (!portInterface.portExists(portUUID))\r
- return Response.status(404).build();\r
- NeutronPort port = portInterface.getPort(portUUID);\r
- if (port.getDeviceID() != null ||\r
- port.getDeviceOwner() != null)\r
- Response.status(403).build();\r
- NeutronPort singleton = portInterface.getPort(portUUID);\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- int status = service.canDeletePort(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- portInterface.removePort(portUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronPortAware service = (INeutronPortAware) instance;\r
- service.neutronPortDeleted(singleton);\r
- }\r
- }\r
- return Response.status(204).build();\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing the open DOVE
+ *
+ * <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. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/ports")
+public class NeutronPortsNorthbound {
+
+ private NeutronPort extractFields(NeutronPort o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all Ports */
+
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackPorts.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response listPorts(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // note: openstack isn't clear about filtering on lists, so we aren't handling them
+ @QueryParam("id") String queryID,
+ @QueryParam("network_id") String queryNetworkID,
+ @QueryParam("name") String queryName,
+ @QueryParam("admin_state_up") String queryAdminStateUp,
+ @QueryParam("status") String queryStatus,
+ @QueryParam("mac_address") String queryMACAddress,
+ @QueryParam("device_id") String queryDeviceID,
+ @QueryParam("device_owner") String queryDeviceOwner,
+ @QueryParam("tenant_id") String queryTenantID,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronPort> allPorts = portInterface.getAllPorts();
+ List<NeutronPort> ans = new ArrayList<NeutronPort>();
+ Iterator<NeutronPort> i = allPorts.iterator();
+ while (i.hasNext()) {
+ NeutronPort oSS = i.next();
+ if ((queryID == null || queryID.equals(oSS.getID())) &&
+ (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&
+ (queryName == null || queryName.equals(oSS.getName())) &&
+ (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
+ (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
+ (queryMACAddress == null || queryMACAddress.equals(oSS.getMacAddress())) &&
+ (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) &&
+ (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) &&
+ (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+ if (fields.size() > 0)
+ ans.add(extractFields(oSS,fields));
+ else
+ ans.add(oSS);
+ }
+ }
+ //TODO: apply pagination to results
+ return Response.status(200).entity(
+ new NeutronPortRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific Port */
+
+ @Path("{portUUID}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackPorts.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response showPort(
+ @PathParam("portUUID") String portUUID,
+ // return fields
+ @QueryParam("fields") List<String> fields ) {
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!portInterface.portExists(portUUID))
+ return Response.status(404).build();
+ if (fields.size() > 0) {
+ NeutronPort ans = portInterface.getPort(portUUID);
+ return Response.status(200).entity(
+ new NeutronPortRequest(extractFields(ans, fields))).build();
+ } else
+ return Response.status(200).entity(
+ new NeutronPortRequest(portInterface.getPort(portUUID))).build();
+ }
+
+ /**
+ * Creates new Ports */
+
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackPorts.class)
+ @StatusCodes({
+ @ResponseCode(code = 201, condition = "Created"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented"),
+ @ResponseCode(code = 503, condition = "MAC generation failure") })
+ public Response createPorts(final NeutronPortRequest input) {
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronPort singleton = input.getSingleton();
+
+ /*
+ * the port must be part of an existing network, must not already exist,
+ * have a valid MAC and the MAC not be in use
+ */
+ if (singleton.getNetworkUUID() == null)
+ return Response.status(400).build();
+ if (portInterface.portExists(singleton.getID()))
+ return Response.status(400).build();
+ if (!networkInterface.networkExists(singleton.getNetworkUUID()))
+ return Response.status(404).build();
+ if (singleton.getMacAddress() == null ||
+ !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))
+ return Response.status(400).build();
+ if (portInterface.macInUse(singleton.getMacAddress()))
+ return Response.status(409).build();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ int status = service.canCreatePort(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ /*
+ * if fixed IPs are specified, each one has to have an existing subnet ID
+ * that is in the same scoping network as the port. In addition, if an IP
+ * address is specified it has to be a valid address for the subnet and not
+ * already in use
+ */
+ List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();
+ if (fixedIPs != null && fixedIPs.size() > 0) {
+ Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
+ while (fixedIPIterator.hasNext()) {
+ Neutron_IPs ip = fixedIPIterator.next();
+ if (ip.getSubnetUUID() == null)
+ return Response.status(400).build();
+ if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+ return Response.status(400).build();
+ NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
+ if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+ return Response.status(400).build();
+ if (ip.getIpAddress() != null) {
+ if (!subnet.isValidIP(ip.getIpAddress()))
+ return Response.status(400).build();
+ if (subnet.isIPInUse(ip.getIpAddress()))
+ return Response.status(409).build();
+ }
+ }
+ }
+
+ // add the port to the cache
+ portInterface.addPort(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ service.neutronPortCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronPort> bulk = input.getBulk();
+ Iterator<NeutronPort> i = bulk.iterator();
+ HashMap<String, NeutronPort> testMap = new HashMap<String, NeutronPort>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronPort test = i.next();
+
+ /*
+ * the port must be part of an existing network, must not already exist,
+ * have a valid MAC and the MAC not be in use. Further the bulk request
+ * can't already contain a new port with the same UUID
+ */
+ if (portInterface.portExists(test.getID()))
+ return Response.status(400).build();
+ if (testMap.containsKey(test.getID()))
+ return Response.status(400).build();
+ for (NeutronPort check : testMap.values()) {
+ if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress()))
+ return Response.status(409).build();
+ for (Neutron_IPs test_fixedIP : test.getFixedIPs()) {
+ for (Neutron_IPs check_fixedIP : check.getFixedIPs()) {
+ if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress()))
+ return Response.status(409).build();
+ }
+ }
+ }
+ testMap.put(test.getID(), test);
+ if (!networkInterface.networkExists(test.getNetworkUUID()))
+ return Response.status(404).build();
+ if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$"))
+ return Response.status(400).build();
+ if (portInterface.macInUse(test.getMacAddress()))
+ return Response.status(409).build();
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ int status = service.canCreatePort(test);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ /*
+ * if fixed IPs are specified, each one has to have an existing subnet ID
+ * that is in the same scoping network as the port. In addition, if an IP
+ * address is specified it has to be a valid address for the subnet and not
+ * already in use (or be the gateway IP address of the subnet)
+ */
+ List<Neutron_IPs> fixedIPs = test.getFixedIPs();
+ if (fixedIPs != null && fixedIPs.size() > 0) {
+ Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
+ while (fixedIPIterator.hasNext()) {
+ Neutron_IPs ip = fixedIPIterator.next();
+ if (ip.getSubnetUUID() == null)
+ return Response.status(400).build();
+ if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+ return Response.status(400).build();
+ NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
+ if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+ return Response.status(400).build();
+ if (ip.getIpAddress() != null) {
+ if (!subnet.isValidIP(ip.getIpAddress()))
+ return Response.status(400).build();
+ //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the
+ //same bulk create
+ if (subnet.isIPInUse(ip.getIpAddress()))
+ return Response.status(409).build();
+ }
+ }
+ }
+ }
+
+ //once everything has passed, then we can add to the cache
+ i = bulk.iterator();
+ while (i.hasNext()) {
+ NeutronPort test = i.next();
+ portInterface.addPort(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ service.neutronPortCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a Port */
+
+ @Path("{portUUID}")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackPorts.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updatePort(
+ @PathParam("portUUID") String portUUID,
+ NeutronPortRequest input
+ ) {
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ // port has to exist and only a single delta is supported
+ if (!portInterface.portExists(portUUID))
+ return Response.status(404).build();
+ NeutronPort target = portInterface.getPort(portUUID);
+ if (!input.isSingleton())
+ return Response.status(400).build();
+ NeutronPort singleton = input.getSingleton();
+ NeutronPort original = portInterface.getPort(portUUID);
+
+ // deltas restricted by Neutron
+ if (singleton.getID() != null || singleton.getTenantID() != null ||
+ singleton.getStatus() != null)
+ return Response.status(400).build();
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ int status = service.canUpdatePort(singleton, original);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+
+ // Verify the new fixed ips are valid
+ List<Neutron_IPs> fixedIPs = singleton.getFixedIPs();
+ if (fixedIPs != null && fixedIPs.size() > 0) {
+ Iterator<Neutron_IPs> fixedIPIterator = fixedIPs.iterator();
+ while (fixedIPIterator.hasNext()) {
+ Neutron_IPs ip = fixedIPIterator.next();
+ if (ip.getSubnetUUID() == null)
+ return Response.status(400).build();
+ if (!subnetInterface.subnetExists(ip.getSubnetUUID()))
+ return Response.status(400).build();
+ NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID());
+ if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID()))
+ return Response.status(400).build();
+ if (ip.getIpAddress() != null) {
+ if (!subnet.isValidIP(ip.getIpAddress()))
+ return Response.status(400).build();
+ if (subnet.isIPInUse(ip.getIpAddress()))
+ return Response.status(409).build();
+ }
+ }
+ }
+
+// TODO: Support change of security groups
+ // update the port and return the modified object
+ portInterface.updatePort(portUUID, singleton);
+ NeutronPort updatedPort = portInterface.getPort(portUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ service.neutronPortUpdated(updatedPort);
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronPortRequest(updatedPort)).build();
+
+ }
+
+ /**
+ * Deletes a Port */
+
+ @Path("{portUUID}")
+ @DELETE
+ @StatusCodes({
+ @ResponseCode(code = 204, condition = "No Content"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response deletePort(
+ @PathParam("portUUID") String portUUID) {
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ // port has to exist and not be owned by anyone. then it can be removed from the cache
+ if (!portInterface.portExists(portUUID))
+ return Response.status(404).build();
+ NeutronPort port = portInterface.getPort(portUUID);
+ if (port.getDeviceID() != null ||
+ port.getDeviceOwner() != null)
+ Response.status(403).build();
+ NeutronPort singleton = portInterface.getPort(portUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ int status = service.canDeletePort(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ portInterface.removePort(portUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronPortAware service = (INeutronPortAware) instance;
+ service.neutronPortDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
-\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronRouterRequest {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="router")\r
- NeutronRouter singletonRouter;\r
-\r
- @XmlElement(name="routers")\r
- List<NeutronRouter> bulkRequest;\r
-\r
- NeutronRouterRequest() {\r
- }\r
-\r
- NeutronRouterRequest(List<NeutronRouter> bulk) {\r
- bulkRequest = bulk;\r
- singletonRouter = null;\r
- }\r
-\r
- NeutronRouterRequest(NeutronRouter router) {\r
- singletonRouter = router;\r
- }\r
-\r
- public List<NeutronRouter> getBulk() {\r
- return bulkRequest;\r
- }\r
-\r
- public NeutronRouter getSingleton() {\r
- return singletonRouter;\r
- }\r
-\r
- public boolean isSingleton() {\r
- return (singletonRouter != null);\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronRouterRequest {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="router")
+ NeutronRouter singletonRouter;
+
+ @XmlElement(name="routers")
+ List<NeutronRouter> bulkRequest;
+
+ NeutronRouterRequest() {
+ }
+
+ NeutronRouterRequest(List<NeutronRouter> bulk) {
+ bulkRequest = bulk;
+ singletonRouter = null;
+ }
+
+ NeutronRouterRequest(NeutronRouter router) {
+ singletonRouter = router;
+ }
+
+ public List<NeutronRouter> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronRouter getSingleton() {
+ return singletonRouter;
+ }
+
+ public boolean isSingleton() {
+ return (singletonRouter != null);
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing the open DOVE\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/routers")\r
-public class NeutronRoutersNorthbound {\r
-\r
- private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {\r
- return o.extractFields(fields);\r
- }\r
-\r
- /**\r
- * Returns a list of all Routers */\r
-\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackRouters.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response listRouters(\r
- // return fields\r
- @QueryParam("fields") List<String> fields,\r
- // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
- @QueryParam("id") String queryID,\r
- @QueryParam("name") String queryName,\r
- @QueryParam("admin_state_up") String queryAdminStateUp,\r
- @QueryParam("status") String queryStatus,\r
- @QueryParam("tenant_id") String queryTenantID,\r
- @QueryParam("external_gateway_info") String queryExternalGatewayInfo,\r
- // pagination\r
- @QueryParam("limit") String limit,\r
- @QueryParam("marker") String marker,\r
- @QueryParam("page_reverse") String pageReverse\r
- // sorting not supported\r
- ) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- List<NeutronRouter> allRouters = routerInterface.getAllRouters();\r
- List<NeutronRouter> ans = new ArrayList<NeutronRouter>();\r
- Iterator<NeutronRouter> i = allRouters.iterator();\r
- while (i.hasNext()) {\r
- NeutronRouter oSS = i.next();\r
- if ((queryID == null || queryID.equals(oSS.getID())) &&\r
- (queryName == null || queryName.equals(oSS.getName())) &&\r
- (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&\r
- (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&\r
- (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&\r
- (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
- if (fields.size() > 0)\r
- ans.add(extractFields(oSS,fields));\r
- else\r
- ans.add(oSS);\r
- }\r
- }\r
- //TODO: apply pagination to results\r
- return Response.status(200).entity(\r
- new NeutronRouterRequest(ans)).build();\r
- }\r
-\r
- /**\r
- * Returns a specific Router */\r
-\r
- @Path("{routerUUID}")\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackRouters.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response showRouter(\r
- @PathParam("routerUUID") String routerUUID,\r
- // return fields\r
- @QueryParam("fields") List<String> fields) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!routerInterface.routerExists(routerUUID))\r
- return Response.status(404).build();\r
- if (fields.size() > 0) {\r
- NeutronRouter ans = routerInterface.getRouter(routerUUID);\r
- return Response.status(200).entity(\r
- new NeutronRouterRequest(extractFields(ans, fields))).build();\r
- } else\r
- return Response.status(200).entity(\r
- new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
- }\r
-\r
- /**\r
- * Creates new Routers */\r
-\r
- @POST\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackRouters.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 201, condition = "Created"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response createRouters(final NeutronRouterRequest input) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (input.isSingleton()) {\r
- NeutronRouter singleton = input.getSingleton();\r
-\r
- /*\r
- * verify that the router doesn't already exist (issue: is deeper inspection necessary?)\r
- * if there is external gateway information provided, verify that the specified network\r
- * exists and has been designated as "router:external"\r
- */\r
- if (routerInterface.routerExists(singleton.getID()))\r
- return Response.status(400).build();\r
- if (singleton.getExternalGatewayInfo() != null) {\r
- String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
- if (!networkInterface.networkExists(externNetworkPtr))\r
- return Response.status(400).build();\r
- NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
- if (!externNetwork.isRouterExternal())\r
- return Response.status(400).build();\r
- }\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- int status = service.canCreateRouter(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
-\r
- /*\r
- * add router to the cache\r
- */\r
- routerInterface.addRouter(singleton);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterCreated(singleton);\r
- }\r
- }\r
- } else {\r
-\r
- /*\r
- * only singleton router creates supported\r
- */\r
- return Response.status(400).build();\r
- }\r
- return Response.status(201).entity(input).build();\r
- }\r
-\r
- /**\r
- * Updates a Router */\r
-\r
- @Path("{routerUUID}")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackRouters.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response updateRouter(\r
- @PathParam("routerUUID") String routerUUID,\r
- NeutronRouterRequest input\r
- ) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * router has to exist and only a single delta can be supplied\r
- */\r
- if (!routerInterface.routerExists(routerUUID))\r
- return Response.status(404).build();\r
- if (!input.isSingleton())\r
- return Response.status(400).build();\r
- NeutronRouter singleton = input.getSingleton();\r
- NeutronRouter original = routerInterface.getRouter(routerUUID);\r
-\r
- /*\r
- * attribute changes blocked by Neutron\r
- */\r
- if (singleton.getID() != null || singleton.getTenantID() != null ||\r
- singleton.getStatus() != null)\r
- return Response.status(400).build();\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- int status = service.canUpdateRouter(singleton, original);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- /*\r
- * if the external gateway info is being changed, verify that the new network\r
- * exists and has been designated as an external network\r
- */\r
- if (singleton.getExternalGatewayInfo() != null) {\r
- String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();\r
- if (!networkInterface.networkExists(externNetworkPtr))\r
- return Response.status(400).build();\r
- NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);\r
- if (!externNetwork.isRouterExternal())\r
- return Response.status(400).build();\r
- }\r
-\r
- /*\r
- * update the router entry and return the modified object\r
- */\r
- routerInterface.updateRouter(routerUUID, singleton);\r
- NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterUpdated(updatedRouter);\r
- }\r
- }\r
- return Response.status(200).entity(\r
- new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();\r
-\r
- }\r
-\r
- /**\r
- * Deletes a Router */\r
-\r
- @Path("{routerUUID}")\r
- @DELETE\r
- @StatusCodes({\r
- @ResponseCode(code = 204, condition = "No Content"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response deleteRouter(\r
- @PathParam("routerUUID") String routerUUID) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * verify that the router exists and is not in use before removing it\r
- */\r
- if (!routerInterface.routerExists(routerUUID))\r
- return Response.status(404).build();\r
- if (routerInterface.routerInUse(routerUUID))\r
- return Response.status(409).build();\r
- NeutronRouter singleton = routerInterface.getRouter(routerUUID);\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- int status = service.canDeleteRouter(singleton);\r
- if (status < 200 || status > 299)\r
- return Response.status(status).build();\r
- }\r
- }\r
- routerInterface.removeRouter(routerUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterDeleted(singleton);\r
- }\r
- }\r
- return Response.status(204).build();\r
- }\r
-\r
- /**\r
- * Adds an interface to a router */\r
-\r
- @Path("{routerUUID}/add_router_interface")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackRouterInterfaces.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response addRouterInterface(\r
- @PathParam("routerUUID") String routerUUID,\r
- NeutronRouter_Interface input\r
- ) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id\r
- * or a port id, but not both, this code assumes that the plugin has filled everything in for us and so both must be present\r
- */\r
- if (!routerInterface.routerExists(routerUUID))\r
- return Response.status(400).build();\r
- NeutronRouter target = routerInterface.getRouter(routerUUID);\r
- if (input.getSubnetUUID() == null ||\r
- input.getPortUUID() == null)\r
- return Response.status(400).build();\r
-\r
- // check that the port is part of the subnet\r
- NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
- if (targetSubnet == null)\r
- return Response.status(400).build();\r
- NeutronPort targetPort = portInterface.getPort(input.getPortUUID());\r
- if (targetPort == null)\r
- return Response.status(400).build();\r
- if (!targetSubnet.getPortsInSubnet().contains(targetPort))\r
- return Response.status(400).build();\r
-\r
- if (targetPort.getFixedIPs().size() != 1)\r
- return Response.status(400).build();\r
- if (targetPort.getDeviceID() != null ||\r
- targetPort.getDeviceOwner() != null)\r
- return Response.status(409).build();\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.canAttachInterface(target, input);\r
- }\r
- }\r
-\r
- //mark the port device id and device owner fields\r
- targetPort.setDeviceOwner("network:router_interface");\r
- targetPort.setDeviceID(routerUUID);\r
-\r
- target.addInterface(input.getPortUUID(), input);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterInterfaceAttached(target, input);\r
- }\r
- }\r
-\r
- return Response.status(200).entity(input).build();\r
- }\r
-\r
- /**\r
- * Removes an interface to a router */\r
-\r
- @Path("{routerUUID}/remove_router_interface")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackRouterInterfaces.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response removeRouterInterface(\r
- @PathParam("routerUUID") String routerUUID,\r
- NeutronRouter_Interface input\r
- ) {\r
- INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);\r
- if (routerInterface == null) {\r
- throw new ServiceUnavailableException("Router CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);\r
- if (portInterface == null) {\r
- throw new ServiceUnavailableException("Port CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- // verify the router exists\r
- if (!routerInterface.routerExists(routerUUID))\r
- return Response.status(400).build();\r
- NeutronRouter target = routerInterface.getRouter(routerUUID);\r
-\r
- /*\r
- * remove by subnet id. Collect information about the impacted router for the response and\r
- * remove the port corresponding to the gateway IP address of the subnet\r
- */\r
- if (input.getPortUUID() == null &&\r
- input.getSubnetUUID() != null) {\r
- NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());\r
- if (port == null)\r
- return Response.status(404).build();\r
- input.setPortUUID(port.getID());\r
- input.setID(target.getID());\r
- input.setTenantID(target.getTenantID());\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.canDetachInterface(target, input);\r
- }\r
- }\r
-\r
- // reset the port ownership\r
- port.setDeviceID(null);\r
- port.setDeviceOwner(null);\r
-\r
- target.removeInterface(input.getPortUUID());\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterInterfaceDetached(target, input);\r
- }\r
- }\r
- return Response.status(200).entity(input).build();\r
- }\r
-\r
- /*\r
- * remove by port id. collect information about the impacted router for the response\r
- * remove the interface and reset the port ownership\r
- */\r
- if (input.getPortUUID() != null &&\r
- input.getSubnetUUID() == null) {\r
- NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());\r
- input.setSubnetUUID(targetInterface.getSubnetUUID());\r
- input.setID(target.getID());\r
- input.setTenantID(target.getTenantID());\r
- NeutronPort port = portInterface.getPort(input.getPortUUID());\r
- port.setDeviceID(null);\r
- port.setDeviceOwner(null);\r
- target.removeInterface(input.getPortUUID());\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterInterfaceDetached(target, input);\r
- }\r
- return Response.status(200).entity(input).build();\r
- }\r
-\r
- /*\r
- * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid\r
- * IP address for the subnet, and then remove the interface, collecting information about the\r
- * impacted router for the response and reset port ownership\r
- */\r
- if (input.getPortUUID() != null &&\r
- input.getSubnetUUID() != null) {\r
- NeutronPort port = portInterface.getPort(input.getPortUUID());\r
- NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());\r
- if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))\r
- return Response.status(409).build();\r
- input.setID(target.getID());\r
- input.setTenantID(target.getTenantID());\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.canDetachInterface(target, input);\r
- }\r
- }\r
- port.setDeviceID(null);\r
- port.setDeviceOwner(null);\r
- target.removeInterface(input.getPortUUID());\r
- for (Object instance : instances) {\r
- INeutronRouterAware service = (INeutronRouterAware) instance;\r
- service.neutronRouterInterfaceDetached(target, input);\r
- }\r
- return Response.status(200).entity(input).build();\r
- }\r
-\r
- // have to specify either a port ID or a subnet ID\r
- return Response.status(400).build();\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
+import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
+import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing the open DOVE
+ *
+ * <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. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/routers")
+public class NeutronRoutersNorthbound {
+
+ private NeutronRouter extractFields(NeutronRouter o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all Routers */
+
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackRouters.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response listRouters(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // note: openstack isn't clear about filtering on lists, so we aren't handling them
+ @QueryParam("id") String queryID,
+ @QueryParam("name") String queryName,
+ @QueryParam("admin_state_up") String queryAdminStateUp,
+ @QueryParam("status") String queryStatus,
+ @QueryParam("tenant_id") String queryTenantID,
+ @QueryParam("external_gateway_info") String queryExternalGatewayInfo,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronRouter> allRouters = routerInterface.getAllRouters();
+ List<NeutronRouter> ans = new ArrayList<NeutronRouter>();
+ Iterator<NeutronRouter> i = allRouters.iterator();
+ while (i.hasNext()) {
+ NeutronRouter oSS = i.next();
+ if ((queryID == null || queryID.equals(oSS.getID())) &&
+ (queryName == null || queryName.equals(oSS.getName())) &&
+ (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) &&
+ (queryStatus == null || queryStatus.equals(oSS.getStatus())) &&
+ (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) &&
+ (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+ if (fields.size() > 0)
+ ans.add(extractFields(oSS,fields));
+ else
+ ans.add(oSS);
+ }
+ }
+ //TODO: apply pagination to results
+ return Response.status(200).entity(
+ new NeutronRouterRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific Router */
+
+ @Path("{routerUUID}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackRouters.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response showRouter(
+ @PathParam("routerUUID") String routerUUID,
+ // return fields
+ @QueryParam("fields") List<String> fields) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!routerInterface.routerExists(routerUUID))
+ return Response.status(404).build();
+ if (fields.size() > 0) {
+ NeutronRouter ans = routerInterface.getRouter(routerUUID);
+ return Response.status(200).entity(
+ new NeutronRouterRequest(extractFields(ans, fields))).build();
+ } else
+ return Response.status(200).entity(
+ new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
+ }
+
+ /**
+ * Creates new Routers */
+
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackRouters.class)
+ @StatusCodes({
+ @ResponseCode(code = 201, condition = "Created"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createRouters(final NeutronRouterRequest input) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronRouter singleton = input.getSingleton();
+
+ /*
+ * verify that the router doesn't already exist (issue: is deeper inspection necessary?)
+ * if there is external gateway information provided, verify that the specified network
+ * exists and has been designated as "router:external"
+ */
+ if (routerInterface.routerExists(singleton.getID()))
+ return Response.status(400).build();
+ if (singleton.getExternalGatewayInfo() != null) {
+ String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
+ if (!networkInterface.networkExists(externNetworkPtr))
+ return Response.status(400).build();
+ NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
+ if (!externNetwork.isRouterExternal())
+ return Response.status(400).build();
+ }
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ int status = service.canCreateRouter(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+
+ /*
+ * add router to the cache
+ */
+ routerInterface.addRouter(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterCreated(singleton);
+ }
+ }
+ } else {
+
+ /*
+ * only singleton router creates supported
+ */
+ return Response.status(400).build();
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a Router */
+
+ @Path("{routerUUID}")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackRouters.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateRouter(
+ @PathParam("routerUUID") String routerUUID,
+ NeutronRouterRequest input
+ ) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * router has to exist and only a single delta can be supplied
+ */
+ if (!routerInterface.routerExists(routerUUID))
+ return Response.status(404).build();
+ if (!input.isSingleton())
+ return Response.status(400).build();
+ NeutronRouter singleton = input.getSingleton();
+ NeutronRouter original = routerInterface.getRouter(routerUUID);
+
+ /*
+ * attribute changes blocked by Neutron
+ */
+ if (singleton.getID() != null || singleton.getTenantID() != null ||
+ singleton.getStatus() != null)
+ return Response.status(400).build();
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ int status = service.canUpdateRouter(singleton, original);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ /*
+ * if the external gateway info is being changed, verify that the new network
+ * exists and has been designated as an external network
+ */
+ if (singleton.getExternalGatewayInfo() != null) {
+ String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID();
+ if (!networkInterface.networkExists(externNetworkPtr))
+ return Response.status(400).build();
+ NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr);
+ if (!externNetwork.isRouterExternal())
+ return Response.status(400).build();
+ }
+
+ /*
+ * update the router entry and return the modified object
+ */
+ routerInterface.updateRouter(routerUUID, singleton);
+ NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterUpdated(updatedRouter);
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build();
+
+ }
+
+ /**
+ * Deletes a Router */
+
+ @Path("{routerUUID}")
+ @DELETE
+ @StatusCodes({
+ @ResponseCode(code = 204, condition = "No Content"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response deleteRouter(
+ @PathParam("routerUUID") String routerUUID) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify that the router exists and is not in use before removing it
+ */
+ if (!routerInterface.routerExists(routerUUID))
+ return Response.status(404).build();
+ if (routerInterface.routerInUse(routerUUID))
+ return Response.status(409).build();
+ NeutronRouter singleton = routerInterface.getRouter(routerUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ int status = service.canDeleteRouter(singleton);
+ if (status < 200 || status > 299)
+ return Response.status(status).build();
+ }
+ }
+ routerInterface.removeRouter(routerUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+
+ /**
+ * Adds an interface to a router */
+
+ @Path("{routerUUID}/add_router_interface")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackRouterInterfaces.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response addRouterInterface(
+ @PathParam("routerUUID") String routerUUID,
+ NeutronRouter_Interface input
+ ) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id
+ * or a port id, but not both, this code assumes that the plugin has filled everything in for us and so both must be present
+ */
+ if (!routerInterface.routerExists(routerUUID))
+ return Response.status(400).build();
+ NeutronRouter target = routerInterface.getRouter(routerUUID);
+ if (input.getSubnetUUID() == null ||
+ input.getPortUUID() == null)
+ return Response.status(400).build();
+
+ // check that the port is part of the subnet
+ NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID());
+ if (targetSubnet == null)
+ return Response.status(400).build();
+ NeutronPort targetPort = portInterface.getPort(input.getPortUUID());
+ if (targetPort == null)
+ return Response.status(400).build();
+ if (!targetSubnet.getPortsInSubnet().contains(targetPort))
+ return Response.status(400).build();
+
+ if (targetPort.getFixedIPs().size() != 1)
+ return Response.status(400).build();
+ if (targetPort.getDeviceID() != null ||
+ targetPort.getDeviceOwner() != null)
+ return Response.status(409).build();
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.canAttachInterface(target, input);
+ }
+ }
+
+ //mark the port device id and device owner fields
+ targetPort.setDeviceOwner("network:router_interface");
+ targetPort.setDeviceID(routerUUID);
+
+ target.addInterface(input.getPortUUID(), input);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterInterfaceAttached(target, input);
+ }
+ }
+
+ return Response.status(200).entity(input).build();
+ }
+
+ /**
+ * Removes an interface to a router */
+
+ @Path("{routerUUID}/remove_router_interface")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackRouterInterfaces.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response removeRouterInterface(
+ @PathParam("routerUUID") String routerUUID,
+ NeutronRouter_Interface input
+ ) {
+ INeutronRouterCRUD routerInterface = NeutronCRUDInterfaces.getINeutronRouterCRUD(this);
+ if (routerInterface == null) {
+ throw new ServiceUnavailableException("Router CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronPortCRUD portInterface = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
+ if (portInterface == null) {
+ throw new ServiceUnavailableException("Port CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ // verify the router exists
+ if (!routerInterface.routerExists(routerUUID))
+ return Response.status(400).build();
+ NeutronRouter target = routerInterface.getRouter(routerUUID);
+
+ /*
+ * remove by subnet id. Collect information about the impacted router for the response and
+ * remove the port corresponding to the gateway IP address of the subnet
+ */
+ if (input.getPortUUID() == null &&
+ input.getSubnetUUID() != null) {
+ NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID());
+ if (port == null)
+ return Response.status(404).build();
+ input.setPortUUID(port.getID());
+ input.setID(target.getID());
+ input.setTenantID(target.getTenantID());
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.canDetachInterface(target, input);
+ }
+ }
+
+ // reset the port ownership
+ port.setDeviceID(null);
+ port.setDeviceOwner(null);
+
+ target.removeInterface(input.getPortUUID());
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterInterfaceDetached(target, input);
+ }
+ }
+ return Response.status(200).entity(input).build();
+ }
+
+ /*
+ * remove by port id. collect information about the impacted router for the response
+ * remove the interface and reset the port ownership
+ */
+ if (input.getPortUUID() != null &&
+ input.getSubnetUUID() == null) {
+ NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID());
+ input.setSubnetUUID(targetInterface.getSubnetUUID());
+ input.setID(target.getID());
+ input.setTenantID(target.getTenantID());
+ NeutronPort port = portInterface.getPort(input.getPortUUID());
+ port.setDeviceID(null);
+ port.setDeviceOwner(null);
+ target.removeInterface(input.getPortUUID());
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterInterfaceDetached(target, input);
+ }
+ return Response.status(200).entity(input).build();
+ }
+
+ /*
+ * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid
+ * IP address for the subnet, and then remove the interface, collecting information about the
+ * impacted router for the response and reset port ownership
+ */
+ if (input.getPortUUID() != null &&
+ input.getSubnetUUID() != null) {
+ NeutronPort port = portInterface.getPort(input.getPortUUID());
+ NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID());
+ if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress()))
+ return Response.status(409).build();
+ input.setID(target.getID());
+ input.setTenantID(target.getTenantID());
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.canDetachInterface(target, input);
+ }
+ }
+ port.setDeviceID(null);
+ port.setDeviceOwner(null);
+ target.removeInterface(input.getPortUUID());
+ for (Object instance : instances) {
+ INeutronRouterAware service = (INeutronRouterAware) instance;
+ service.neutronRouterInterfaceDetached(target, input);
+ }
+ return Response.status(200).entity(input).build();
+ }
+
+ // have to specify either a port ID or a subnet ID
+ return Response.status(400).build();
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-import java.util.List;\r
-\r
-import javax.xml.bind.annotation.XmlAccessType;\r
-import javax.xml.bind.annotation.XmlAccessorType;\r
-import javax.xml.bind.annotation.XmlElement;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-\r
-@XmlRootElement\r
-@XmlAccessorType(XmlAccessType.NONE)\r
-\r
-public class NeutronSubnetRequest {\r
- // See OpenStack Network API v2.0 Reference for description of\r
- // annotated attributes\r
-\r
- @XmlElement(name="subnet")\r
- NeutronSubnet singletonSubnet;\r
-\r
- @XmlElement(name="subnets")\r
- List<NeutronSubnet> bulkRequest;\r
-\r
- NeutronSubnetRequest() {\r
- }\r
-\r
- NeutronSubnetRequest(List<NeutronSubnet> bulk) {\r
- bulkRequest = bulk;\r
- singletonSubnet = null;\r
- }\r
-\r
- NeutronSubnetRequest(NeutronSubnet subnet) {\r
- singletonSubnet = subnet;\r
- }\r
-\r
- public NeutronSubnet getSingleton() {\r
- return singletonSubnet;\r
- }\r
-\r
- public List<NeutronSubnet> getBulk() {\r
- return bulkRequest;\r
- }\r
-\r
- public boolean isSingleton() {\r
- return (singletonSubnet != null);\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronSubnetRequest {
+ // See OpenStack Network API v2.0 Reference for description of
+ // annotated attributes
+
+ @XmlElement(name="subnet")
+ NeutronSubnet singletonSubnet;
+
+ @XmlElement(name="subnets")
+ List<NeutronSubnet> bulkRequest;
+
+ NeutronSubnetRequest() {
+ }
+
+ NeutronSubnetRequest(List<NeutronSubnet> bulk) {
+ bulkRequest = bulk;
+ singletonSubnet = null;
+ }
+
+ NeutronSubnetRequest(NeutronSubnet subnet) {
+ singletonSubnet = subnet;
+ }
+
+ public NeutronSubnet getSingleton() {
+ return singletonSubnet;
+ }
+
+ public List<NeutronSubnet> getBulk() {
+ return bulkRequest;
+ }
+
+ public boolean isSingleton() {
+ return (singletonSubnet != null);
+ }
+}
-/*\r
- * Copyright IBM Corporation, 2013. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.networkconfig.neutron.northbound;\r
-\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DELETE;\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.PUT;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-\r
-import org.codehaus.enunciate.jaxrs.ResponseCode;\r
-import org.codehaus.enunciate.jaxrs.StatusCodes;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;\r
-import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
-import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
-import org.opendaylight.controller.northbound.commons.RestMessages;\r
-import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;\r
-import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;\r
-import org.opendaylight.controller.sal.utils.ServiceHelper;\r
-\r
-/**\r
- * Open DOVE Northbound REST APIs.<br>\r
- * This class provides REST APIs for managing open DOVE internals related to Subnets\r
- *\r
- * <br>\r
- * <br>\r
- * Authentication scheme : <b>HTTP Basic</b><br>\r
- * Authentication realm : <b>opendaylight</b><br>\r
- * Transport : <b>HTTP and HTTPS</b><br>\r
- * <br>\r
- * HTTPS Authentication is disabled by default. Administrator can enable it in\r
- * tomcat-server.xml after adding a proper keystore / SSL certificate from a\r
- * trusted authority.<br>\r
- * More info :\r
- * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration\r
- *\r
- */\r
-\r
-@Path("/subnets")\r
-public class NeutronSubnetsNorthbound {\r
-\r
- private NeutronSubnet extractFields(NeutronSubnet o, List<String> fields) {\r
- return o.extractFields(fields);\r
- }\r
-\r
-\r
- /**\r
- * Returns a list of all Subnets */\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackSubnets.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response listSubnets(\r
- // return fields\r
- @QueryParam("fields") List<String> fields,\r
- // note: openstack isn't clear about filtering on lists, so we aren't handling them\r
- @QueryParam("id") String queryID,\r
- @QueryParam("network_id") String queryNetworkID,\r
- @QueryParam("name") String queryName,\r
- @QueryParam("ip_version") String queryIPVersion,\r
- @QueryParam("cidr") String queryCIDR,\r
- @QueryParam("gateway_ip") String queryGatewayIP,\r
- @QueryParam("enable_dhcp") String queryEnableDHCP,\r
- @QueryParam("tenant_id") String queryTenantID,\r
- // pagination\r
- @QueryParam("limit") String limit,\r
- @QueryParam("marker") String marker,\r
- @QueryParam("page_reverse") String pageReverse\r
- // sorting not supported\r
- ) {\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- List<NeutronSubnet> allNetworks = subnetInterface.getAllSubnets();\r
- List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();\r
- Iterator<NeutronSubnet> i = allNetworks.iterator();\r
- while (i.hasNext()) {\r
- NeutronSubnet oSS = i.next();\r
- if ((queryID == null || queryID.equals(oSS.getID())) &&\r
- (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&\r
- (queryName == null || queryName.equals(oSS.getName())) &&\r
- (queryIPVersion == null || queryIPVersion.equals(oSS.getIpVersion())) &&\r
- (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) &&\r
- (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) &&\r
- (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) &&\r
- (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {\r
- if (fields.size() > 0) {\r
- ans.add(extractFields(oSS,fields));\r
- } else {\r
- ans.add(oSS);\r
- }\r
- }\r
- }\r
- //TODO: apply pagination to results\r
- return Response.status(200).entity(\r
- new NeutronSubnetRequest(ans)).build();\r
- }\r
-\r
- /**\r
- * Returns a specific Subnet */\r
-\r
- @Path("{subnetUUID}")\r
- @GET\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackSubnets.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response showSubnet(\r
- @PathParam("subnetUUID") String subnetUUID,\r
- // return fields\r
- @QueryParam("fields") List<String> fields) {\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (!subnetInterface.subnetExists(subnetUUID)) {\r
- return Response.status(404).build();\r
- }\r
- if (fields.size() > 0) {\r
- NeutronSubnet ans = subnetInterface.getSubnet(subnetUUID);\r
- return Response.status(200).entity(\r
- new NeutronSubnetRequest(extractFields(ans, fields))).build();\r
- } else {\r
- return Response.status(200).entity(\r
- new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();\r
- }\r
- }\r
-\r
- /**\r
- * Creates new Subnets */\r
-\r
- @POST\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackSubnets.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 201, condition = "Created"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response createSubnets(final NeutronSubnetRequest input) {\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);\r
- if (networkInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
- if (input.isSingleton()) {\r
- NeutronSubnet singleton = input.getSingleton();\r
-\r
- /*\r
- * Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)\r
- * the specified network exists, the subnet has a valid network address,\r
- * and that the gateway IP doesn't overlap with the allocation pools\r
- * *then* add the subnet to the cache\r
- */\r
- if (subnetInterface.subnetExists(singleton.getID())) {\r
- return Response.status(400).build();\r
- }\r
- if (!networkInterface.networkExists(singleton.getNetworkUUID())) {\r
- return Response.status(404).build();\r
- }\r
- if (!singleton.isValidCIDR()) {\r
- return Response.status(400).build();\r
- }\r
- if (!singleton.initDefaults()) {\r
- throw new InternalServerErrorException("subnet object could not be initialized properly");\r
- }\r
- if (singleton.gatewayIP_Pool_overlap()) {\r
- return Response.status(409).build();\r
- }\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- int status = service.canCreateSubnet(singleton);\r
- if (status < 200 || status > 299) {\r
- return Response.status(status).build();\r
- }\r
- }\r
- }\r
- subnetInterface.addSubnet(singleton);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- service.neutronSubnetCreated(singleton);\r
- }\r
- }\r
- } else {\r
- List<NeutronSubnet> bulk = input.getBulk();\r
- Iterator<NeutronSubnet> i = bulk.iterator();\r
- HashMap<String, NeutronSubnet> testMap = new HashMap<String, NeutronSubnet>();\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
- while (i.hasNext()) {\r
- NeutronSubnet test = i.next();\r
-\r
- /*\r
- * Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)\r
- * the specified network exists, the subnet has a valid network address,\r
- * and that the gateway IP doesn't overlap with the allocation pools,\r
- * and that the bulk request doesn't already contain a subnet with this id\r
- */\r
-\r
- if (!test.initDefaults()) {\r
- throw new InternalServerErrorException("subnet object could not be initialized properly");\r
- }\r
- if (subnetInterface.subnetExists(test.getID())) {\r
- return Response.status(400).build();\r
- }\r
- if (testMap.containsKey(test.getID())) {\r
- return Response.status(400).build();\r
- }\r
- testMap.put(test.getID(), test);\r
- if (!networkInterface.networkExists(test.getNetworkUUID())) {\r
- return Response.status(404).build();\r
- }\r
- if (!test.isValidCIDR()) {\r
- return Response.status(400).build();\r
- }\r
- if (test.gatewayIP_Pool_overlap()) {\r
- return Response.status(409).build();\r
- }\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- int status = service.canCreateSubnet(test);\r
- if (status < 200 || status > 299) {\r
- return Response.status(status).build();\r
- }\r
- }\r
- }\r
- }\r
-\r
- /*\r
- * now, each element of the bulk request can be added to the cache\r
- */\r
- i = bulk.iterator();\r
- while (i.hasNext()) {\r
- NeutronSubnet test = i.next();\r
- subnetInterface.addSubnet(test);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- service.neutronSubnetCreated(test);\r
- }\r
- }\r
- }\r
- }\r
- return Response.status(201).entity(input).build();\r
- }\r
-\r
- /**\r
- * Updates a Subnet */\r
-\r
- @Path("{subnetUUID}")\r
- @PUT\r
- @Produces({ MediaType.APPLICATION_JSON })\r
- @Consumes({ MediaType.APPLICATION_JSON })\r
- //@TypeHint(OpenStackSubnets.class)\r
- @StatusCodes({\r
- @ResponseCode(code = 200, condition = "Operation successful"),\r
- @ResponseCode(code = 400, condition = "Bad Request"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 403, condition = "Forbidden"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response updateSubnet(\r
- @PathParam("subnetUUID") String subnetUUID, final NeutronSubnetRequest input\r
- ) {\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Subnet CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * verify the subnet exists and there is only one delta provided\r
- */\r
- if (!subnetInterface.subnetExists(subnetUUID)) {\r
- return Response.status(404).build();\r
- }\r
- if (!input.isSingleton()) {\r
- return Response.status(400).build();\r
- }\r
- NeutronSubnet delta = input.getSingleton();\r
- NeutronSubnet original = subnetInterface.getSubnet(subnetUUID);\r
-\r
- /*\r
- * updates restricted by Neutron\r
- */\r
- if (delta.getID() != null || delta.getTenantID() != null ||\r
- delta.getIpVersion() != null || delta.getCidr() != null ||\r
- delta.getAllocationPools() != null) {\r
- return Response.status(400).build();\r
- }\r
-\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- int status = service.canUpdateSubnet(delta, original);\r
- if (status < 200 || status > 299) {\r
- return Response.status(status).build();\r
- }\r
- }\r
- }\r
-\r
- /*\r
- * update the object and return it\r
- */\r
- subnetInterface.updateSubnet(subnetUUID, delta);\r
- NeutronSubnet updatedSubnet = subnetInterface.getSubnet(subnetUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- service.neutronSubnetUpdated(updatedSubnet);\r
- }\r
- }\r
- return Response.status(200).entity(\r
- new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();\r
- }\r
-\r
- /**\r
- * Deletes a Subnet */\r
-\r
- @Path("{subnetUUID}")\r
- @DELETE\r
- @StatusCodes({\r
- @ResponseCode(code = 204, condition = "No Content"),\r
- @ResponseCode(code = 401, condition = "Unauthorized"),\r
- @ResponseCode(code = 404, condition = "Not Found"),\r
- @ResponseCode(code = 409, condition = "Conflict"),\r
- @ResponseCode(code = 501, condition = "Not Implemented") })\r
- public Response deleteSubnet(\r
- @PathParam("subnetUUID") String subnetUUID) {\r
- INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);\r
- if (subnetInterface == null) {\r
- throw new ServiceUnavailableException("Network CRUD Interface "\r
- + RestMessages.SERVICEUNAVAILABLE.toString());\r
- }\r
-\r
- /*\r
- * verify the subnet exists and it isn't currently in use\r
- */\r
- if (!subnetInterface.subnetExists(subnetUUID)) {\r
- return Response.status(404).build();\r
- }\r
- if (subnetInterface.subnetInUse(subnetUUID)) {\r
- return Response.status(409).build();\r
- }\r
- NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID);\r
- Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- int status = service.canDeleteSubnet(singleton);\r
- if (status < 200 || status > 299) {\r
- return Response.status(status).build();\r
- }\r
- }\r
- }\r
-\r
- /*\r
- * remove it and return 204 status\r
- */\r
- subnetInterface.removeSubnet(subnetUUID);\r
- if (instances != null) {\r
- for (Object instance : instances) {\r
- INeutronSubnetAware service = (INeutronSubnetAware) instance;\r
- service.neutronSubnetDeleted(singleton);\r
- }\r
- }\r
- return Response.status(204).build();\r
- }\r
-}\r
+/*
+ * Copyright IBM Corporation, 2013. 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.networkconfig.neutron.northbound;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+/**
+ * Open DOVE Northbound REST APIs.<br>
+ * This class provides REST APIs for managing open DOVE internals related to Subnets
+ *
+ * <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. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+
+@Path("/subnets")
+public class NeutronSubnetsNorthbound {
+
+ private NeutronSubnet extractFields(NeutronSubnet o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+
+ /**
+ * Returns a list of all Subnets */
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackSubnets.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response listSubnets(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // note: openstack isn't clear about filtering on lists, so we aren't handling them
+ @QueryParam("id") String queryID,
+ @QueryParam("network_id") String queryNetworkID,
+ @QueryParam("name") String queryName,
+ @QueryParam("ip_version") String queryIPVersion,
+ @QueryParam("cidr") String queryCIDR,
+ @QueryParam("gateway_ip") String queryGatewayIP,
+ @QueryParam("enable_dhcp") String queryEnableDHCP,
+ @QueryParam("tenant_id") String queryTenantID,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronSubnet> allNetworks = subnetInterface.getAllSubnets();
+ List<NeutronSubnet> ans = new ArrayList<NeutronSubnet>();
+ Iterator<NeutronSubnet> i = allNetworks.iterator();
+ while (i.hasNext()) {
+ NeutronSubnet oSS = i.next();
+ if ((queryID == null || queryID.equals(oSS.getID())) &&
+ (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) &&
+ (queryName == null || queryName.equals(oSS.getName())) &&
+ (queryIPVersion == null || queryIPVersion.equals(oSS.getIpVersion())) &&
+ (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) &&
+ (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) &&
+ (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) &&
+ (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(oSS,fields));
+ } else {
+ ans.add(oSS);
+ }
+ }
+ }
+ //TODO: apply pagination to results
+ return Response.status(200).entity(
+ new NeutronSubnetRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific Subnet */
+
+ @Path("{subnetUUID}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackSubnets.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response showSubnet(
+ @PathParam("subnetUUID") String subnetUUID,
+ // return fields
+ @QueryParam("fields") List<String> fields) {
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!subnetInterface.subnetExists(subnetUUID)) {
+ return Response.status(404).build();
+ }
+ if (fields.size() > 0) {
+ NeutronSubnet ans = subnetInterface.getSubnet(subnetUUID);
+ return Response.status(200).entity(
+ new NeutronSubnetRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(
+ new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();
+ }
+ }
+
+ /**
+ * Creates new Subnets */
+
+ @POST
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackSubnets.class)
+ @StatusCodes({
+ @ResponseCode(code = 201, condition = "Created"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createSubnets(final NeutronSubnetRequest input) {
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ INeutronNetworkCRUD networkInterface = NeutronCRUDInterfaces.getINeutronNetworkCRUD( this);
+ if (networkInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronSubnet singleton = input.getSingleton();
+
+ /*
+ * Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)
+ * the specified network exists, the subnet has a valid network address,
+ * and that the gateway IP doesn't overlap with the allocation pools
+ * *then* add the subnet to the cache
+ */
+ if (subnetInterface.subnetExists(singleton.getID())) {
+ return Response.status(400).build();
+ }
+ if (!networkInterface.networkExists(singleton.getNetworkUUID())) {
+ return Response.status(404).build();
+ }
+ if (!singleton.isValidCIDR()) {
+ return Response.status(400).build();
+ }
+ if (!singleton.initDefaults()) {
+ throw new InternalServerErrorException("subnet object could not be initialized properly");
+ }
+ if (singleton.gatewayIP_Pool_overlap()) {
+ return Response.status(409).build();
+ }
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ int status = service.canCreateSubnet(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ subnetInterface.addSubnet(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ service.neutronSubnetCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronSubnet> bulk = input.getBulk();
+ Iterator<NeutronSubnet> i = bulk.iterator();
+ HashMap<String, NeutronSubnet> testMap = new HashMap<String, NeutronSubnet>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronSubnet test = i.next();
+
+ /*
+ * Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?)
+ * the specified network exists, the subnet has a valid network address,
+ * and that the gateway IP doesn't overlap with the allocation pools,
+ * and that the bulk request doesn't already contain a subnet with this id
+ */
+
+ if (!test.initDefaults()) {
+ throw new InternalServerErrorException("subnet object could not be initialized properly");
+ }
+ if (subnetInterface.subnetExists(test.getID())) {
+ return Response.status(400).build();
+ }
+ if (testMap.containsKey(test.getID())) {
+ return Response.status(400).build();
+ }
+ testMap.put(test.getID(), test);
+ if (!networkInterface.networkExists(test.getNetworkUUID())) {
+ return Response.status(404).build();
+ }
+ if (!test.isValidCIDR()) {
+ return Response.status(400).build();
+ }
+ if (test.gatewayIP_Pool_overlap()) {
+ return Response.status(409).build();
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ int status = service.canCreateSubnet(test);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ }
+
+ /*
+ * now, each element of the bulk request can be added to the cache
+ */
+ i = bulk.iterator();
+ while (i.hasNext()) {
+ NeutronSubnet test = i.next();
+ subnetInterface.addSubnet(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ service.neutronSubnetCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a Subnet */
+
+ @Path("{subnetUUID}")
+ @PUT
+ @Produces({ MediaType.APPLICATION_JSON })
+ @Consumes({ MediaType.APPLICATION_JSON })
+ //@TypeHint(OpenStackSubnets.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 400, condition = "Bad Request"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateSubnet(
+ @PathParam("subnetUUID") String subnetUUID, final NeutronSubnetRequest input
+ ) {
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Subnet CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the subnet exists and there is only one delta provided
+ */
+ if (!subnetInterface.subnetExists(subnetUUID)) {
+ return Response.status(404).build();
+ }
+ if (!input.isSingleton()) {
+ return Response.status(400).build();
+ }
+ NeutronSubnet delta = input.getSingleton();
+ NeutronSubnet original = subnetInterface.getSubnet(subnetUUID);
+
+ /*
+ * updates restricted by Neutron
+ */
+ if (delta.getID() != null || delta.getTenantID() != null ||
+ delta.getIpVersion() != null || delta.getCidr() != null ||
+ delta.getAllocationPools() != null) {
+ return Response.status(400).build();
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ int status = service.canUpdateSubnet(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ subnetInterface.updateSubnet(subnetUUID, delta);
+ NeutronSubnet updatedSubnet = subnetInterface.getSubnet(subnetUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ service.neutronSubnetUpdated(updatedSubnet);
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build();
+ }
+
+ /**
+ * Deletes a Subnet */
+
+ @Path("{subnetUUID}")
+ @DELETE
+ @StatusCodes({
+ @ResponseCode(code = 204, condition = "No Content"),
+ @ResponseCode(code = 401, condition = "Unauthorized"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response deleteSubnet(
+ @PathParam("subnetUUID") String subnetUUID) {
+ INeutronSubnetCRUD subnetInterface = NeutronCRUDInterfaces.getINeutronSubnetCRUD( this);
+ if (subnetInterface == null) {
+ throw new ServiceUnavailableException("Network CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the subnet exists and it isn't currently in use
+ */
+ if (!subnetInterface.subnetExists(subnetUUID)) {
+ return Response.status(404).build();
+ }
+ if (subnetInterface.subnetInUse(subnetUUID)) {
+ return Response.status(409).build();
+ }
+ NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ int status = service.canDeleteSubnet(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * remove it and return 204 status
+ */
+ subnetInterface.removeSubnet(subnetUUID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronSubnetAware service = (INeutronSubnetAware) instance;
+ service.neutronSubnetDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
- <version>0.5.1-SNAPSHOT</version>
+ <version>0.6.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
throw new AsynchronousCloseException();
}
- inBuffer.flip();
- msgs = factory.parseMessages(inBuffer);
- if (inBuffer.hasRemaining()) {
- inBuffer.compact();
- } else {
+ try {
+ inBuffer.flip();
+ msgs = factory.parseMessages(inBuffer);
+ if (inBuffer.hasRemaining()) {
+ inBuffer.compact();
+ } else {
+ inBuffer.clear();
+ }
+ } catch (Exception e) {
inBuffer.clear();
+ logger.debug("Caught exception: ", e);
}
return msgs;
}
peerNetData.position(), peerNetData.limit());
}
- peerAppData.flip();
- msgs = factory.parseMessages(peerAppData);
- if (peerAppData.hasRemaining()) {
- peerAppData.compact();
- } else {
+ try {
+ peerAppData.flip();
+ msgs = factory.parseMessages(peerAppData);
+ if (peerAppData.hasRemaining()) {
+ peerAppData.compact();
+ } else {
+ peerAppData.clear();
+ }
+ } catch (Exception e) {
peerAppData.clear();
+ logger.debug("Caught exception: ", e);
}
this.socket.register(this.selector, SelectionKey.OP_READ, this);
}
if (msgs == null) {
- logger.info("{} is down", this);
- reportSwitchStateChange(false);
return;
}
for (OFMessage msg : msgs) {
OFType type = msg.getType();
switch (type) {
case HELLO:
- // send feature request
- OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST);
- asyncFastSend(featureRequest);
- this.state = SwitchState.WAIT_FEATURES_REPLY;
- startSwitchTimer();
+ sendFeaturesRequest();
break;
case ECHO_REQUEST:
OFEchoReply echoReply = (OFEchoReply) factory.getMessage(OFType.ECHO_REPLY);
// respond immediately
asyncSendNow(echoReply, msg.getXid());
+
+ // send features request if not sent yet
+ sendFeaturesRequest();
break;
case ECHO_REPLY:
this.probeSent = false;
return this.sid;
}
+ private void sendFeaturesRequest() {
+ if (!isOperational() && (this.state != SwitchState.WAIT_FEATURES_REPLY)) {
+ // send feature request
+ OFMessage featureRequest = factory.getMessage(OFType.FEATURES_REQUEST);
+ asyncFastSend(featureRequest);
+ this.state = SwitchState.WAIT_FEATURES_REPLY;
+ startSwitchTimer();
+ }
+ }
+
private void processFeaturesReply(OFFeaturesReply reply) {
if (this.state == SwitchState.WAIT_FEATURES_REPLY) {
this.sid = reply.getDatapathId();
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
import org.opendaylight.controller.sal.action.ActionType;
import org.opendaylight.controller.sal.action.Controller;
import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Enqueue;
import org.opendaylight.controller.sal.action.Flood;
import org.opendaylight.controller.sal.action.FloodAll;
import org.opendaylight.controller.sal.action.HwPath;
return flow;
}
+ private static final Map<Integer, Class<? extends Action>> actionMap = new HashMap<Integer, Class<? extends Action>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(1 << 0, Output.class);
+ put(1 << 1, SetVlanId.class);
+ put(1 << 2, SetVlanPcp.class);
+ put(1 << 3, PopVlan.class);
+ put(1 << 4, SetDlSrc.class);
+ put(1 << 5, SetDlDst.class);
+ put(1 << 6, SetNwSrc.class);
+ put(1 << 7, SetNwDst.class);
+ put(1 << 8, SetNwTos.class);
+ put(1 << 9, SetTpSrc.class);
+ put(1 << 10, SetTpDst.class);
+ put(1 << 11, Enqueue.class);
+ }
+ };
+
+ /**
+ * Returns the supported flow actions for the netwrok node given the bitmask
+ * representing the actions the Openflow 1.0 switch supports
+ *
+ * @param ofActionBitmask
+ * OF 1.0 action bitmask
+ * @return The correspondent list of SAL Action classes
+ */
+ public static List<Class<? extends Action>> getFlowActions(int ofActionBitmask) {
+ List<Class<? extends Action>> list = new ArrayList<Class<? extends Action>>();
+
+ for (int i = 0; i < Integer.SIZE; i++) {
+ int index = 1 << i;
+ if ((index & ofActionBitmask) > 0) {
+ if (actionMap.containsKey(index)) {
+ list.add(actionMap.get(index));
+ }
+ }
+ }
+ // Add implicit SAL actions
+ list.add(Controller.class);
+ list.add(SwPath.class);
+ list.add(HwPath.class);
+ list.add(Drop.class);
+
+ return list;
+ }
+
}
import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitchStateListener;
+import org.opendaylight.controller.sal.action.SupportedFlowActions;
import org.opendaylight.controller.sal.connection.ConnectionLocality;
import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
-import org.opendaylight.controller.sal.core.Actions;
import org.opendaylight.controller.sal.core.Buffers;
import org.opendaylight.controller.sal.core.Capabilities;
import org.opendaylight.controller.sal.core.ContainerFlow;
props.add(c);
}
int act = sw.getActions();
- Actions a = new Actions(act);
+ SupportedFlowActions a = new SupportedFlowActions(FlowConverter.getFlowActions(act));
if (a != null) {
props.add(a);
}
--- /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.sal.action;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.sal.core.NodeConnector;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Enqueue extends Action {
+ private static final long serialVersionUID = 1L;
+ @XmlElement
+ private NodeConnector port;
+
+ /* Dummy constructor for JAXB */
+ @SuppressWarnings("unused")
+ private Enqueue() {
+ }
+
+ public Enqueue(NodeConnector port) {
+ type = ActionType.ENQUEUE;
+ this.port = port;
+ }
+
+ public NodeConnector getPort() {
+ return port;
+ }
+}
--- /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.sal.action;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.opendaylight.controller.sal.core.Property;
+
+/**
+ * @file SupportedFlowActions.java
+ *
+ * @brief Class representing the supported flow actions
+ *
+ * Describes the supported flow actions
+ */
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class SupportedFlowActions extends Property {
+ private static final long serialVersionUID = 1L;
+ public static final String SupportedFlowActionsPropName = "supportedFlowActions";
+ private List<Class<? extends Action>> actions;
+
+ private SupportedFlowActions() {
+ super(SupportedFlowActionsPropName);
+ this.actions = new ArrayList<Class<? extends Action>>();
+ }
+
+ public SupportedFlowActions(List<Class<? extends Action>> actions) {
+ super(SupportedFlowActionsPropName);
+ this.actions = new ArrayList<Class<? extends Action>>(actions);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ SupportedFlowActions other = (SupportedFlowActions) obj;
+ if (actions == null) {
+ if (other.actions != null) {
+ return false;
+ }
+ } else if (!actions.equals(other.actions)) {
+ return false;
+ }
+ return true;
+ }
+
+ public List<Class<? extends Action>> getActions() {
+ return new ArrayList<Class<? extends Action>>(this.actions);
+ }
+
+ @XmlElement(name = "value")
+ @Override
+ public String getStringValue() {
+ List<String> nameList = new ArrayList<String>();
+ for (Class<? extends Action> clazz : actions) {
+ nameList.add(clazz.getSimpleName());
+ }
+ Collections.sort(nameList);
+ return nameList.toString();
+ }
+
+ @Override
+ public Property clone() {
+ return new SupportedFlowActions(this.actions);
+ }
+
+ @Override
+ public String toString() {
+ return this.getStringValue();
+ }
+}
* @brief Class representing actions
*
* Describes supported actions
+ * @Deprecated This class is OF 1.0 specific. Use SupportedFlowActions instead.
*/
-
+@Deprecated
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Actions extends Property {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (!super.equals(obj))
+ }
+ if (!super.equals(obj)) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
Actions other = (Actions) obj;
- if (actionsValue != other.actionsValue)
+ if (actionsValue != other.actionsValue) {
return false;
+ }
return true;
}
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
<artifactId>junit</artifactId>
</dependency>
<dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
</dependency>
</dependencies>
</project>
private boolean isDefaultContainer = true;
private static final int REPLACE_RETRY = 1;
+ /* Information about the default subnet. If there have been no configured subnets, i.e.,
+ * subnets.size() == 0 or subnetsConfigList.size() == 0, then this subnet will be the
+ * only subnet returned. As soon as a user-configured subnet is created this one will
+ * vanish.
+ */
+ protected static SubnetConfig DEFAULT_SUBNETCONFIG;
+ protected static Subnet DEFAULT_SUBNET;
+ protected static String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
+ static{
+ DEFAULT_SUBNETCONFIG = new SubnetConfig(DEFAULT_SUBNET_NAME, "0.0.0.0/0", new ArrayList<String>());
+ DEFAULT_SUBNET = new Subnet(DEFAULT_SUBNETCONFIG);
+ }
+
public void notifySubnetChange(Subnet sub, boolean add) {
synchronized (switchManagerAware) {
for (Object subAware : switchManagerAware) {
@Override
public List<SubnetConfig> getSubnetsConfigList() {
- return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+ // if there are no subnets, return the default subnet
+ if(subnetsConfigList.size() == 0){
+ return Collections.singletonList(DEFAULT_SUBNETCONFIG);
+ }else{
+ return new ArrayList<SubnetConfig>(subnetsConfigList.values());
+ }
}
@Override
public SubnetConfig getSubnetConfig(String subnet) {
- return subnetsConfigList.get(subnet);
+ // if there are no subnets, return the default subnet
+ if(subnetsConfigList.size() == 0 && subnet == DEFAULT_SUBNET_NAME){
+ return DEFAULT_SUBNETCONFIG;
+ }else{
+ return subnetsConfigList.get(subnet);
+ }
}
private List<SpanConfig> getSpanConfigList(Node node) {
@Override
public Subnet getSubnetByNetworkAddress(InetAddress networkAddress) {
+ // if there are no subnets, return the default subnet
+ if (subnets.size() == 0) {
+ return DEFAULT_SUBNET;
+ }
+
Subnet sub;
Set<InetAddress> indices = subnets.keySet();
for (InetAddress i : indices) {
Set<Node> nodes = connectionManager.getLocalNodes();
List<NodeJsonBean> result = new LinkedList<NodeJsonBean>();
+ if (nodes == null) {
+ return result;
+ }
for (Node node : nodes) {
Description descriptionProperty = (Description) switchManager.getNodeProp(node, "description");
- String description = descriptionProperty.getValue();
+ String description = node.toString();
+ if (descriptionProperty != null) {
+ description = descriptionProperty.getValue();
+ }
NodeJsonBean nodeBean = new NodeJsonBean();
nodeBean.setNodeId(node.getNodeIDString());
nodeBean.setNodeType(node.getType());
return "forward:" + "/";
}
-}
\ No newline at end of file
+}
<module>opendaylight/commons/checkstyle</module>
<module>opendaylight/commons/opendaylight</module>
<module>opendaylight/commons/parent</module>
+ <module>opendaylight/commons/logback_settings</module>
</modules>
<profiles>
--- /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/maven-v4_0_0.xsd">
+ <!-- Get some common settings for the project we are using it in -->
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.thirdparty</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <relativePath>../commons/thirdparty</relativePath>
+ </parent>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>exificient</artifactId>
+ <version>0.9.2-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Embed-Dependency>*;scope=!provided;type=!pom;inline=false</Embed-Dependency>
+ <Embed-Transitive>false</Embed-Transitive>
+ <Export-Package>
+ com.siemens.ct.exi.*,
+ </Export-Package>
+ <Import-Package>
+ javax.xml.namespace,
+ javax.xml.parsers,
+ javax.xml.stream,
+ javax.xml.stream.events,
+ javax.xml.transform.sax,
+ org.apache.xerces.impl.xs,
+ org.apache.xerces.impl.xs.models,
+ org.apache.xerces.xni,
+ org.apache.xerces.xni.grammars,
+ org.apache.xerces.xni.parser,
+ org.apache.xerces.xs,
+ org.w3c.dom,
+ org.xml.sax,
+ org.xml.sax.ext,
+ org.xml.sax.helpers
+ </Import-Package>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>com.siemens.ct.exi</groupId>
+ <artifactId>exificient</artifactId>
+ <version>0.9.2</version>
+ </dependency>
+ </dependencies>
+
+</project>