<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-persister-features</artifactId>
- <version>${config.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>netconf-features</artifactId>
- <version>${netconf.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-features</artifactId>
- <version>${config.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-features</artifactId>
- <version>${config.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>features-odl-protocol-framework</artifactId>
- <version>${protocol-framework.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-features</artifactId>
- <version>${config.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<jsr305.api.version>2.0.1</jsr305.api.version>
<jsr311.api.version>1.1.1</jsr311.api.version>
<jsr311.v2.api.version>2.0</jsr311.v2.api.version>
- <junit.version>4.8.1</junit.version>
<karaf.branding.version>1.0.0-SNAPSHOT</karaf.branding.version>
<karaf.shell.version>3.0.0</karaf.shell.version>
<karaf.version>3.0.1</karaf.version>
<sonar.branch>${user.name}-private-view</sonar.branch>
<sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
<!-- Sonar properties using jacoco to retrieve integration test results -->
+ <sonar-jacoco-listeners.version>2.4</sonar-jacoco-listeners.version>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.language>java</sonar.language>
+ <sonar.jacoco.reportPath>target/code-coverage/jacoco.exec</sonar.jacoco.reportPath>
+ <sonar.jacoco.itReportPath>target/code-coverage/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.skippedModules>org.openflow.openflowj,net.sf.jung2,org.opendaylight.controller.protobuff.messages</sonar.skippedModules>
<spifly.version>1.0.0</spifly.version>
<spring-osgi.version>1.2.1</spring-osgi.version>
<spring-security-karaf.version>3.1.4.RELEASE</spring-security-karaf.version>
<spring-security.version>3.1.3.RELEASE</spring-security.version>
<spring.version>3.1.3.RELEASE</spring.version>
- <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2</sonar.skippedModules>
<statistics.northbound.version>0.4.2-SNAPSHOT</statistics.northbound.version>
<statisticsmanager.implementation.version>0.4.2-SNAPSHOT</statisticsmanager.implementation.version>
<statisticsmanager.version>0.5.1-SNAPSHOT</statisticsmanager.version>
<artifactId>akka-osgi_${scala.version}</artifactId>
<version>${akka.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-slf4j_${scala.version}</artifactId>
+ <version>${akka.version}</version>
+ </dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<artifactId>filter-valve</artifactId>
<version>${filtervalve.version}</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>flow-management-compatibility</artifactId>
- <version>${mdsal.version}</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>flowprogrammer.northbound</artifactId>
<artifactId>sal-distributed-datastore</artifactId>
<version>${mdsal.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-clustering-commons</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-clustering-config</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>model-flow-base</artifactId>
<version>${mdsal.version}</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <version>${mdsal.version}</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-service</artifactId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>${junit.version}</version>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.logback_settings</artifactId>
<version>${yangtools.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-features</artifactId>
+ <version>${config.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-odl-protocol-framework</artifactId>
+ <version>${protocol-framework.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-features</artifactId>
+ <version>${netconf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-features</artifactId>
+ <version>${config.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-netty-features</artifactId>
+ <version>${config.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-adsal</artifactId>
+ <version>${sal.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-features</artifactId>
+ <version>${mdsal.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
+ <dependencies>
+ <!-- Sonar -->
+ <dependency>
+ <groupId>org.codehaus.sonar-plugins.java</groupId>
+ <artifactId>sonar-jacoco-listeners</artifactId>
+ <version>${sonar-jacoco-listeners.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
<build>
<pluginManagement>
<plugins>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
+ <executions>
+ <execution>
+ <id>prepare-ut-agent</id>
+ <phase>process-test-classes</phase>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${sonar.jacoco.reportPath}</destFile>
+ <propertyName>jacoco.agent.ut.arg</propertyName>
+ </configuration>
+ </execution>
+ <execution>
+ <id>prepare-it-agent</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${sonar.jacoco.itReportPath}</destFile>
+ <propertyName>jacoco.agent.it.arg</propertyName>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
<plugin>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe.version}</version>
<configuration>
- <argLine>${testvm.argLine}</argLine>
+ <argLine>${testvm.argLine} ${jacoco.agent.it.arg}</argLine>
<systemProperties>
<property>
<name>logback.configurationFile</name>
<value>logback.xml</value>
</property>
</systemProperties>
+ <!-- Specific to generate mapping between tests and covered code -->
+ <properties>
+ <property>
+ <name>listener</name>
+ <value>org.sonar.java.jacoco.JUnitListener</value>
+ </property>
+ </properties>
</configuration>
<executions>
<execution>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
- <argLine>${testvm.argLine}</argLine>
+ <argLine>${testvm.argLine} ${jacoco.agent.ut.arg}</argLine>
<systemProperties>
<property>
<name>logback.configurationFile</name>
<value>logback.xml</value>
</property>
</systemProperties>
+ <!-- Specific to generate mapping between tests and covered code -->
+ <properties>
+ <property>
+ <name>listener</name>
+ <value>org.sonar.java.jacoco.JUnitListener</value>
+ </property>
+ </properties>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ </plugin>
</plugins>
</build>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <forkCount>1</forkCount>
- <reuseForks>false</reuseForks>
- <perCoreThreadCount>false</perCoreThreadCount>
- <threadCount>1</threadCount>
- </configuration>
- </plugin>
</plugins>
</build>
*/
package org.opendaylight.controller.config.manager.impl.osgi;
+import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.registerService;
+import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.wrap;
+
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.List;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanServer;
import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.CodecRegistryProvider;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSCPModuleInfoRegistry;
import org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanServer;
-import java.lang.management.ManagementFactory;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.registerService;
-import static org.opendaylight.controller.config.manager.impl.util.OsgiRegistrationUtil.wrap;
-
public class ConfigManagerActivator implements BundleActivator {
private final MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
private AutoCloseable autoCloseable;
@Override
- public void start(BundleContext context) {
+ public void start(final BundleContext context) {
ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();// the inner strategy is backed by thread context cl?
bundleTracker.open();
// register config registry to OSGi
+ AutoCloseable clsReg = registerService(context, moduleInfoBackedContext, GeneratedClassLoadingStrategy.class);
AutoCloseable configRegReg = registerService(context, configRegistry, ConfigRegistryImpl.class);
// register config registry to jmx
serviceTracker.open();
List<AutoCloseable> list = Arrays.asList(
- codecRegistryProvider, configRegistry, wrap(bundleTracker), configRegReg, configRegistryJMXRegistrator, wrap(serviceTracker));
+ codecRegistryProvider, clsReg,configRegistry, wrap(bundleTracker), configRegReg, configRegistryJMXRegistrator, wrap(serviceTracker));
autoCloseable = OsgiRegistrationUtil.aggregate(list);
}
@Override
- public void stop(BundleContext context) throws Exception {
+ public void stop(final BundleContext context) throws Exception {
autoCloseable.close();
}
}
*/
package org.opendaylight.controller.config.manager.impl.runtimembean;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
import java.lang.management.ManagementFactory;
import java.util.Map;
import org.opendaylight.controller.config.manager.impl.jmx.HierarchicalRuntimeBeanRegistrationImpl;
import org.opendaylight.controller.config.manager.impl.jmx.RootRuntimeBeanRegistratorImpl;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
public class RuntimeBeanRegistratorImplTest extends
AbstractLockedPlatformMBeanServerTest {
static final String module1 = "module1";
assertEquals(0, baseJMXRegistrator.getRegisteredObjectNames().size());
}
- protected void checkExists(ObjectName on) throws Exception {
+ protected void checkExists(final ObjectName on) throws Exception {
platformMBeanServer.getMBeanInfo(on);
}
- protected void checkNotExists(ObjectName on) throws Exception {
+ protected void checkNotExists(final ObjectName on) throws Exception {
try {
platformMBeanServer.getMBeanInfo(on);
fail();
}
private HierarchicalRuntimeBeanRegistration createAdditional(
- HierarchicalRuntimeBeanRegistrationImpl rootRegistration)
+ final HierarchicalRuntimeBeanRegistrationImpl rootRegistration)
throws Exception {
HierarchicalRuntimeBeanRegistrationImpl registration = rootRegistration
*/
package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
import java.util.Map;
+
import javax.management.ObjectName;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
<capability>urn:opendaylight:params:xml:ns:yang:controller:netty:timer?module=netty-timer&revision=2013-11-19</capability>
</required-capabilities>
<configuration>
-
+
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<module>
<name>singleton</name>
</module>
</modules>
-
+
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<service>
<type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-threadgroup</type>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <forkCount>1</forkCount>
- <reuseForks>false</reuseForks>
- <perCoreThreadCount>false</perCoreThreadCount>
- <threadCount>1</threadCount>
- </configuration>
- </plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <redirectTestOutputToFile>true</redirectTestOutputToFile>
- <parallel>classes</parallel>
- <forkCount>1C</forkCount>
- <reuseForks>false</reuseForks>
- <perCoreThreadCount>true</perCoreThreadCount>
- <threadCount>2</threadCount>
- </configuration>
- </plugin>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <forkCount>1</forkCount>
- <reuseForks>false</reuseForks>
- <perCoreThreadCount>false</perCoreThreadCount>
- </configuration>
- <executions>
- <execution>
- <id>default-test</id>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- <execution>
- <id>integration-tests</id>
- <goals>
- <goal>test</goal>
- </goals>
- <phase>integration-test</phase>
- <configuration>
- <includes>
- <include>**/org/opendaylight/controller/config/yangjmxgenerator/it/*.java</include>
- </includes>
- <skip>false</skip>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
</project>
<artifactId>yang-parser-impl</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest-core</artifactId>
- <version>1.1</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
*/
package org.opendaylight.controller.config.yangjmxgenerator;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.openmbean.SimpleType;
+
import org.junit.Test;
import org.mockito.Mockito;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import javax.management.openmbean.SimpleType;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static org.hamcrest.CoreMatchers.is;
-
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.doReturn;
-
public class RuntimeBeanEntryTest extends AbstractYangTest {
public static final String PACKAGE_NAME = "packages.sis";
Map<String, RuntimeBeanEntry> runtimeBeans = RuntimeBeanEntry
.extractClassNameToRuntimeBeanMap(PACKAGE_NAME, caseNode, "test-name", new TypeProviderWrapper(new
TypeProviderImpl(context)), "test", jmxImplModule);
- assertThat(runtimeBeans.size(), is(1));
+ assertEquals(1, runtimeBeans.size());
RuntimeBeanEntry runtimeMXBean = runtimeBeans.get("testRuntimeMXBean");
- assertThat(runtimeMXBean.isRoot(), is(true));
- assertThat(runtimeMXBean.getYangName(), is("test-name"));
+ assertTrue(runtimeMXBean.isRoot());
+ assertEquals("test-name", runtimeMXBean.getYangName());
}
@Test
threadsJavaModule, modulesToSIEs, context,
new TypeProviderWrapper(new TypeProviderImpl(context)),
PACKAGE_NAME);
- assertThat(namesToMBEs.isEmpty(), is(false));
+ assertFalse(namesToMBEs.isEmpty());
// get threadfactory-naming bean
ModuleMXBeanEntry threadfactoryNamingMXBean = namesToMBEs
// get runtime beans
Collection<RuntimeBeanEntry> runtimeBeanEntries = threadfactoryNamingMXBean
.getRuntimeBeans();
- assertThat(runtimeBeanEntries.isEmpty(), is(false));
+ assertFalse(runtimeBeanEntries.isEmpty());
// get root runtime bean
RuntimeBeanEntry threadfactoryRuntimeBeanEntry = getRuntimeBeanEntryByJavaName(
runtimeBeanEntries, "NamingThreadFactoryRuntimeMXBean");
assertNotNull(threadfactoryRuntimeBeanEntry);
- assertThat(threadfactoryRuntimeBeanEntry.isRoot(), is(true));
+ assertTrue(threadfactoryRuntimeBeanEntry.isRoot());
// get thread runtime bean
RuntimeBeanEntry runtimeBeanEntry = getRuntimeBeanEntryByJavaName(
assertNotNull(runtimeBeanEntry);
// test thread runtime bean properties
- assertThat(runtimeBeanEntry.getJavaNamePrefix(),
- is(THREAD_RUNTIME_BEAN_JAVA_PREFIX));
- assertThat(runtimeBeanEntry.getPackageName(), is(PACKAGE_NAME));
- assertThat(runtimeBeanEntry.getFullyQualifiedName(runtimeBeanEntry
- .getJavaNameOfRuntimeMXBean()), is(PACKAGE_NAME + "."
- + THREAD_RUNTIME_BEAN_JAVA_NAME));
- assertThat(runtimeBeanEntry.getYangName(),
- is(THREAD_RUNTIME_BEAN_YANG_NAME));
+ assertEquals(THREAD_RUNTIME_BEAN_JAVA_PREFIX, runtimeBeanEntry.getJavaNamePrefix());
+ assertEquals(PACKAGE_NAME, runtimeBeanEntry.getPackageName());
+ assertEquals(PACKAGE_NAME + "." + THREAD_RUNTIME_BEAN_JAVA_NAME,
+ runtimeBeanEntry.getFullyQualifiedName(runtimeBeanEntry
+ .getJavaNameOfRuntimeMXBean()));
+ assertEquals(THREAD_RUNTIME_BEAN_YANG_NAME, runtimeBeanEntry.getYangName());
// get thread runtime bean rpcs
List<RuntimeBeanEntry.Rpc> rpcs = new ArrayList<RuntimeBeanEntry.Rpc>(
runtimeBeanEntry.getRpcs());
- assertThat(rpcs.size(), is(2));
+ assertEquals(2, rpcs.size());
// get sleep rpc and test it
RuntimeBeanEntry.Rpc rpc = getRpcByName(rpcs, SLEEP_RPC_NAME);
assertNotNull(rpc);
- assertThat(rpc.getYangName(), is(SLEEP_RPC_NAME));
+ assertEquals(SLEEP_RPC_NAME, rpc.getYangName());
- assertThat(((JavaAttribute)rpc.getReturnType()).getType().getFullyQualifiedName().endsWith(SLEEP_RPC_OUTPUT), is(true));
+ assertTrue(((JavaAttribute)rpc.getReturnType()).getType().getFullyQualifiedName().endsWith(SLEEP_RPC_OUTPUT));
// get sleep rpc input attribute and test it
List<JavaAttribute> attributes = rpc.getParameters();
- assertThat(attributes.size(), is(1));
+ assertEquals(1, attributes.size());
JavaAttribute attribute = attributes.get(0);
- assertThat(attribute.getAttributeYangName(), is(SLEEP_RPC_INPUT_NAME));
- assertThat(attribute.getType().getName(), is(SLEEP_RPC_INPUT_TYPE));
- assertThat(attribute.getLowerCaseCammelCase(), is(SLEEP_RPC_INPUT_NAME));
- assertThat(attribute.getUpperCaseCammelCase(), is("Millis"));
+ assertEquals(SLEEP_RPC_INPUT_NAME, attribute.getAttributeYangName());
+ assertEquals(SLEEP_RPC_INPUT_TYPE, attribute.getType().getName());
+ assertEquals(SLEEP_RPC_INPUT_NAME, attribute.getLowerCaseCammelCase());
+ assertEquals("Millis", attribute.getUpperCaseCammelCase());
assertNull(attribute.getNullableDefault());
assertNull(attribute.getNullableDescription());
- assertThat(attribute.getOpenType(), is(SimpleType.class));
+ assertTrue(attribute.getOpenType() instanceof SimpleType);
}
private RuntimeBeanEntry getRuntimeBeanEntryByJavaName(
final Collection<RuntimeBeanEntry> runtimeBeanEntries,
- String javaName) {
+ final String javaName) {
if (runtimeBeanEntries != null && !runtimeBeanEntries.isEmpty()) {
for (RuntimeBeanEntry runtimeBeanEntry : runtimeBeanEntries) {
if (runtimeBeanEntry.getJavaNameOfRuntimeMXBean().equals(
}
private RuntimeBeanEntry.Rpc getRpcByName(
- final List<RuntimeBeanEntry.Rpc> rpcs, String name) {
+ final List<RuntimeBeanEntry.Rpc> rpcs, final String name) {
if (rpcs != null && !rpcs.isEmpty()) {
for (RuntimeBeanEntry.Rpc rpc : rpcs) {
if (rpc.getName().equals(name)) {
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-netty-features</artifactId>
- <version>${config.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>features-adsal</artifactId>
- <version>${sal.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>mdsal-features</artifactId>
- <version>${mdsal.version}</version>
<classifier>features</classifier>
<type>xml</type>
<scope>runtime</scope>
<phase>generate-resources</phase>
<configuration>
<outputDirectory>${project.build.directory}/configuration</outputDirectory>
- <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config</includeArtifactIds>
- <includes>**\/*.xml</includes>
+ <includeArtifactIds>sal-rest-connector-config,config-netty-config,md-sal-config,netconf-config,toaster-config,netconf-connector-config,sal-clustering-config</includeArtifactIds>
+ <includes>**\/*.xml,**/*.conf</includes>
<excludeTransitive>true</excludeTransitive>
<ignorePermissions>false</ignorePermissions>
</configuration>
<artifactId>jeromq</artifactId>
<version>0.3.1</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-distributed-datastore</artifactId>
- </dependency>
-
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-distributed-datastore</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-clustering-config</artifactId>
+ </dependency>
</dependencies>
</profile>
<profile>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>compatibility-parent</artifactId>
- <version>1.1-SNAPSHOT</version>
- </parent>
- <artifactId>flow-management-compatibility</artifactId>
- <packaging>bundle</packaging>
-
- <dependencies>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>forwardingrulesmanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-compatibility</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
-
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Bundle-Name>Forwarding Rules Manager Adapter for MD-SAL</Bundle-Name>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <tag>HEAD</tag>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
-</project>
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.frm.compatibility;
-
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.FlowsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ConfigurationReader implements FlowManagementReader {
-
- private final static Logger LOG = LoggerFactory.getLogger(ConfigurationReader.class);
-
- private IForwardingRulesManager manager;
-
- @Override
- public Flows readAllFlows() {
- List<FlowConfig> staticFlows = this.manager.getStaticFlows();
- List<Flow> flowMap = new ArrayList<Flow>(staticFlows.size());
-
- for (FlowConfig conf : staticFlows) {
- flowMap.add(FlowConfigMapping.toConfigurationFlow(conf));
- }
- final FlowsBuilder flowsBuilder = new FlowsBuilder();
- return (flowsBuilder.setFlow(flowMap)).build();
- }
-
- @Override
- public Flow readFlow(final FlowKey key) {
- try {
- final FlowConfig flowConf =
- this.manager.getStaticFlow(String.valueOf(key.getId()), NodeMapping.toADNode(key.getNode()));
- return FlowConfigMapping.toConfigurationFlow(flowConf);
- } catch (Exception e) {
- String errMsg = MessageFormat.format("readFlow by key {} fail", key);
- LOG.error(errMsg, e);
- throw new RuntimeException(errMsg, e);
- }
- }
-
- public IForwardingRulesManager getManager() {
- return this.manager;
- }
-
- public void setManager(final IForwardingRulesManager manager) {
- this.manager = manager;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.frm.compatibility;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-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.Arguments;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public class FRMRuntimeDataProvider implements RuntimeDataProvider, DataCommitHandler<InstanceIdentifier<? extends DataObject>,DataObject> {
-
- private final static InstanceIdentifier<Flows> FLOWS_PATH = InstanceIdentifier.<Flows> builder(Flows.class).toInstance();
-
- private final FlowManagementReader configuration = new ConfigurationReader();
- private DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener;
- private DataProviderService dataService;
- private IForwardingRulesManager manager;
-
- public Registration init() {
- return this.dataService.registerCommitHandler(FRMRuntimeDataProvider.FLOWS_PATH, this);
- }
-
- @Override
- public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
- return this.readFrom(this.configuration, path);
- }
-
- @Override
- public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
- return this.readFrom(this.configuration, path);
- }
-
- public DataObject readFrom(final FlowManagementReader store, final InstanceIdentifier<? extends DataObject> path) {
- if (Objects.equal(FRMRuntimeDataProvider.FLOWS_PATH, path)) {
- return store.readAllFlows();
- }
- if (FRMRuntimeDataProvider.FLOWS_PATH.contains(path)) {
- return store.readFlow(this.toFlowKey(path));
- }
- return null;
- }
-
- @Override
- public FlowCommitTransaction requestCommit(final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- return new FlowCommitTransaction(this, modification);
- }
-
- public FlowKey toFlowKey(final InstanceIdentifier<? extends DataObject> identifier) {
- Preconditions.<InstanceIdentifier<? extends DataObject>> checkNotNull(identifier);
-
- Iterable<PathArgument> path = identifier.getPathArguments();
- PathArgument get = path.iterator().next();
- final Identifier itemKey = Arguments.<IdentifiableItem> checkInstanceOf(get, IdentifiableItem.class).getKey();
- return Arguments.<FlowKey> checkInstanceOf(itemKey, FlowKey.class);
- }
-
- public RpcResult<Void> finish(final FlowCommitTransaction transaction) {
- Iterable<FlowConfig> toRemove = transaction.getToRemove();
- for (final FlowConfig flow : toRemove) {
- this.manager.removeStaticFlow(flow.getName(), flow.getNode());
- }
- Iterable<FlowConfig> toUpdate = transaction.getToUpdate();
- for (final FlowConfig flow : toUpdate) {
- this.manager.removeStaticFlow(flow.getName(), flow.getNode());
- this.manager.addStaticFlow(flow);
- }
- return RpcResultBuilder.<Void> success().build();
- }
-
- public RpcResult<Void> rollback(final FlowCommitTransaction transaction) {
- return null;
- }
-
- public DataProviderService getDataService() {
- return this.dataService;
- }
-
- public void setDataService(final DataProviderService dataService) {
- this.dataService = dataService;
- }
-
- public DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> getChangeListener() {
- return this.changeListener;
- }
-
- public void setChangeListener(final DataChangeListener<InstanceIdentifier<? extends DataObject>, DataObject> changeListener) {
- this.changeListener = changeListener;
- }
-
- public IForwardingRulesManager getManager() {
- return this.manager;
- }
-
- public void setManager(final IForwardingRulesManager manager) {
- this.manager = manager;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.frm.compatibility;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-public class FlowCommitTransaction implements DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject> {
-
- private final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification;
- private final HashSet<FlowConfig> toAdd = new HashSet<FlowConfig>();
- private final FRMRuntimeDataProvider flowManager;
- private Iterable<FlowConfig> toUpdate;
- private Iterable<FlowConfig> toRemove;
-
- public FlowCommitTransaction(
- final FRMRuntimeDataProvider flowManager,
- final DataModification<InstanceIdentifier<? extends DataObject>, DataObject> modification) {
- this.flowManager = flowManager;
- this.modification = modification;
- this.processModification();
- }
-
- @Override
- public RpcResult<Void> finish() throws IllegalStateException {
- return this.flowManager.finish(this);
- }
-
- @Override
- public RpcResult<Void> rollback() throws IllegalStateException {
- return this.flowManager.rollback(this);
- }
-
- public void processModification() {
- final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> updated =
- this.modification.getUpdatedConfigurationData().entrySet();
- final List<FlowConfig> forUpdate = new ArrayList<FlowConfig>(updated.size());
-
- if (updated != null && !(updated.isEmpty())) {
- for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : updated) {
- if (FlowConfigMapping.isFlowPath(entry.getKey())) {
- forUpdate.add(FlowConfigMapping.toFlowConfig((Flow) entry.getValue()));
- }
- }
- }
- this.toUpdate = Collections.unmodifiableCollection(forUpdate);
-
- final Set<InstanceIdentifier<? extends DataObject>> removedConfigurationData =
- this.modification.getRemovedConfigurationData();
- final List<FlowConfig> forRemove = new ArrayList<FlowConfig>(removedConfigurationData.size());
-
- if (removedConfigurationData != null && !(removedConfigurationData.isEmpty())) {
- for (InstanceIdentifier<? extends DataObject> data : removedConfigurationData) {
- if (FlowConfigMapping.isFlowPath(data)) {
- forRemove.add(FlowConfigMapping.toFlowConfig(data));
- }
- }
- }
- this.toRemove = Collections.unmodifiableCollection(forRemove);
- }
-
- @Override
- public DataModification<InstanceIdentifier<? extends DataObject>, DataObject> getModification() {
- return this.modification;
- }
-
- public FRMRuntimeDataProvider getFlowManager() {
- return this.flowManager;
- }
-
- public HashSet<FlowConfig> getToAdd() {
- return this.toAdd;
- }
-
- public Iterable<FlowConfig> getToUpdate() {
- return this.toUpdate;
- }
-
- public Iterable<FlowConfig> getToRemove() {
- return this.toRemove;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.frm.compatibility;
-
-import java.text.MessageFormat;
-import java.util.Iterator;
-
-import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
-import org.opendaylight.controller.sal.compatibility.MDFlowMapping;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FlowConfigMapping {
-
- private final static Logger LOG = LoggerFactory.getLogger(FlowConfigMapping.class);
-
- /* nodes/node/flow -> 0 / 1 / 2 */
- private static final int FLOW_KEY_IDENTIFIER_DEEP = 2;
-
- public static Flow toConfigurationFlow(final FlowConfig sourceCfg) {
- final FlowAdded source = MDFlowMapping.flowAdded(sourceCfg.getFlow());
- final FlowBuilder flowBuilder = new FlowBuilder();
- flowBuilder.setInstructions(source.getInstructions());
- flowBuilder.setCookie(source.getCookie());
- flowBuilder.setHardTimeout(source.getHardTimeout());
- flowBuilder.setIdleTimeout(source.getIdleTimeout());
- flowBuilder.setMatch(source.getMatch());
- flowBuilder.setNode(source.getNode());
-
- FlowKey flowKey =
- new FlowKey(Long.valueOf(sourceCfg.getName()), flowBuilder.getNode());
- flowBuilder.setKey(flowKey);
- return flowBuilder.build();
- }
-
- public static FlowConfig toFlowConfig(final Flow sourceCfg) {
- try {
- final FlowConfig flowConfig = new FlowConfig();
- flowConfig.setName(String.valueOf(sourceCfg.getId()));
- flowConfig.setNode(NodeMapping.toADNode(sourceCfg.getNode()));
- return flowConfig;
- } catch (Exception e) {
- String errMsg = MessageFormat.format("Convert from Flow {} to FlowConfig fail", sourceCfg);
- LOG.error(errMsg, e);
- throw new RuntimeException(errMsg, e);
- }
- }
-
- public static FlowConfig toFlowConfig(final InstanceIdentifier<? extends Object> identifier) {
- try {
- PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(identifier);
- if (pathArg != null) {
- final FlowConfig flowConfig = new FlowConfig();
- FlowKey key = ((IdentifiableItem<Flow, FlowKey>) pathArg).getKey();
- flowConfig.setName(String.valueOf(key.getId()));
- flowConfig.setNode(NodeMapping.toADNode(key.getNode()));
- return flowConfig;
- }
- return null;
- } catch (Exception e) {
- String errMsg = MessageFormat.format("Convert from InstanceIdentifier {} to FlowConfig fail", identifier);
- LOG.error(errMsg, e);
- throw new RuntimeException(errMsg, e);
- }
- }
-
- public static boolean isFlowPath(final InstanceIdentifier<? extends Object> path) {
- PathArgument pathArg = FlowConfigMapping.getSecondPathArgumentFromPath(path);
- if (pathArg == null) {
- return false;
- }
- if (pathArg instanceof IdentifiableItem<?,?>) {
- final Identifiable<?> key = ((IdentifiableItem<?, ? extends Identifiable<?>>) pathArg).getKey();
- if ((key instanceof FlowKey)) {
- return true;
- }
- }
- return false;
- }
-
- private static PathArgument getSecondPathArgumentFromPath(final InstanceIdentifier<? extends Object> path) {
- if (path != null && path.getPathArguments() != null) {
- Iterator<PathArgument> iterator = path.getPathArguments().iterator();
- int deep = 0;
- while (iterator.hasNext()) {
- PathArgument pathArg = iterator.next();
- if (deep == FlowConfigMapping.FLOW_KEY_IDENTIFIER_DEEP) {
- return pathArg;
- }
- deep++;
- }
- }
- return null;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.frm.compatibility;
-
-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.config.rev130819.flows.FlowKey;
-
-public interface FlowManagementReader {
-
- Flows readAllFlows();
-
- Flow readFlow(FlowKey key);
-
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 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.md.frm.compatibility;
-
-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.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.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class SampleConsumer {
-
- ConsumerContext context;
-
- void addFlowExample() {
-
- DataBrokerService dataService = context.getSALService(DataBrokerService.class);
-
- DataModificationTransaction transaction = dataService.beginTransaction();
- Flow flow = createSampleFlow("foo", null);
- InstanceIdentifier<Flow> path = InstanceIdentifier.builder(Flows.class).child(Flow.class, flow.getKey())
- .toInstance();
- transaction.putConfigurationData(path, flow);
-
- transaction.commit();
-
- dataService.readConfigurationData(path);
- }
-
- Flow createSampleFlow(String name, NodeRef node) {
- FlowBuilder ret = new FlowBuilder();
- FlowKey key = new FlowKey(Long.parseLong(name), node);
- ret.setKey(key);
- return ret.build();
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>compatibility-parent</artifactId>
- <version>1.1-SNAPSHOT</version>
- </parent>
- <artifactId>inventory-topology-compatibility</artifactId>
- <packaging>bundle</packaging>
-
- <dependencies>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>forwardingrulesmanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-binding-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-common-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-compatibility</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>switchmanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>topologymanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-topology</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Bundle-Name>Forwarding Rules Manager Adapter
- for MD-SAL</Bundle-Name>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <scm>
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
- <tag>HEAD</tag>
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
- </scm>
-</project>
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.inventory;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.compatibility.InventoryMapping;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-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.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
-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.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class InventoryReader implements RuntimeDataProvider {
- private static final Logger LOG = LoggerFactory.getLogger(InventoryReader.class);
- private ISwitchManager switchManager;
-
- public ISwitchManager getSwitchManager() {
- return switchManager;
- }
-
- public void setSwitchManager(final ISwitchManager switchManager) {
- this.switchManager = switchManager;
- }
-
- @Override
- public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
- // Topology and Inventory are operational only
- return null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
- final Class<? extends DataObject> type = path.getTargetType();
- if (Nodes.class.equals(type)) {
- return readNodes(((InstanceIdentifier<Nodes>) path));
- }
- if (Node.class.equals(type)) {
- return readNode(((InstanceIdentifier<Node>) path));
- }
- if (NodeConnector.class.equals(type)) {
- return readNodeConnector(((InstanceIdentifier<NodeConnector>) path));
- }
-
- LOG.debug("Unsupported type {}", type);
- return null;
- }
-
- private NodeConnector readNodeConnector(final InstanceIdentifier<NodeConnector> identifier) {
- return constructNodeConnector(InventoryMapping.toAdNodeConnector(identifier));
- }
-
- private Node readNode(final InstanceIdentifier<Node> identifier) {
- return constructNode(InventoryMapping.toAdNode(identifier));
- }
-
- private Node constructNode(final org.opendaylight.controller.sal.core.Node node) {
- final Set<org.opendaylight.controller.sal.core.NodeConnector> connectors = getSwitchManager().getNodeConnectors(node);
- final ArrayList<NodeConnector> tpList = new ArrayList<NodeConnector>(connectors.size());
- for (final org.opendaylight.controller.sal.core.NodeConnector connector : connectors) {
- tpList.add(constructNodeConnector(connector));
- }
-
- return new NodeBuilder()
- .setKey(InventoryMapping.toNodeKey(node))
- .setNodeConnector(tpList)
- .build();
- }
-
- private Nodes readNodes(final InstanceIdentifier<Nodes> identifier) {
- final Set<org.opendaylight.controller.sal.core.Node> nodes = getSwitchManager().getNodes();
- final ArrayList<Node> nodeList = new ArrayList<Node>(nodes.size());
- for (final org.opendaylight.controller.sal.core.Node node : nodes) {
- nodeList.add(constructNode(node));
- }
-
- return new NodesBuilder().setNode(nodeList).build();
- }
-
- private static NodeConnector constructNodeConnector(final org.opendaylight.controller.sal.core.NodeConnector connector) {
- return new NodeConnectorBuilder().setKey(InventoryMapping.toNodeConnectorKey(connector)).build();
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.switchmanager;
-
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.controller.sal.core.Bandwidth;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Description;
-import org.opendaylight.controller.sal.core.ForwardingMode;
-import org.opendaylight.controller.sal.core.MacAddress;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.Tier;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.Subnet;
-import org.opendaylight.controller.switchmanager.Switch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-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.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class CompatibleSwitchManager extends ConfigurableSwitchManager implements ISwitchManager {
- private static final Logger LOG = LoggerFactory.getLogger(CompatibleSwitchManager.class);
-
- private DataBrokerService _dataService;
-
- public DataBrokerService getDataService() {
- return this._dataService;
- }
-
- public void setDataService(final DataBrokerService dataService) {
- this._dataService = dataService;
- }
-
- @Override
- public Status addNodeConnectorProp(final NodeConnector nodeConnector, final Property prop) {
- final DataModificationTransaction it = getDataService().beginTransaction();
- final NodeConnectorRef path = NodeMapping.toNodeConnectorRef(nodeConnector);
- return null;
- }
-
- @Override
- public Property createProperty(final String propName, final String propValue) {
- try {
- if (propName.equalsIgnoreCase(Description.propertyName)) {
- return new Description(propValue);
- } else if (propName.equalsIgnoreCase(Tier.TierPropName)) {
- return new Tier(Integer.parseInt(propValue));
- } else if (propName.equalsIgnoreCase(Bandwidth.BandwidthPropName)) {
- return new Bandwidth(Long.parseLong(propValue));
- } else if (propName.equalsIgnoreCase(ForwardingMode.name)) {
- return new ForwardingMode(Integer.parseInt(propValue));
- } else if (propName.equalsIgnoreCase(MacAddress.name)) {
- return new MacAddress(propValue);
- } else {
- LOG.debug("Not able to create {} property", propName);
- }
- } catch (Exception e) {
- LOG.debug("createProperty caught exception {}", e.getMessage());
- }
-
- return null;
- }
-
- @Override
- public boolean doesNodeConnectorExist(final NodeConnector nc) {
- return (getDataService().readOperationalData(NodeMapping.toNodeConnectorRef(nc).getValue()) != null);
- }
-
- @Override
- public byte[] getControllerMAC() {
- final Enumeration<NetworkInterface> nis;
- try {
- nis = NetworkInterface.getNetworkInterfaces();
- } catch (SocketException e) {
- LOG.error("Failed to acquire list of interfaces, cannot determine controller MAC", e);
- return null;
- }
-
- while (nis.hasMoreElements()) {
- final NetworkInterface ni = nis.nextElement();
- try {
- return ni.getHardwareAddress();
- } catch (SocketException e) {
- LOG.error("Failed to acquire controller MAC from interface {}", ni, e);
- }
- }
-
- // This happens when running controller on windows VM, for example
- // Try parsing the OS command output
- LOG.warn("Failed to acquire controller MAC: No physical interface found");
- return null;
- }
-
- @Override
- public Map<String,Property> getControllerProperties() {
- return Collections.<String, Property>emptyMap();
- }
-
- @Override
- public Property getControllerProperty(final String propertyName) {
- return null;
- }
-
- @Override
- public List<Switch> getNetworkDevices() {
- final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).toInstance();
- final Nodes data = ((Nodes) getDataService().readOperationalData(path));
- final ArrayList<Switch> ret = new ArrayList<>();
- for (final Node node : data.getNode()) {
- try {
- ret.add(toSwitch(node));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create switch {}", node), e);
- }
- }
- return ret;
- }
-
- @Override
- public NodeConnector getNodeConnector(final org.opendaylight.controller.sal.core.Node node, final String nodeConnectorName) {
- final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(nodeConnectorName));
- try {
- return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, node);
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create node connector for {} {}", node, nodeConnectorName), e);
- }
- }
-
- @Override
- public Property getNodeConnectorProp(final NodeConnector nodeConnector, final String propName) {
- return getNodeConnectorProps(nodeConnector).get(propName);
- }
-
- @Override
- public Map<String,Property> getNodeConnectorProps(final NodeConnector nodeConnector) {
- final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(nodeConnector);
- return toAdProperties(readNodeConnector(ref.getValue()));
- }
-
- @Override
- public Set<NodeConnector> getNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
- final Node data = this.readNode(NodeMapping.toNodeRef(node).getValue());
- final HashSet<NodeConnector> ret = new HashSet<>();
- for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
- try {
- ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create node {} connector", node, nc.getKey()), e);
- }
- }
- return ret;
- }
-
- @Override
- public String getNodeDescription(final org.opendaylight.controller.sal.core.Node node) {
- return ((Description) getNodeProps(node).get(Description.propertyName)).getValue();
- }
-
- @Override
- public byte[] getNodeMAC(final org.opendaylight.controller.sal.core.Node node) {
- return ((MacAddress) getNodeProps(node).get(MacAddress.name)).getMacAddress();
- }
-
- @Override
- public Property getNodeProp(final org.opendaylight.controller.sal.core.Node node, final String propName) {
- return getNodeProps(node).get(propName);
- }
-
- @Override
- public Map<String,Property> getNodeProps(final org.opendaylight.controller.sal.core.Node node) {
- final NodeRef ref = NodeMapping.toNodeRef(node);
- return toAdProperties(((Node) getDataService().readOperationalData(ref.getValue())));
- }
-
- @Override
- public Set<org.opendaylight.controller.sal.core.Node> getNodes() {
- final InstanceIdentifier<Nodes> path = InstanceIdentifier.builder(Nodes.class).toInstance();
- final Nodes data = ((Nodes) getDataService().readOperationalData(path));
- final HashSet<org.opendaylight.controller.sal.core.Node> ret = new HashSet<>();
- for (final Node node : data.getNode()) {
- try {
- ret.add(new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, node.getKey()));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create node for {}", node), e);
- }
- }
- return ret;
- }
-
- private static Switch toSwitch(final Node node) throws ConstructionException {
- return new Switch(new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, node.getKey()));
- }
-
- @Override
- public Set<NodeConnector> getPhysicalNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
- final NodeRef ref = NodeMapping.toNodeRef(node);
- final Node data = readNode(ref.getValue());
- final HashSet<NodeConnector> ret = new HashSet<>();
- for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
- final FlowCapableNodeConnector flowConnector = nc.getAugmentation(FlowCapableNodeConnector.class);
- try {
- ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create connector for {} on node {}", nc.getKey(), node), e);
- }
- }
- return ret;
- }
-
- private static Map<String,Property> toAdProperties(final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector connector) {
- return Collections.emptyMap();
- }
-
- private static Map<String,Property> toAdProperties(final Node connector) {
- return Collections.emptyMap();
- }
-
- private Node readNode(final InstanceIdentifier<? extends Object> ref) {
- return (Node) getDataService().readOperationalData((ref));
- }
-
- private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector readNodeConnector(final InstanceIdentifier<? extends Object> ref) {
- return ((org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector) getDataService().readOperationalData(ref));
- }
-
- @Override
- public List<NodeConnector> getSpanPorts(final org.opendaylight.controller.sal.core.Node node) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Subnet getSubnetByNetworkAddress(final InetAddress networkAddress) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Set<NodeConnector> getUpNodeConnectors(final org.opendaylight.controller.sal.core.Node node) {
- final Node data = readNode(NodeMapping.toNodeRef(node).getValue());
- final HashSet<NodeConnector> ret = new HashSet<>();
- for (final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc : data.getNodeConnector()) {
- final FlowCapableNodeConnector flowConn = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
- if (flowConn != null && flowConn.getState() != null && !flowConn.getState().isLinkDown()) {
- try {
- ret.add(new NodeConnector(NodeMapping.MD_SAL_TYPE, nc.getKey(), node));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create node connector for node {} connector {}", node, nc), e);
- }
- }
- }
- return ret;
- }
-
- @Override
- public Boolean isNodeConnectorEnabled(final NodeConnector nodeConnector) {
- final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(nodeConnector);
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector data = readNodeConnector(ref.getValue());
- return true;
- }
-
- @Override
- public boolean isSpecial(final NodeConnector p) {
- final NodeConnectorRef ref = NodeMapping.toNodeConnectorRef(p);
- final org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector data = readNodeConnector(ref.getValue());
- return true;
- }
-
- @Override
- public Status removeControllerProperty(final String propertyName) {
- return null;
- }
-
- @Override
- public Status removeNodeAllProps(final org.opendaylight.controller.sal.core.Node node) {
- return null;
- }
-
- @Override
- public Status removeNodeConnectorAllProps(final NodeConnector nodeConnector) {
- return null;
- }
-
- @Override
- public Status removeNodeConnectorProp(final NodeConnector nc, final String propName) {
- return null;
- }
-
- @Override
- public Status removeNodeProp(final org.opendaylight.controller.sal.core.Node node, final String propName) {
- return null;
- }
-
- @Override
- public Status removePortsFromSubnet(final String name, final List<String> nodeConnectors) {
- return null;
- }
-
- @Override
- public Status removeSubnet(final String name) {
- return null;
- }
-
- @Override
- public Status setControllerProperty(final Property property) {
- return null;
- }
-
- @Override
- public void setNodeProp(final org.opendaylight.controller.sal.core.Node node, final Property prop) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Status addPortsToSubnet(final String name, final List<String> nodeConnectors) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Set<Switch> getConfiguredNotConnectedSwitches() {
- return null;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.switchmanager;
-
-import java.util.List;
-
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.SpanConfig;
-import org.opendaylight.controller.switchmanager.SubnetConfig;
-import org.opendaylight.controller.switchmanager.SwitchConfig;
-
-/**
- * These methods should be backed by config subsystem.
- */
-public abstract class ConfigurableSwitchManager implements ISwitchManager {
- @Override
- public Status saveSwitchConfig() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Status removeSpanConfig(final SpanConfig cfgObject) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Status addSubnet(final SubnetConfig configObject) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final Status addSpanConfig(final SpanConfig configObject) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final List<SpanConfig> getSpanConfigList() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final void updateSwitchConfig(final SwitchConfig cfgObject) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final Status updateNodeConfig(final SwitchConfig switchConfig) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final SubnetConfig getSubnetConfig(final String subnet) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final Status removeNodeConfig(final String nodeId) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final Status removeSubnet(final SubnetConfig configObject) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final List<SubnetConfig> getSubnetsConfigList() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final SwitchConfig getSwitchConfig(final String nodeId) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public Status modifySubnet(final SubnetConfig configObject) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.topology;
-
-import java.util.Iterator;
-
-import org.opendaylight.controller.sal.compatibility.InventoryMapping;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-
-import com.google.common.base.Splitter;
-
-public class TopologyMapping {
- private static final String HEAD_TAIL_STRING = "::::";
- private static final Splitter HEAD_TAIL_SPLITTER = Splitter.on(HEAD_TAIL_STRING);
-
- public TopologyMapping(final TopologyKey path, final InstanceIdentifier<Topology> key) {
- // No-op for now. Multi-instance will require fixing InventoryMapping first.
- }
-
- public Edge toAdTopologyEdge(final InstanceIdentifier<Link> identifier) throws ConstructionException {
- @SuppressWarnings("unchecked")
- final LinkKey linkKey = ((KeyedInstanceIdentifier<Link, LinkKey>)identifier).getKey();
-
- final Iterator<String> it = HEAD_TAIL_SPLITTER.split(linkKey.getLinkId().getValue()).iterator();
- final NodeConnector tail = InventoryMapping.nodeConnectorFromId(it.next());
- final NodeConnector head = InventoryMapping.nodeConnectorFromId(it.next());
- return new Edge(tail, head);
- }
-
- public NodeConnector toAdTopologyNodeConnector(final InstanceIdentifier<TerminationPoint> identifier) {
- @SuppressWarnings("unchecked")
- final TerminationPointKey tpKey = ((KeyedInstanceIdentifier<TerminationPoint, TerminationPointKey>)identifier).getKey();
-
- return InventoryMapping.nodeConnectorFromId(tpKey.getTpId().getValue());
- }
-
- public org.opendaylight.controller.sal.core.Node toAdTopologyNode(final InstanceIdentifier<Node> identifier) {
- @SuppressWarnings("unchecked")
- final NodeKey nodeKey = ((KeyedInstanceIdentifier<Node, NodeKey>)identifier).getKey();
-
- return InventoryMapping.nodeFromNodeId(nodeKey.getNodeId().getValue());
- }
-
- public NodeKey toTopologyNodeKey(final org.opendaylight.controller.sal.core.Node node) {
- return new NodeKey(new NodeId(InventoryMapping.toNodeId(node)));
- }
-
- public TerminationPointKey toTopologyTerminationPointKey(final NodeConnector nc) {
- return new TerminationPointKey(new TpId(InventoryMapping.toNodeConnectorId(nc)));
- }
-
- public LinkKey toTopologyLinkKey(final Edge edge) {
- final TerminationPointKey sourceTp = toTopologyTerminationPointKey(edge.getTailNodeConnector());
- final TerminationPointKey destTp = toTopologyTerminationPointKey(edge.getHeadNodeConnector());
-
- final StringBuilder sb = new StringBuilder();
- sb.append(sourceTp.getTpId().toString());
- sb.append(HEAD_TAIL_STRING);
- sb.append(destTp.getTpId().toString());
- return new LinkKey(new LinkId(sb.toString()));
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.topology;
-
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopologyReader implements RuntimeDataProvider {
- private static final Logger LOG = LoggerFactory.getLogger(TopologyReader.class);
- private final InstanceIdentifier<Topology> topologyPath;
- private final TopologyKey topologyKey;
- private final TopologyMapping mapping;
- private ITopologyManager topologyManager;
- private ISwitchManager switchManager;
-
- public ISwitchManager getSwitchManager() {
- return this.switchManager;
- }
-
- public void setSwitchManager(final ISwitchManager switchManager) {
- this.switchManager = switchManager;
- }
-
- public ITopologyManager getTopologyManager() {
- return this.topologyManager;
- }
-
- public void setTopologyManager(final ITopologyManager topologyManager) {
- this.topologyManager = topologyManager;
- }
-
- public TopologyKey getTopologyKey() {
- return this.topologyKey;
- }
-
- public TopologyMapping getMapping() {
- return this.mapping;
- }
-
- public TopologyReader() {
- this.topologyKey = new TopologyKey(new TopologyId("compatibility:ad-sal"));
- this.topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
- .child(Topology.class, topologyKey)
- .toInstance();
- this.mapping = new TopologyMapping(topologyKey, topologyPath);
- }
-
- @Override
- public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
- // Topology and Inventory are operational only
- return null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
- if (!topologyPath.contains(path)) {
- return null;
- }
-
- final Class<? extends DataObject> type = path.getTargetType();
- if (Link.class.equals(type)) {
- return readLink((InstanceIdentifier<Link>) path);
- }
- if (Node.class.equals(type)) {
- return readNode((InstanceIdentifier<Node>) path);
- }
- if (TerminationPoint.class.equals(type)) {
- return readTerminationPoint((InstanceIdentifier<TerminationPoint>) path);
-
- }
- if (Topology.class.equals(type)) {
- return readTopology((InstanceIdentifier<Topology>) path);
- }
-
- LOG.debug("Unsupported type {}", type);
- return null;
- }
-
- private Link readLink(final InstanceIdentifier<Link> identifier) {
- final Edge edge;
- try {
- edge = this.mapping.toAdTopologyEdge(identifier);
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to construct edge for link %s", identifier), e);
- }
-
- final Map<Edge,Set<Property>> edges;
- if (topologyManager != null) {
- edges = topologyManager.getEdges();
- } else {
- edges = null;
- }
-
- final Set<Property> properties;
- if (edges != null) {
- properties = edges.get(edge);
- } else {
- properties = null;
- }
-
- return constructLink(edge);
- }
-
- private TerminationPoint readTerminationPoint(final InstanceIdentifier<TerminationPoint> identifier) {
- return constructTerminationPoint(mapping.toAdTopologyNodeConnector(identifier));
- }
-
- private Node readNode(final InstanceIdentifier<Node> identifier) {
- return constructNode(mapping.toAdTopologyNode(identifier));
- }
-
- private Topology readTopology(final InstanceIdentifier<Topology> identifier) {
- final Set<org.opendaylight.controller.sal.core.Node> nodes = getSwitchManager().getNodes();
- final ArrayList<Node> nodeList = new ArrayList<Node>(nodes.size());
- for (final org.opendaylight.controller.sal.core.Node node : nodes) {
- nodeList.add(constructNode(node));
- }
-
- final Map<Edge,Set<Property>> edges = getTopologyManager().getEdges();
- final ArrayList<Link> linkList = new ArrayList<Link>(edges.size());
- for (final Edge edge : edges.keySet()) {
- linkList.add(constructLink(edge));
- }
-
- return new TopologyBuilder()
- .setKey(topologyKey)
- .setNode(nodeList)
- .setLink(linkList)
- .build();
- }
-
- private Link constructLink(final Edge edge) {
- final NodeConnector sourceNc = edge.getTailNodeConnector();
- final NodeConnector destNc = edge.getHeadNodeConnector();
-
- final LinkBuilder it = new LinkBuilder().setKey(mapping.toTopologyLinkKey(edge));
-
- it.setSource(new SourceBuilder()
- .setSourceNode(mapping.toTopologyNodeKey(sourceNc.getNode()).getNodeId())
- .setSourceTp(mapping.toTopologyTerminationPointKey(sourceNc).getTpId())
- .build());
-
- it.setDestination(new DestinationBuilder()
- .setDestNode(mapping.toTopologyNodeKey(destNc.getNode()).getNodeId())
- .setDestTp(mapping.toTopologyTerminationPointKey(destNc).getTpId())
- .build());
-
- return it.build();
- }
-
- private Node constructNode(final org.opendaylight.controller.sal.core.Node node) {
- final Set<NodeConnector> connectors = getSwitchManager().getNodeConnectors(node);
- final ArrayList<TerminationPoint> tpList = new ArrayList<TerminationPoint>(connectors.size());
- for (final NodeConnector connector : connectors) {
- tpList.add(constructTerminationPoint(connector));
- }
-
- return new NodeBuilder()
- .setKey(mapping.toTopologyNodeKey(node))
- .setTerminationPoint(tpList)
- .build();
- }
-
- private TerminationPoint constructTerminationPoint(final NodeConnector connector) {
- return new TerminationPointBuilder().setKey(mapping.toTopologyTerminationPointKey(connector)).build();
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.topologymanager;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.compatibility.NodeMapping;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Destination;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Source;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class AdSalTopologyMapping {
- private final InstanceIdentifier<Topology> topologyPath;
-
- public AdSalTopologyMapping(final TopologyKey topology) {
- this.topologyPath = InstanceIdentifier.builder(NetworkTopology.class)
- .child(Topology.class, topology).toInstance();
- }
-
- public InstanceIdentifier<Topology> getTopologyPath() {
- return topologyPath;
- }
-
- public InstanceIdentifier<TerminationPoint> toTerminationPoint(final NodeConnector connector) {
- return getTopologyPath().builder()
- .child(Node.class)
- .child(TerminationPoint.class, toTerminationPointKey(connector))
- .toInstance();
- }
-
- public Map<Edge,Set<Property>> toEdgePropertiesMap(final Iterable<Link> links) {
- final HashMap<Edge,Set<Property>> ret = new HashMap<>();
- for (final Link link : links) {
- try {
- ret.put(toEdge(link), toProperties(link));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to create edge properties for {}", link), e);
- }
- }
- return ret;
- }
-
- public static Set<Edge> toEdges(final Iterable<Link> links) throws ConstructionException {
- final HashSet<Edge> ret = new HashSet<Edge>();
- for (final Link link : links) {
- ret.add(toEdge(link));
- }
- return ret;
- }
-
- public static Edge toEdge(final Link link) throws ConstructionException {
- final NodeConnector tail = toNodeConnector(link.getSource());
- final NodeConnector head = toNodeConnector(link.getDestination());
- return new Edge(tail, head);
- }
-
- public static org.opendaylight.controller.sal.core.Node toAdNode(final Node node) throws ConstructionException {
- return toAdNode(node.getNodeId());
- }
-
- public static org.opendaylight.controller.sal.core.Node toAdNode(final NodeId node) throws ConstructionException {
- final NodeKey key = new NodeKey(
- new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(node));
- return new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, key);
- }
-
- public static NodeConnector toNodeConnector(final Source ref) throws ConstructionException {
- final org.opendaylight.controller.sal.core.Node adNode = toAdNode(ref.getSourceNode());
- final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(ref.getSourceTp()));
- return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
- }
-
- public static NodeConnector toNodeConnector(final Destination ref) throws ConstructionException {
- final org.opendaylight.controller.sal.core.Node adNode = toAdNode(ref.getDestNode());
- final NodeConnectorKey key = new NodeConnectorKey(new NodeConnectorId(ref.getDestTp()));
- return new NodeConnector(NodeMapping.MD_SAL_TYPE, key, adNode);
- }
-
- public TerminationPointKey toTerminationPointKey(final NodeConnector connector) {
- return null;
- }
-
- public Set<Property> toProperties(final Link link) {
- return null;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.topologymanager;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.binding.util.TypeSafeDataReader;
-import org.opendaylight.controller.sal.core.ConstructionException;
-import org.opendaylight.controller.sal.core.Edge;
-import org.opendaylight.controller.sal.core.Host;
-import org.opendaylight.controller.sal.core.NodeConnector;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-
-@SuppressWarnings("all")
-public class CompatibleTopologyManager extends ConfigurableLinkManager implements ITopologyManager {
- private AdSalTopologyMapping topologyMapping;
- private TypeSafeDataReader dataReader;
-
- public TypeSafeDataReader getDataReader() {
- return dataReader;
- }
-
- public void setDataReader(final TypeSafeDataReader dataReader) {
- this.dataReader = dataReader;
- }
-
- public AdSalTopologyMapping getTopologyMapping() {
- return topologyMapping;
- }
-
- public void setTopologyMapping(final AdSalTopologyMapping topologyMapping) {
- this.topologyMapping = topologyMapping;
- }
-
- @Override
- public Map<Edge,Set<Property>> getEdges() {
- final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
- return this.topologyMapping.toEdgePropertiesMap(topology.getLink());
- }
-
- @Override
- public Map<org.opendaylight.controller.sal.core.Node, Set<Edge>> getNodeEdges() {
- final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
- final HashMap<org.opendaylight.controller.sal.core.Node, Set<Edge>> ret = new HashMap<>();
- for (final Node node : topology.getNode()) {
- try {
- ret.put(topologyMapping.toAdNode(node), topologyMapping.toEdges(
- FluentIterable.from(topology.getLink()).filter(new Predicate<Link>() {
- @Override
- public boolean apply(final Link input) {
- final NodeId nodeId = node.getNodeId();
- if (nodeId.equals(input.getSource().getSourceNode())) {
- return true;
- }
- if (nodeId.equals(input.getDestination().getDestNode())) {
- return true;
- }
-
- return false;
- }
- })));
- } catch (ConstructionException e) {
- throw new IllegalStateException(String.format("Failed to construct node for {}", node), e);
- }
- }
- return ret;
- }
-
- /**
- * Returns true if point is connected to link
- */
- private boolean isInternal(final TerminationPoint point) {
- final Topology topology = getDataReader().readConfigurationData(topologyMapping.getTopologyPath());
- final TpId tpId = point.getKey().getTpId();
- return FluentIterable.from(topology.getLink()).anyMatch(new Predicate<Link>() {
- @Override
- public boolean apply(final Link input) {
- if (tpId.equals(input.getSource().getSourceTp())) {
- return true;
- }
- if (tpId.equals(input.getDestination().getDestTp())) {
- return true;
- }
- return false;
- }
- });
- }
-
- @Override
- public Set<NodeConnector> getNodeConnectorWithHost() {
- return null;
- }
-
- @Override
- public Host getHostAttachedToNodeConnector(final NodeConnector p) {
- final InstanceIdentifier<TerminationPoint> tpPath = topologyMapping.toTerminationPoint(p);
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public List<Host> getHostsAttachedToNodeConnector(final NodeConnector p) {
- final Topology topology = getDataReader().readOperationalData(topologyMapping.getTopologyPath());
- throw new UnsupportedOperationException("Hosts not mapped yet");
- }
-
- @Override
- public Map<org.opendaylight.controller.sal.core.Node, Set<NodeConnector>> getNodesWithNodeConnectorHost() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public boolean isInternal(final NodeConnector p) {
- final TerminationPoint connector = getDataReader()
- .readConfigurationData(topologyMapping.toTerminationPoint(p));
- return this.isInternal(connector);
- }
-
- @Override
- public void updateHostLink(final NodeConnector p, final Host h, final UpdateType t, final Set<Property> props) {
- // Update app defined topology
- }
-
- @Override
- public Status saveConfig() {
- // FIXME: commit configuration
- return null;
- }
-}
+++ /dev/null
-/**
- * Copyright (c) 2014 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.md.compatibility.topologymanager;
-
-import java.util.concurrent.ConcurrentMap;
-
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.topologymanager.ITopologyManager;
-import org.opendaylight.controller.topologymanager.TopologyUserLinkConfig;
-
-public abstract class ConfigurableLinkManager implements ITopologyManager {
- @Override
- public final Status addUserLink(final TopologyUserLinkConfig link) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final Status deleteUserLink(final String linkName) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-
- @Override
- public final ConcurrentMap<String,TopologyUserLinkConfig> getUserLinks() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub");
- }
-}
<modules>
<module>sal-compatibility</module>
- <module>inventory-topology-compatibility</module>
- <module>flow-management-compatibility</module>
</modules>
<dependencies>
*/
package org.opendaylight.controller.sal.compatibility;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
-
import org.opendaylight.controller.sal.common.util.Arguments;
import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
import org.opendaylight.controller.sal.core.Bandwidth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
public final class NodeMapping {
private static final Logger LOG = LoggerFactory
.getLogger(NodeMapping.class);
- /** openflow id prefix */
+ /**
+ * openflow id prefix
+ */
public static final String OPENFLOW_ID_PREFIX = "openflow:";
public final static String MD_SAL_TYPE = "MD_SAL_DEPRECATED";
}
public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) throws ConstructionException {
- Long aDNodeId = openflowFullNodeIdToLong(NodeMapping.toADNodeId(id));
- return new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, aDNodeId);
+ String nodeId = NodeMapping.toADNodeId(id);
+ String nodeIdasNumber = nodeId.replaceFirst("^.*:", "");
+ if (isInteger(nodeIdasNumber)) {
+ Long aDNodeId = openflowFullNodeIdToLong(nodeIdasNumber);
+ return new org.opendaylight.controller.sal.core.Node(NodeIDType.OPENFLOW, aDNodeId);
+ } else {
+ return new org.opendaylight.controller.sal.core.Node(NodeIDType.PRODUCTION, nodeId);
+ }
}
/**
if (adNodeId == null) {
return null;
}
- return new BigInteger(adNodeId.replaceFirst("^.*:", "")).longValue();
+ return new BigInteger(adNodeId).longValue();
}
public static NodeId toNodeId(final InstanceIdentifier<?> id) {
}
/**
- * @param ncid nodeConnector identifier, e.g.: OF:21 or CTRL
- * @param node
+ * @param ncid nodeConnector identifier, e.g.: OF:21 or CTRL
+ * @param aDNode
* @return nodeConnector attached to given node
* @throws ConstructionException
*/
* @return
*/
private static NodeId toNodeId(org.opendaylight.controller.sal.core.Node aDNode) {
- return new NodeId(aDNode.getType() + ":" +String.valueOf(aDNode.getID()));
+ return new NodeId(aDNode.getType() + ":" + String.valueOf(aDNode.getID()));
}
public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) {
public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) {
Preconditions.checkArgument(NodeIDType.OPENFLOW.equals(node.getType()));
final Long nodeId = Arguments.<Long>checkInstanceOf(node.getID(), Long.class);
- final NodeKey nodeKey = new NodeKey(new NodeId(OPENFLOW_ID_PREFIX+nodeId));
+ final NodeKey nodeKey = new NodeKey(new NodeId(OPENFLOW_ID_PREFIX + nodeId));
final InstanceIdentifier<Node> nodePath = InstanceIdentifier.builder(Nodes.class).child(NODE_CLASS, nodeKey).toInstance();
return new NodeRef(nodePath);
}
}
/**
- * @param id
+ * @param nodeRef
* @return node description in AD form, e.g.: OF|00:00:00:...:01
*/
private static Description toADDescription(NodeRef nodeRef) {
public static Buffers toADBuffers(final Long buffers) {
return new Buffers(buffers.intValue());
}
+
+
+ private static final boolean isInteger(String value) {
+ if (value.isEmpty()) return false;
+ for (int i = 0; i < value.length(); i++) {
+ if (i == 0 && value.charAt(i) == '-') {
+ if (value.length() == 1) return false;
+ else continue;
+ }
+ if (Character.digit(value.charAt(i), 10) < 0) return false;
+ }
+ return true;
+ }
}
} catch (ConstructionException e) {
Assert.fail("should succeed to construct Node: "+e.getMessage());
}
+
+ final String nodeUriPrefix = "opendaylight-inventory:nodes/node/";
+ nodeId = new NodeId(nodeUriPrefix + "iosv-2");
+ try {
+ observed = NodeMapping.toADNode(nodeId);
+ Assert.assertEquals("PR|opendaylight-inventory:nodes/node/iosv-2", observed.toString());
+ } catch (ConstructionException e) {
+ Assert.fail("should succeed to construct Node: "+e.getMessage());
+ }
+
}
/**
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-api</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-service</artifactId>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-operational-datastore-provider</type>
<name>distributed-operational-store-module</name>
- <schema-service>
+ <operational-schema-service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
<name>yang-schema-service</name>
- </schema-service>
+ </operational-schema-service>
</module>
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-config-datastore-provider</type>
<name>distributed-config-store-module</name>
- <schema-service>
+ <configschema-service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
<name>yang-schema-service</name>
- </schema-service>
+ </config-schema-service>
</module>
-->
<!--InMemory DOM DataStore-->
<module>sal-inmemory-datastore</module>
- <!--sal-protocolbuffer-encoding-->
- <module>sal-protocolbuffer-encoding</module>
+ <!--sal-protocolbuffer-encoding is now part of sal-clutering-commons-->
+ <module>sal-clustering-commons</module>
+
+ <!-- sal clustering configuration -->
+ <module>sal-clustering-config</module>
<!-- sal-distributed-datastore -->
<module>sal-distributed-datastore</module>
@Override
public List<ReplicatedLogEntry> getFrom(long logEntryIndex) {
+ return getFrom(logEntryIndex, journal.size());
+ }
+
+ @Override
+ public List<ReplicatedLogEntry> getFrom(long logEntryIndex, int max) {
int adjustedIndex = adjustedIndex(logEntryIndex);
int size = journal.size();
List<ReplicatedLogEntry> entries = new ArrayList<>(100);
if (adjustedIndex >= 0 && adjustedIndex < size) {
// physical index should be less than list size and >= 0
- entries.addAll(journal.subList(adjustedIndex, size));
+ int maxIndex = adjustedIndex + max;
+ if(maxIndex > size){
+ maxIndex = size;
+ }
+ entries.addAll(journal.subList(adjustedIndex, maxIndex));
}
return entries;
}
+
@Override
public long size() {
return journal.size();
* Since this is set to 100 milliseconds the Election timeout should be
* at least 200 milliseconds
*/
- protected static final FiniteDuration HEART_BEAT_INTERVAL =
+ public static final FiniteDuration HEART_BEAT_INTERVAL =
new FiniteDuration(100, TimeUnit.MILLISECONDS);
@Override
public FiniteDuration getElectionTimeOutInterval() {
// returns 2 times the heart beat interval
- return HEART_BEAT_INTERVAL.$times(2);
+ return getHeartBeatInterval().$times(2);
}
@Override
replicatedLog.lastIndex(), replicatedLog.snapshotIndex,
replicatedLog.snapshotTerm, replicatedLog.size());
currentBehavior = switchBehavior(RaftState.Follower);
+ onStateChanged();
}
}
RaftState state =
currentBehavior.handleMessage(getSender(), message);
+ RaftActorBehavior oldBehavior = currentBehavior;
currentBehavior = switchBehavior(state);
+ if(oldBehavior != currentBehavior){
+ onStateChanged();
+ }
}
}
String peerAddress = context.getPeerAddress(leaderId);
LOG.debug("getLeader leaderId = " + leaderId + " peerAddress = "
+ peerAddress);
+
+ if(peerAddress == null){
+ return null;
+ }
return context.actorSelection(peerAddress);
}
+ /**
+ *
+ * @return the current leader's id
+ */
+ protected String getLeaderId(){
+ return currentBehavior.getLeaderId();
+ }
+
protected RaftState getRaftState() {
return currentBehavior.state();
}
behavior = new Leader(context);
}
- onStateChanged();
+
return behavior;
}
*/
List<ReplicatedLogEntry> getFrom(long index);
+ /**
+ *
+ * @param index the index of the log entry
+ */
+ List<ReplicatedLogEntry> getFrom(long index, int max);
/**
*
// that has fallen too far behind with the log but yet is not
// eligible to receive a snapshot
entries =
- context.getReplicatedLog().getFrom(nextIndex);
+ context.getReplicatedLog().getFrom(nextIndex, 1);
}
followerActor.tell(
*/
package org.opendaylight.controller.cluster.raft;
+import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@Before
public void setUp() {
replicatedLogImpl = new MockAbstractReplicatedLogImpl();
+ // create a set of initial entries in the in-memory log
+ replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
+ replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
+
}
@After
@Test
public void testIndexOperations() {
- // create a set of initial entries in the in-memory log
- replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
- replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
- replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
- replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
// check if the values returned are correct, with snapshotIndex = -1
assertEquals("B", replicatedLogImpl.get(1).getData().toString());
}
+ @Test
+ public void testGetFromWithMax(){
+ List<ReplicatedLogEntry> from = replicatedLogImpl.getFrom(0, 1);
+ Assert.assertEquals(1, from.size());
+ Assert.assertEquals(1, from.get(0).getTerm());
+
+ from = replicatedLogImpl.getFrom(0, 20);
+ Assert.assertEquals(4, from.size());
+ Assert.assertEquals(2, from.get(3).getTerm());
+
+ from = replicatedLogImpl.getFrom(1, 2);
+ Assert.assertEquals(2, from.size());
+ Assert.assertEquals(1, from.get(1).getTerm());
+
+ }
+
// create a snapshot for test
public Map takeSnapshot(int numEntries) {
Map map = new HashMap(numEntries);
return entries;
}
+ @Override public List<ReplicatedLogEntry> getFrom(long index, int max) {
+ if(index >= log.size() || index < 0){
+ return Collections.EMPTY_LIST;
+ }
+ List<ReplicatedLogEntry> entries = new ArrayList<>();
+ int maxIndex = (int) index + max;
+ if(maxIndex > log.size()){
+ maxIndex = log.size();
+ }
+
+ for(int i=(int) index ; i < maxIndex ; i++) {
+ entries.add(get(i));
+ }
+ return entries;
+
+ }
+
@Override public long size() {
return log.size();
}
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
public void testThatAnElectionTimeoutIsTriggered(){
new JavaTestKit(getSystem()) {{
- new Within(duration("1 seconds")) {
+ new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
protected void run() {
Candidate candidate = new Candidate(createActorContext(getTestActor()));
- final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
+ final Boolean out = new ExpectMsg<Boolean>(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6), "ElectionTimeout") {
// do not put code outside this method, will run afterwards
protected Boolean match(Object in) {
if (in instanceof ElectionTimeout) {
import akka.testkit.JavaTestKit;
import junit.framework.Assert;
import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftActorContext;
import org.opendaylight.controller.cluster.raft.RaftState;
public void testThatAnElectionTimeoutIsTriggered(){
new JavaTestKit(getSystem()) {{
- new Within(duration("1 seconds")) {
+ new Within(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6)) {
protected void run() {
Follower follower = new Follower(createActorContext(getTestActor()));
- final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
+ final Boolean out = new ExpectMsg<Boolean>(DefaultConfigParamsImpl.HEART_BEAT_INTERVAL.$times(6), "ElectionTimeout") {
// do not put code outside this method, will run afterwards
protected Boolean match(Object in) {
if (in instanceof ElectionTimeout) {
}
protected Map<InstanceIdentifier<?>, DataObject> toBinding(
+ InstanceIdentifier<?> path,
final Map<YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized) {
Map<InstanceIdentifier<?>, DataObject> newMap = new HashMap<>();
if (potential.isPresent()) {
Entry<InstanceIdentifier<? extends DataObject>, DataObject> binding = potential.get();
newMap.put(binding.getKey(), binding.getValue());
+ } else if (entry.getKey().getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ DataObject bindingDataObject = getCodec().toBinding(path, entry.getValue());
+ if (bindingDataObject != null) {
+ newMap.put(path, bindingDataObject);
+ }
}
} catch (DeserializationException e) {
LOG.warn("Failed to transform {}, omitting it", entry, e);
}
}
- protected Set<InstanceIdentifier<?>> toBinding(
+ protected Set<InstanceIdentifier<?>> toBinding(InstanceIdentifier<?> path,
final Set<YangInstanceIdentifier> normalized) {
Set<InstanceIdentifier<?>> hashSet = new HashSet<>();
for (YangInstanceIdentifier normalizedPath : normalized) {
if (potential.isPresent()) {
InstanceIdentifier<? extends DataObject> binding = potential.get();
hashSet.add(binding);
+ } else if (normalizedPath.getLastPathArgument() instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+ hashSet.add(path);
}
} catch (DeserializationException e) {
LOG.warn("Failed to transform {}, omitting it", normalizedPath, e);
@Override
public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
if (createdCache == null) {
- createdCache = Collections.unmodifiableMap(toBinding(domEvent.getCreatedData()));
+ createdCache = Collections.unmodifiableMap(toBinding(path, domEvent.getCreatedData()));
}
return createdCache;
}
@Override
public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
if (updatedCache == null) {
- updatedCache = Collections.unmodifiableMap(toBinding(domEvent.getUpdatedData()));
+ updatedCache = Collections.unmodifiableMap(toBinding(path, domEvent.getUpdatedData()));
}
return updatedCache;
@Override
public Set<InstanceIdentifier<?>> getRemovedPaths() {
if (removedCache == null) {
- removedCache = Collections.unmodifiableSet(toBinding(domEvent.getRemovedPaths()));
+ removedCache = Collections.unmodifiableSet(toBinding(path, domEvent.getRemovedPaths()));
}
return removedCache;
}
@Override
public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
if (originalCache == null) {
- originalCache = Collections.unmodifiableMap(toBinding(domEvent.getOriginalData()));
+ originalCache = Collections.unmodifiableMap(toBinding(path, domEvent.getOriginalData()));
}
return originalCache;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.controller.sal.binding.api.mount.MountProviderInstance;
import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker;
import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
--- /dev/null
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+
+public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
+ private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+ private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+ private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
+ TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeLeafOnlyUsesAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> COMPLEX_AUGMENT =
+ TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexUsesAugment.class);
+ private static final ListViaUsesKey LIST_VIA_USES_KEY =
+ new ListViaUsesKey("list key");
+ private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
+ new ListViaUsesKey("list key modified");
+
+ @Test
+ public void leafOnlyAugmentationCreatedTest() {
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
+ assertEmpty(event.getUpdatedData());
+ assertEmpty(event.getOriginalData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void leafOnlyAugmentationUpdatedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+ assertCommit(writeTx.submit());
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
+ assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+ assertEmpty(event.getCreatedData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void leafOnlyAugmentationDeletedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
+ assertCommit(writeTx.submit());
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
+ assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
+ assertEmpty(event.getCreatedData());
+ assertEmpty(event.getUpdatedData());
+ }
+
+ @Test
+ public void complexAugmentationCreatedTest() {
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
+ assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+ assertEmpty(event.getUpdatedData());
+ assertEmpty(event.getOriginalData());
+ assertEmpty(event.getRemovedPaths());
+ }
+
+ @Test
+ public void complexAugmentationUpdatedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
+ assertCommit(writeTx.submit());
+ TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
+ assertCommit(writeTx.submit());
+ assertTrue(listener.hasEvent());
+ AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+ assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
+ assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
+ assertContains(event.getRemovedPaths(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+ assertContains(event.getOriginalData(), COMPLEX_AUGMENT);
+ assertContains(event.getOriginalData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+ }
+}
import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
<type>test-jar</type>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-service</artifactId>
+++ /dev/null
-/*
- * Copyright (c) 2014 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.binding.test.bugfix;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.junit.Ignore;
-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.test.AbstractDataServiceTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-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.config.rev130819.flows.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
-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.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-@SuppressWarnings("deprecation")
-public class DOMCodecBug01Test extends AbstractDataServiceTest {
-
- private static final long FLOW_ID = 1234;
- private static final String NODE_ID = "node:1";
-
- private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
-
- private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) //
- .child(Node.class, NODE_KEY).toInstance();
-
- private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
-
- private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
-
- private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
- InstanceIdentifier.builder(Flows.class) //
- .child(Flow.class, FLOW_KEY) //
- .toInstance();
-
-
-
- /**
- *
- * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=
- *
- * Cannot compile CoDec for
- * org.opendaylight.yang.gen.v1.urn.opendaylight.flow
- * .config.rev130819.flows.Flow
- *
- * When invoking following code in the consumer, user got an
- * IllegalStateException during creation of mapping between Java DTOs and
- * data-dom.
- *
- * Exception was compilation error which was caused by incorect generation
- * of code.
- *
- * Reported by Depthi V V
- *
- * @deprecated This test tests indirect generation, which should be tested
- * different way. the test creates conflicting transactions
- * and assumes correct commit - to test codec generation
- *
- */
- @Test
- @Ignore
- @Deprecated
- public void testIndirectGeneration() throws Exception {
-
- ExecutorService basePool = Executors.newFixedThreadPool(2);
- ListeningExecutorService listenablePool = MoreExecutors.listeningDecorator(basePool);
-
- createFlow();
-
- Object lock = new Object();
- CreateFlowTask task1 = new CreateFlowTask(lock);
- CreateFlowTask task2 = new CreateFlowTask(lock);
- CreateFlowTask task3 = new CreateFlowTask(lock);
-
- ListenableFuture<Void> task1Future = listenablePool.submit(task1);
- ListenableFuture<Void> task2Future = listenablePool.submit(task2);
- ListenableFuture<Void> task3Future = listenablePool.submit(task3);
-
-
- @SuppressWarnings("unchecked")
- ListenableFuture<List<Void>> compositeFuture = Futures.allAsList(task1Future,task2Future,task3Future);
-
- Thread.sleep(500);
- //lock.notifyAll();
- compositeFuture.get();
-
- verifyDataAreStoredProperly();
-
- DataModificationTransaction modification2 = baDataService.beginTransaction();
- modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
-
- DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
- assertNotNull(originalData);
- RpcResult<TransactionStatus> ret2 = modification2.commit().get();
-
- assertNotNull(ret2);
- assertEquals(TransactionStatus.COMMITED, ret2.getResult());
-
- // Data are not in the store.
- assertNull(baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA));
-
- }
-
- private void createFlow() throws Exception {
-
- DataModificationTransaction modification = baDataService.beginTransaction();
-
- FlowBuilder flow = new FlowBuilder();
- MatchBuilder match = new MatchBuilder();
- VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
- VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
- VlanId vlanId = new VlanId(10);
- vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
- match.setVlanMatch(vlanBuilder.build());
-
- flow.setKey(FLOW_KEY);
- flow.setMatch(match.build());
- flow.setNode(NODE_REF);
- InstructionsBuilder instructions = new InstructionsBuilder();
- InstructionBuilder instruction = new InstructionBuilder();
-
- instruction.setOrder(10);
- ApplyActionsBuilder applyActions = new ApplyActionsBuilder();
- List<Action> actionList = new ArrayList<>();
- PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder();
- popMplsAction.setEthernetType(34);
- actionList.add(new ActionBuilder().setAction(new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction.build()).build()).setOrder(10).build());
-
- applyActions.setAction(actionList );
-
- instruction.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions.build()).build());
-
-
- List<Instruction> instructionList = Collections.<Instruction>singletonList(instruction.build());
- instructions.setInstruction(instructionList );
-
- flow.setInstructions(instructions.build());
- modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build());
- RpcResult<TransactionStatus> ret = modification.commit().get();
- assertNotNull(ret);
- assertEquals(TransactionStatus.COMMITED, ret.getResult());
- }
-
- private void createFlow2() throws Exception {
- DataModificationTransaction modification = baDataService.beginTransaction();
- long id = 123;
- FlowKey key = new FlowKey(id, new NodeRef(NODE_INSTANCE_ID_BA));
- InstanceIdentifier<?> path1;
- FlowBuilder flow = new FlowBuilder();
- flow.setKey(key);
- MatchBuilder match = new MatchBuilder();
- match.setLayer4Match(new TcpMatchBuilder().build());
- flow.setMatch(match.build());
-
- path1 = InstanceIdentifier.builder(Flows.class).child(Flow.class, key).toInstance();
- // DataObject cls = (DataObject) modification.readConfigurationData(path1);
- modification.putConfigurationData(path1, flow.build());
- modification.commit();
-
- }
-
- private class CreateFlowTask implements Callable<Void> {
-
- public CreateFlowTask(final Object startSync) {
- }
-
- @Override
- public Void call() {
- try {
- //startSyncObj ect.wait();
- //Thread.sleep(500);
- createFlow();
- createFlow2();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return null;
- }
- }
-
- private void verifyDataAreStoredProperly() {
- CompositeNode biFlows = biDataService.readConfigurationData(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.of(Flows.QNAME));
- assertNotNull(biFlows);
- CompositeNode biFlow = biFlows.getFirstCompositeByName(Flow.QNAME);
- assertNotNull(biFlow);
- }
-
-
-}
</parent>
<artifactId>sal-binding-it</artifactId>
- <properties>
- <sonar.jacoco.itReportPath>../sal-binding-broker/target/jacoco-it.exec</sonar.jacoco.itReportPath>
- <!-- Sonar jacoco plugin to get integration test coverage info -->
- <sonar.jacoco.reportPath>../sal-binding-broker/target/jacoco.exec</sonar.jacoco.reportPath>
- </properties>
-
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <scope>provided</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-service</artifactId>
</lifecycleMappingMetadata>
</configuration>
</plugin>
- <plugin>
- <groupId>org.jacoco</groupId>
- <artifactId>jacoco-maven-plugin</artifactId>
- <version>${jacoco.version}</version>
- <configuration>
- <destFile>../sal-binding-broker/target/jacoco-it.exec</destFile>
- <includes>
- <include>org.opendaylight.controller.*</include>
- </includes>
- </configuration>
- <executions>
- <execution>
- <id>pre-test</id>
- <goals>
- <goal>prepare-agent</goal>
- </goals>
- </execution>
- <execution>
- <id>post-test</id>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- </executions>
- </plugin>
</plugins>
</pluginManagement>
<plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <reuseForks>false</reuseForks>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.jacoco</groupId>
- <artifactId>jacoco-maven-plugin</artifactId>
- <configuration>
- <includes>
- <include>org.opendaylight.controller.*</include>
- </includes>
- </configuration>
- <executions>
- <execution>
- <id>pre-test</id>
- <goals>
- <goal>prepare-agent</goal>
- </goals>
- </execution>
- <execution>
- <id>post-test</id>
- <goals>
- <goal>report</goal>
- </goals>
- <phase>test</phase>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>maven-paxexam-plugin</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
- <artifactId>sal-protocolbuffer-encoding</artifactId>
+ <artifactId>sal-clustering-commons</artifactId>
<packaging>bundle</packaging>
# org.opendaylight.controller.protobuff.messages to properly exclude from sonar.
########################################################################################################
-protoc --proto_path=src/main/resources --java_out=src/main/java src/main/resources/*.proto
+protoc --proto_path=src/main/resources --proto_path=../sal-akka-raft/src/main/resources --java_out=src/main/java src/main/resources/*.proto
echo "Done generating Java source files."
public class PathUtils {
public static String getParentPath(String currentElementPath){
- String parentPath = "";
+ StringBuilder parentPath = new StringBuilder();
if(currentElementPath != null){
String[] parentPaths = currentElementPath.split("/");
if(parentPaths.length > 2){
for(int i=0;i<parentPaths.length-1;i++){
if(parentPaths[i].length() > 0){
- parentPath += "/" + parentPaths[i];
+ parentPath.append("/");
+ parentPath.append(parentPaths[i]);
}
}
}
}
- return parentPath;
+ return parentPath.toString();
}
}
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: CompositeModificationPayload.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Cohort.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Common.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: SimpleNormalizedNode.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: DataChangeListener.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Persistent.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: ListenerRegistration.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: ShardManager.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: ShardTransactionChain.proto
-/*
- *
- * Copyright (c) 2014 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
- *
- */
-
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: ShardTransaction.proto
*/
com.google.protobuf.ByteString
getTransactionIdBytes();
+
+ // required int32 transactionType = 2;
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ boolean hasTransactionType();
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ int getTransactionType();
}
/**
* Protobuf type {@code org.opendaylight.controller.mdsal.CreateTransaction}
transactionId_ = input.readBytes();
break;
}
+ case 16: {
+ bitField0_ |= 0x00000002;
+ transactionType_ = input.readInt32();
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
}
}
+ // required int32 transactionType = 2;
+ public static final int TRANSACTIONTYPE_FIELD_NUMBER = 2;
+ private int transactionType_;
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ public boolean hasTransactionType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ public int getTransactionType() {
+ return transactionType_;
+ }
+
private void initFields() {
transactionId_ = "";
+ transactionType_ = 0;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
memoizedIsInitialized = 0;
return false;
}
+ if (!hasTransactionType()) {
+ memoizedIsInitialized = 0;
+ return false;
+ }
memoizedIsInitialized = 1;
return true;
}
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeBytes(1, getTransactionIdBytes());
}
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeInt32(2, transactionType_);
+ }
getUnknownFields().writeTo(output);
}
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, getTransactionIdBytes());
}
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeInt32Size(2, transactionType_);
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
super.clear();
transactionId_ = "";
bitField0_ = (bitField0_ & ~0x00000001);
+ transactionType_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
return this;
}
to_bitField0_ |= 0x00000001;
}
result.transactionId_ = transactionId_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.transactionType_ = transactionType_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
transactionId_ = other.transactionId_;
onChanged();
}
+ if (other.hasTransactionType()) {
+ setTransactionType(other.getTransactionType());
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
return false;
}
+ if (!hasTransactionType()) {
+
+ return false;
+ }
return true;
}
return this;
}
+ // required int32 transactionType = 2;
+ private int transactionType_ ;
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ public boolean hasTransactionType() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ public int getTransactionType() {
+ return transactionType_;
+ }
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ public Builder setTransactionType(int value) {
+ bitField0_ |= 0x00000002;
+ transactionType_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>required int32 transactionType = 2;</code>
+ */
+ public Builder clearTransactionType() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ transactionType_ = 0;
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.CreateTransaction)
}
java.lang.String[] descriptorData = {
"\n\026ShardTransaction.proto\022!org.opendaylig" +
"ht.controller.mdsal\032\014Common.proto\"\022\n\020Clo" +
- "seTransaction\"\027\n\025CloseTransactionReply\"*" +
+ "seTransaction\"\027\n\025CloseTransactionReply\"C" +
"\n\021CreateTransaction\022\025\n\rtransactionId\030\001 \002" +
- "(\t\"M\n\026CreateTransactionReply\022\034\n\024transact" +
- "ionActorPath\030\001 \002(\t\022\025\n\rtransactionId\030\002 \002(" +
- "\t\"\022\n\020ReadyTransaction\"*\n\025ReadyTransactio" +
- "nReply\022\021\n\tactorPath\030\001 \002(\t\"l\n\nDeleteData\022" +
- "^\n\037instanceIdentifierPathArguments\030\001 \002(\013" +
- "25.org.opendaylight.controller.mdsal.Ins",
- "tanceIdentifier\"\021\n\017DeleteDataReply\"j\n\010Re" +
- "adData\022^\n\037instanceIdentifierPathArgument" +
- "s\030\001 \002(\01325.org.opendaylight.controller.md" +
- "sal.InstanceIdentifier\"P\n\rReadDataReply\022" +
- "?\n\016normalizedNode\030\001 \001(\0132\'.org.opendaylig" +
- "ht.controller.mdsal.Node\"\254\001\n\tWriteData\022^" +
- "\n\037instanceIdentifierPathArguments\030\001 \002(\0132" +
- "5.org.opendaylight.controller.mdsal.Inst" +
- "anceIdentifier\022?\n\016normalizedNode\030\002 \002(\0132\'" +
- ".org.opendaylight.controller.mdsal.Node\"",
- "\020\n\016WriteDataReply\"\254\001\n\tMergeData\022^\n\037insta" +
+ "(\t\022\027\n\017transactionType\030\002 \002(\005\"M\n\026CreateTra" +
+ "nsactionReply\022\034\n\024transactionActorPath\030\001 " +
+ "\002(\t\022\025\n\rtransactionId\030\002 \002(\t\"\022\n\020ReadyTrans" +
+ "action\"*\n\025ReadyTransactionReply\022\021\n\tactor" +
+ "Path\030\001 \002(\t\"l\n\nDeleteData\022^\n\037instanceIden" +
+ "tifierPathArguments\030\001 \002(\01325.org.opendayl",
+ "ight.controller.mdsal.InstanceIdentifier" +
+ "\"\021\n\017DeleteDataReply\"j\n\010ReadData\022^\n\037insta" +
"nceIdentifierPathArguments\030\001 \002(\01325.org.o" +
"pendaylight.controller.mdsal.InstanceIde" +
- "ntifier\022?\n\016normalizedNode\030\002 \002(\0132\'.org.op" +
- "endaylight.controller.mdsal.Node\"\020\n\016Merg" +
- "eDataReplyBV\n:org.opendaylight.controlle" +
- "r.protobuff.messages.transactionB\030ShardT" +
- "ransactionMessages"
+ "ntifier\"P\n\rReadDataReply\022?\n\016normalizedNo" +
+ "de\030\001 \001(\0132\'.org.opendaylight.controller.m" +
+ "dsal.Node\"\254\001\n\tWriteData\022^\n\037instanceIdent" +
+ "ifierPathArguments\030\001 \002(\01325.org.opendayli" +
+ "ght.controller.mdsal.InstanceIdentifier\022" +
+ "?\n\016normalizedNode\030\002 \002(\0132\'.org.opendaylig",
+ "ht.controller.mdsal.Node\"\020\n\016WriteDataRep" +
+ "ly\"\254\001\n\tMergeData\022^\n\037instanceIdentifierPa" +
+ "thArguments\030\001 \002(\01325.org.opendaylight.con" +
+ "troller.mdsal.InstanceIdentifier\022?\n\016norm" +
+ "alizedNode\030\002 \002(\0132\'.org.opendaylight.cont" +
+ "roller.mdsal.Node\"\020\n\016MergeDataReplyBV\n:o" +
+ "rg.opendaylight.controller.protobuff.mes" +
+ "sages.transactionB\030ShardTransactionMessa" +
+ "ges"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
internal_static_org_opendaylight_controller_mdsal_CreateTransaction_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_org_opendaylight_controller_mdsal_CreateTransaction_descriptor,
- new java.lang.String[] { "TransactionId", });
+ new java.lang.String[] { "TransactionId", "TransactionType", });
internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_descriptor =
getDescriptor().getMessageTypes().get(3);
internal_static_org_opendaylight_controller_mdsal_CreateTransactionReply_fieldAccessorTable = new
message CreateTransaction{
required string transactionId = 1;
+ required int32 transactionType =2;
}
message CreateTransactionReply{
NormalizedNodeToNodeCodec codec =
new NormalizedNodeToNodeCodec(schemaContext);
+ long start = System.currentTimeMillis();
Container container =
codec.encode(instanceIdentifierFromString(id), output);
+ long end = System.currentTimeMillis();
+
+ System.out.println("Timetaken to encode :"+(end-start));
assertNotNull(container);
assertEquals(id, container.getParentPath() + "/"
// first get the node representation of normalized node
final Node node = container.getNormalizedNode();
+ start = System.currentTimeMillis();
NormalizedNode<?, ?> normalizedNode =
codec.decode(instanceIdentifierFromString(id), node);
+ end = System.currentTimeMillis();
+
+ System.out.println("Timetaken to decode :"+(end-start));
assertEquals(normalizedNode.getValue().toString(), output.getValue()
.toString());
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 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
+-->
+<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.1-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-clustering-config</artifactId>
+ <description>Configuration files for md-sal clustering</description>
+ <packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/*.conf</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+ <name>inmemory-data-broker</name>
+
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+
+ <config-data-store>
+ <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+ <name>distributed-config-store-service</name>
+ </config-data-store>
+
+ <operational-data-store>
+ <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+ <name>distributed-operational-store-service</name>
+ </operational-data-store>
+ </module>
+
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-operational-datastore-provider</type>
+ <name>distributed-operational-store-module</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:distributed-datastore-provider">prefix:distributed-config-datastore-provider</type>
+ <name>distributed-config-store-module</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:remote-rpc-connector">prefix:remote-rpc-connector</type>
+ <name>remote-rpc-connector</name>
+ <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:config:remote-rpc-connector">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-broker>
+ </module>
+
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+ <service>
+ <type xmlns:config-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store">config-dom-store-spi:config-dom-datastore</type>
+ <instance>
+ <name>distributed-config-store-service</name>
+ <provider>/modules/module[type='distributed-config-datastore-provider'][name='distributed-config-store-module']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:operational-dom-store-spi="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store">operational-dom-store-spi:operational-dom-datastore</type>
+ <instance>
+ <name>distributed-operational-store-service</name>
+ <provider>/modules/module[type='distributed-operational-datastore-provider'][name='distributed-operational-store-module']</provider>
+ </instance>
+ </service>
+
+ </services>
+ </data>
+ </configuration>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
+ </required-capabilities>
+</snapshot>
--- /dev/null
+
+odl-cluster-data {
+ akka {
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ serializers {
+ java = "akka.serialization.JavaSerializer"
+ proto = "akka.remote.serialization.ProtobufSerializer"
+ }
+
+ serialization-bindings {
+ "com.google.protobuf.Message" = proto
+
+ }
+ }
+ remote {
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "<CHANGE_ME>"
+ port = 2550
+ maximum-frame-size = 2097152
+ send-buffer-size = 52428800
+ receive-buffer-size = 52428800
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@<CHANGE_ME>:2550"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
+
+odl-cluster-rpc {
+ akka {
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+
+ }
+ remote {
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "<CHANGE_ME>"
+ port = 2551
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@<CHANGE_ME>:2551"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
--- /dev/null
+# This file describes which shards live on which members
+# The format for a module-shards is as follows,
+# {
+# name = "<friendly_name_of_the_module>"
+# shards = [
+# {
+# name="<any_name_that_is_unique_for_the_module>"
+# replicas = [
+# "<name_of_member_on_which_to_run>"
+# ]
+# ]
+# }
+#
+# For Helium we support only one shard per module. Beyond Helium
+# we will support more than 1
+# The replicas section is a collection of member names. This information
+# will be used to decide on which members replicas of a particular shard will be
+# located. Once replication is integrated with the distributed data store then
+# this section can have multiple entries.
+#
+#
+
+
+module-shards = [
+ {
+ name = "default"
+ shards = [
+ {
+ name="default"
+ replicas = [
+ "member-1"
+ ]
+ }
+ ]
+ },
+ {
+ name = "topology"
+ shards = [
+ {
+ name="topology"
+ replicas = [
+ "member-1"
+ ]
+ }
+ ]
+ },
+ {
+ name = "inventory"
+ shards = [
+ {
+ name="inventory"
+ replicas = [
+ "member-1"
+ ]
+ }
+ ]
+ },
+ {
+ name = "toaster"
+ shards = [
+ {
+ name="toaster"
+ replicas = [
+ "member-1"
+ ]
+ }
+ ]
+ }
+
+]
--- /dev/null
+# This file should describe all the modules that need to be placed in a separate shard
+# The format of the configuration is as follows
+# {
+# name = "<friendly_name_of_module>"
+# namespace = "<the yang namespace of the module>"
+# shard-strategy = "module"
+# }
+#
+# Note that at this time the only shard-strategy we support is module which basically
+# will put all the data of a single module in two shards (one for config and one for
+# operational data)
+
+modules = [
+ {
+ name = "inventory"
+ namespace = "urn:opendaylight:inventory"
+ shard-strategy = "module"
+ },
+
+ {
+ name = "topology"
+ namespace = "urn:TBD:params:xml:ns:yang:network-topology"
+ shard-strategy = "module"
+ },
+
+ {
+ name = "toaster"
+ namespace = "http://netconfcentral.org/ns/toaster"
+ shard-strategy = "module"
+ }
+
+]
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications 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.md.sal.common.api.data;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+
+import com.google.common.base.Function;
+
+/**
+ * A type of TransactionCommitFailedException that indicates a situation that would result in a
+ * threading deadlock. This can occur if a caller that submits a write transaction tries to perform
+ * a blocking call via one of the <code>get</code> methods on the returned ListenableFuture. Callers
+ * should process the commit result asynchronously (via Futures#addCallback) to ensure deadlock
+ * won't occur.
+ *
+ * @author Thomas Pantelis
+ */
+public class TransactionCommitDeadlockException extends TransactionCommitFailedException {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String DEADLOCK_MESSAGE =
+ "An attempt to block on a ListenableFuture via a get method from a write " +
+ "transaction submit was detected that would result in deadlock. The commit " +
+ "result must be obtained asynchronously, e.g. via Futures#addCallback, to avoid deadlock.";
+
+ public static Function<Void, Exception> DEADLOCK_EXECUTOR_FUNCTION = new Function<Void, Exception>() {
+ @Override
+ public Exception apply(Void notUsed) {
+ return new TransactionCommitDeadlockException( DEADLOCK_MESSAGE,
+ RpcResultBuilder.newError(ErrorType.APPLICATION, "lock-denied", DEADLOCK_MESSAGE));
+ }
+ };
+
+ public TransactionCommitDeadlockException(String message, final RpcError... errors) {
+ super(message, errors);
+ }
+}
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Path;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>sal-protocolbuffer-encoding</artifactId>
+ <artifactId>sal-clustering-commons</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<Private-Package></Private-Package>
<Import-Package>!*snappy;!org.jboss.*;*</Import-Package>
<Embed-Dependency>
- sal-protocolbuffer-encoding;
+ sal-clustering-commons;
sal-akka-raft;
!sal*;
!*config-api*;
@Nullable @Override public ActorSystem apply(@Nullable Void aVoid) {
ActorSystem system =
- ActorSystem.create("opendaylight-cluster", ConfigFactory
- .load().getConfig("ODLCluster"));
+ ActorSystem.create("opendaylight-cluster-data", ConfigFactory
+ .load().getConfig("odl-cluster-data"));
system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
return system;
}
}
@Override public void handleReceive(Object message) throws Exception {
- if(message.getClass().equals(DataChanged.SERIALIZABLE_CLASS)){
+ if(message instanceof DataChanged){
dataChanged(message);
} else if(message instanceof EnableNotification){
enableNotification((EnableNotification) message);
return;
}
- DataChanged reply = DataChanged.fromSerialize(schemaContext,message, pathId);
+ DataChanged reply = (DataChanged) message;
AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>
change = reply.getChange();
this.listener.onDataChanged(change);
if(getSender() != null){
- getSender().tell(new DataChangedReply().toSerializable(), getSelf());
+ getSender().tell(new DataChangedReply(), getSelf());
}
}
@Override public void onDataChanged(
AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
- dataChangeListenerActor.tell(new DataChanged(schemaContext,change).toSerializable(), null);
+ dataChangeListenerActor.tell(new DataChanged(schemaContext,change), null);
}
}
package org.opendaylight.controller.cluster.datastore;
-import java.util.concurrent.Executors;
-
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
-
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.Executors;
/**
*
Object result = actorContext.executeLocalShardOperation(shardName,
new RegisterChangeListener(path, dataChangeListenerActor.path(),
- scope).toSerializable(),
+ scope),
ActorContext.ASK_DURATION
);
if (result != null) {
- RegisterChangeListenerReply reply = RegisterChangeListenerReply
- .fromSerializable(actorContext.getActorSystem(), result);
+ RegisterChangeListenerReply reply = (RegisterChangeListenerReply) result;
return new DataChangeListenerRegistrationProxy(actorContext
.actorSelection(reply.getListenerRegistrationPath()), listener,
dataChangeListenerActor);
import akka.event.LoggingAdapter;
import akka.japi.Creator;
import akka.serialization.Serialization;
-
+import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
-
import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardMBeanFactory;
import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardStats;
import org.opendaylight.controller.cluster.datastore.messages.CommitTransactionReply;
import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
import org.opendaylight.controller.cluster.datastore.modification.Modification;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
+import org.opendaylight.controller.cluster.raft.ConfigParams;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
import org.opendaylight.controller.cluster.raft.RaftActor;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import scala.concurrent.duration.FiniteDuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
/**
* A Shard represents a portion of the logical data tree <br/>
*/
public class Shard extends RaftActor {
+ private static final ConfigParams configParams = new ShardConfigParams();
+
public static final String DEFAULT_NAME = "default";
private final ListeningExecutorService storeExecutor =
private final List<ActorSelection> dataChangeListeners = new ArrayList<>();
private Shard(String name, Map<String, String> peerAddresses) {
- super(name, peerAddresses);
+ super(name, peerAddresses, Optional.of(configParams));
this.name = name;
} else if(getLeader() != null){
getLeader().forward(message, getContext());
}
- } else if (message.getClass().equals(RegisterChangeListener.SERIALIZABLE_CLASS)) {
- registerChangeListener(RegisterChangeListener.fromSerializable(getContext().system(), message));
+ } else if (message instanceof RegisterChangeListener) {
+ registerChangeListener((RegisterChangeListener) message);
} else if (message instanceof UpdateSchemaContext) {
updateSchemaContext((UpdateSchemaContext) message);
} else if (message instanceof ForwardedCommitTransaction) {
}
}
+ private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
+ if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
+ return getContext().actorOf(
+ ShardTransaction.props( store.newReadOnlyTransaction(), getSelf(), schemaContext), transactionId);
+
+ }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
+ return getContext().actorOf(
+ ShardTransaction.props( store.newReadWriteTransaction(), getSelf(), schemaContext), transactionId);
+
+
+ }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
+ return getContext().actorOf(
+ ShardTransaction.props( store.newWriteOnlyTransaction(), getSelf(), schemaContext), transactionId);
+ }else{
+ throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+ }
+ }
+
private void createTransaction(CreateTransaction createTransaction) {
- DOMStoreReadWriteTransaction transaction =
- store.newReadWriteTransaction();
+
String transactionId = "shard-" + createTransaction.getTransactionId();
LOG.info("Creating transaction : {} " , transactionId);
- ActorRef transactionActor = getContext().actorOf(
- ShardTransaction.props(transaction, getSelf(), schemaContext), transactionId);
+ ActorRef transactionActor = createTypedTransactionActor(createTransaction,transactionId);
getSender()
.tell(new CreateTransactionReply(Serialization.serializedActorPath(transactionActor), createTransaction.getTransactionId()).toSerializable(),
LOG.debug("registerDataChangeListener sending reply, listenerRegistrationPath = " + listenerRegistration.path().toString());
getSender()
- .tell(new RegisterChangeListenerReply(listenerRegistration.path()).toSerializable(),
+ .tell(new RegisterChangeListenerReply(listenerRegistration.path()),
getSelf());
}
for(ActorSelection dataChangeListener : dataChangeListeners){
dataChangeListener.tell(new EnableNotification(isLeader()), getSelf());
}
+
+ if(getLeaderId() != null){
+ shardMBean.setLeader(getLeaderId());
+ }
+
+ shardMBean.setRaftState(getRaftState().name());
}
@Override public String persistenceId() {
return this.name;
}
+
+
+ private static class ShardConfigParams extends DefaultConfigParamsImpl {
+ public static final FiniteDuration HEART_BEAT_INTERVAL =
+ new FiniteDuration(500, TimeUnit.MILLISECONDS);
+
+ @Override public FiniteDuration getHeartBeatInterval() {
+ return HEART_BEAT_INTERVAL;
+ }
+ }
}
--- /dev/null
+/*
+ *
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardReadTransaction extends ShardTransaction {
+ private final DOMStoreReadTransaction transaction;
+ private final LoggingAdapter log =
+ Logging.getLogger(getContext().system(), this);
+
+ public ShardReadTransaction(DOMStoreReadTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+ super(shardActor, schemaContext);
+ this.transaction = transaction;
+
+ }
+
+ public ShardReadTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+ super(transactionChain, shardActor, schemaContext);
+ this.transaction = transaction;
+ }
+
+ @Override
+ public void handleReceive(Object message) throws Exception {
+ if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ readData(transaction,ReadData.fromSerializable(message));
+ } else {
+ super.handleReceive(message);
+ }
+ }
+ protected void closeTransaction(CloseTransaction message) {
+ transaction.close();
+ getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+ getSelf().tell(PoisonPill.getInstance(), getSelf());
+ }
+
+}
--- /dev/null
+/*
+ *
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardReadWriteTransaction extends ShardTransaction {
+ private final DOMStoreReadWriteTransaction transaction;
+ private final LoggingAdapter log =
+ Logging.getLogger(getContext().system(), this);
+ public ShardReadWriteTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+ super(transactionChain, shardActor, schemaContext);
+ this.transaction = transaction;
+ }
+
+ public ShardReadWriteTransaction(DOMStoreReadWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+ super( shardActor, schemaContext);
+ this.transaction = transaction;
+ }
+
+ @Override
+ public void handleReceive(Object message) throws Exception {
+ if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ readData(transaction,ReadData.fromSerializable(message));
+ }else if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ writeData(transaction, WriteData.fromSerializable(message, schemaContext));
+ } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ mergeData(transaction, MergeData.fromSerializable(message, schemaContext));
+ } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ deleteData(transaction,DeleteData.fromSerizalizable(message));
+ } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ readyTransaction(transaction,new ReadyTransaction());
+ }else {
+ super.handleReceive(message);
+ }
+ }
+
+ protected void closeTransaction(CloseTransaction message) {
+ transaction.close();
+ getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+ getSelf().tell(PoisonPill.getInstance(), getSelf());
+ }
+}
package org.opendaylight.controller.cluster.datastore;
import akka.actor.ActorRef;
-import akka.actor.PoisonPill;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
-import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
import org.opendaylight.controller.cluster.datastore.messages.MergeData;
import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
import org.opendaylight.controller.cluster.datastore.modification.MutableCompositeModification;
import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
* <li> {@link org.opendaylight.controller.cluster.datastore.messages.CloseTransaction}
* </p>
*/
-public class ShardTransaction extends AbstractUntypedActor {
-
- private final ActorRef shardActor;
- private final SchemaContext schemaContext;
-
- // FIXME : see below
- // If transactionChain is not null then this transaction is part of a
- // transactionChain. Not really clear as to what that buys us
- private final DOMStoreTransactionChain transactionChain;
-
- private final DOMStoreReadWriteTransaction transaction;
-
- private final MutableCompositeModification modification =
- new MutableCompositeModification();
-
- private final LoggingAdapter log =
- Logging.getLogger(getContext().system(), this);
-
- public ShardTransaction(DOMStoreReadWriteTransaction transaction,
- ActorRef shardActor, SchemaContext schemaContext) {
- this(null, transaction, shardActor, schemaContext);
- }
-
- public ShardTransaction(DOMStoreTransactionChain transactionChain, DOMStoreReadWriteTransaction transaction,
- ActorRef shardActor, SchemaContext schemaContext) {
- this.transactionChain = transactionChain;
- this.transaction = transaction;
- this.shardActor = shardActor;
- this.schemaContext = schemaContext;
- }
-
-
-
- public static Props props(final DOMStoreReadWriteTransaction transaction,
- final ActorRef shardActor, final SchemaContext schemaContext) {
- return Props.create(new Creator<ShardTransaction>() {
-
- @Override
- public ShardTransaction create() throws Exception {
- return new ShardTransaction(transaction, shardActor, schemaContext);
- }
- });
- }
-
- public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadWriteTransaction transaction,
- final ActorRef shardActor, final SchemaContext schemaContext) {
- return Props.create(new Creator<ShardTransaction>() {
-
- @Override
- public ShardTransaction create() throws Exception {
- return new ShardTransaction(transactionChain, transaction, shardActor, schemaContext);
- }
- });
+public abstract class ShardTransaction extends AbstractUntypedActor {
+
+ private final ActorRef shardActor;
+ protected final SchemaContext schemaContext;
+
+ // FIXME : see below
+ // If transactionChain is not null then this transaction is part of a
+ // transactionChain. Not really clear as to what that buys us
+ private final DOMStoreTransactionChain transactionChain;
+
+
+ private final MutableCompositeModification modification =
+ new MutableCompositeModification();
+
+ private final LoggingAdapter log =
+ Logging.getLogger(getContext().system(), this);
+
+ protected ShardTransaction(
+ ActorRef shardActor, SchemaContext schemaContext) {
+ this(null, shardActor, schemaContext);
+ }
+
+ protected ShardTransaction(DOMStoreTransactionChain transactionChain,
+ ActorRef shardActor, SchemaContext schemaContext) {
+ this.transactionChain = transactionChain;
+ //this.transaction = transaction;
+ this.shardActor = shardActor;
+ this.schemaContext = schemaContext;
+ }
+
+
+
+ public static Props props(final DOMStoreReadTransaction transaction,
+ final ActorRef shardActor, final SchemaContext schemaContext) {
+ return Props.create(new Creator<ShardTransaction>() {
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardReadTransaction(transaction, shardActor, schemaContext);
+ }
+ });
+ }
+
+ public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadTransaction transaction,
+ final ActorRef shardActor, final SchemaContext schemaContext) {
+ return Props.create(new Creator<ShardTransaction>() {
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardReadTransaction(transactionChain, transaction, shardActor, schemaContext);
+ }
+ });
+ }
+
+ public static Props props(final DOMStoreReadWriteTransaction transaction,
+ final ActorRef shardActor, final SchemaContext schemaContext) {
+ return Props.create(new Creator<ShardTransaction>() {
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardReadWriteTransaction(transaction, shardActor, schemaContext);
+ }
+ });
+ }
+
+ public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreReadWriteTransaction transaction,
+ final ActorRef shardActor, final SchemaContext schemaContext) {
+ return Props.create(new Creator<ShardTransaction>() {
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardReadWriteTransaction(transactionChain, transaction, shardActor, schemaContext);
+ }
+ });
+ }
+
+
+ public static Props props(final DOMStoreWriteTransaction transaction,
+ final ActorRef shardActor, final SchemaContext schemaContext) {
+ return Props.create(new Creator<ShardTransaction>() {
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardWriteTransaction(transaction, shardActor, schemaContext);
+ }
+ });
+ }
+
+ public static Props props(final DOMStoreTransactionChain transactionChain, final DOMStoreWriteTransaction transaction,
+ final ActorRef shardActor, final SchemaContext schemaContext) {
+ return Props.create(new Creator<ShardTransaction>() {
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardWriteTransaction(transactionChain, transaction, shardActor, schemaContext);
+ }
+ });
+ }
+
+
+ @Override
+ public void handleReceive(Object message) throws Exception {
+ if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
+ closeTransaction(new CloseTransaction());
+ } else if (message instanceof GetCompositedModification) {
+ // This is here for testing only
+ getSender().tell(new GetCompositeModificationReply(
+ new ImmutableCompositeModification(modification)), getSelf());
+ }else{
+ throw new Exception ("ShardTransaction:handleRecieve received an unknown message"+message);
}
-
-
- @Override
- public void handleReceive(Object message) throws Exception {
- if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
- readData(ReadData.fromSerializable(message));
- } else if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
- writeData(WriteData.fromSerializable(message, schemaContext));
- } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
- mergeData(MergeData.fromSerializable(message, schemaContext));
- } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
- deleteData(DeleteData.fromSerizalizable(message));
- } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
- readyTransaction(new ReadyTransaction());
- } else if (message.getClass().equals(CloseTransaction.SERIALIZABLE_CLASS)) {
- closeTransaction(new CloseTransaction());
- } else if (message instanceof GetCompositedModification) {
- // This is here for testing only
- getSender().tell(new GetCompositeModificationReply(
- new ImmutableCompositeModification(modification)), getSelf());
- }else{
- throw new Exception ("Shard:handleRecieve received an unknown message"+message);
+ }
+
+ abstract protected void closeTransaction(CloseTransaction message);
+
+ protected void readData(DOMStoreReadTransaction transaction,ReadData message) {
+ final ActorRef sender = getSender();
+ final ActorRef self = getSelf();
+ final YangInstanceIdentifier path = message.getPath();
+ final ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
+ transaction.read(path);
+
+ future.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Optional<NormalizedNode<?, ?>> optional = future.get();
+ if (optional.isPresent()) {
+ sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
+ } else {
+ sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ log.error(e,
+ "An exception happened when reading data from path : "
+ + path.toString());
}
- }
- private void readData(ReadData message) {
- final ActorRef sender = getSender();
- final ActorRef self = getSelf();
- final YangInstanceIdentifier path = message.getPath();
- final ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
- transaction.read(path);
-
- future.addListener(new Runnable() {
- @Override
- public void run() {
- try {
- Optional<NormalizedNode<?, ?>> optional = future.get();
- if (optional.isPresent()) {
- sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
- } else {
- sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
- }
- } catch (InterruptedException | ExecutionException e) {
- log.error(e,
- "An exception happened when reading data from path : "
- + path.toString());
- }
-
- }
- }, getContext().dispatcher());
- }
+ }
+ }, getContext().dispatcher());
+ }
- private void writeData(WriteData message) {
- modification.addModification(
- new WriteModification(message.getPath(), message.getData(),schemaContext));
- LOG.debug("writeData at path : " + message.getPath().toString());
- transaction.write(message.getPath(), message.getData());
- getSender().tell(new WriteDataReply().toSerializable(), getSelf());
- }
+ protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) {
+ modification.addModification(
+ new WriteModification(message.getPath(), message.getData(),schemaContext));
+ LOG.debug("writeData at path : " + message.getPath().toString());
+ transaction.write(message.getPath(), message.getData());
+ getSender().tell(new WriteDataReply().toSerializable(), getSelf());
+ }
- private void mergeData(MergeData message) {
- modification.addModification(
- new MergeModification(message.getPath(), message.getData(), schemaContext));
- LOG.debug("mergeData at path : " + message.getPath().toString());
- transaction.merge(message.getPath(), message.getData());
- getSender().tell(new MergeDataReply().toSerializable(), getSelf());
- }
+ protected void mergeData(DOMStoreWriteTransaction transaction, MergeData message) {
+ modification.addModification(
+ new MergeModification(message.getPath(), message.getData(), schemaContext));
+ LOG.debug("mergeData at path : " + message.getPath().toString());
+ transaction.merge(message.getPath(), message.getData());
+ getSender().tell(new MergeDataReply().toSerializable(), getSelf());
+ }
- private void deleteData(DeleteData message) {
- modification.addModification(new DeleteModification(message.getPath()));
- transaction.delete(message.getPath());
- getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
- }
+ protected void deleteData(DOMStoreWriteTransaction transaction, DeleteData message) {
+ modification.addModification(new DeleteModification(message.getPath()));
+ transaction.delete(message.getPath());
+ getSender().tell(new DeleteDataReply().toSerializable(), getSelf());
+ }
- private void readyTransaction(ReadyTransaction message) {
- DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
- ActorRef cohortActor = getContext().actorOf(
- ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
- getSender()
- .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
+ protected void readyTransaction(DOMStoreWriteTransaction transaction, ReadyTransaction message) {
+ DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
+ ActorRef cohortActor = getContext().actorOf(
+ ThreePhaseCommitCohort.props(cohort, shardActor, modification), "cohort");
+ getSender()
+ .tell(new ReadyTransactionReply(cohortActor.path()).toSerializable(), getSelf());
- }
-
- private void closeTransaction(CloseTransaction message) {
- transaction.close();
- getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
- getSelf().tell(PoisonPill.getInstance(), getSelf());
- }
+ }
- // These classes are in here for test purposes only
+ // These classes are in here for test purposes only
- static class GetCompositedModification {
+ static class GetCompositedModification {
- }
+ }
- static class GetCompositeModificationReply {
- private final CompositeModification modification;
+ static class GetCompositeModificationReply {
+ private final CompositeModification modification;
- GetCompositeModificationReply(CompositeModification modification) {
- this.modification = modification;
- }
+ GetCompositeModificationReply(CompositeModification modification) {
+ this.modification = modification;
+ }
- public CompositeModification getModification() {
- return modification;
- }
+ public CompositeModification getModification() {
+ return modification;
}
+ }
}
import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
-import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
}
}
+ private ActorRef createTypedTransactionActor(CreateTransaction createTransaction,String transactionId){
+ if(createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_ONLY.ordinal()){
+ return getContext().actorOf(
+ ShardTransaction.props( chain.newReadOnlyTransaction(), getSelf(), schemaContext), transactionId);
+
+ }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.READ_WRITE.ordinal()){
+ return getContext().actorOf(
+ ShardTransaction.props( chain.newReadWriteTransaction(), getSelf(), schemaContext), transactionId);
+
+
+ }else if (createTransaction.getTransactionType()== TransactionProxy.TransactionType.WRITE_ONLY.ordinal()){
+ return getContext().actorOf(
+ ShardTransaction.props( chain.newWriteOnlyTransaction(), getSelf(), schemaContext), transactionId);
+ }else{
+ throw new IllegalArgumentException ("CreateTransaction message has unidentified transaction type="+createTransaction.getTransactionType()) ;
+ }
+ }
+
private void createTransaction(CreateTransaction createTransaction) {
- DOMStoreReadWriteTransaction transaction =
- chain.newReadWriteTransaction();
- ActorRef transactionActor = getContext().actorOf(ShardTransaction
- .props(chain, transaction, getContext().parent(), schemaContext), "shard-" + createTransaction.getTransactionId());
+
+ ActorRef transactionActor = createTypedTransactionActor(createTransaction, "shard-" + createTransaction.getTransactionId());
getSender()
.tell(new CreateTransactionReply(transactionActor.path().toString(),createTransaction.getTransactionId()).toSerializable(),
getSelf());
--- /dev/null
+/*
+ *
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * @author: syedbahm
+ * Date: 8/6/14
+ */
+public class ShardWriteTransaction extends ShardTransaction {
+ private final DOMStoreWriteTransaction transaction;
+ private final LoggingAdapter log =
+ Logging.getLogger(getContext().system(), this);
+ public ShardWriteTransaction(DOMStoreWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+ super( shardActor, schemaContext);
+ this.transaction = transaction;
+
+ }
+
+ public ShardWriteTransaction(DOMStoreTransactionChain transactionChain, DOMStoreWriteTransaction transaction, ActorRef shardActor, SchemaContext schemaContext) {
+ super(transactionChain, shardActor, schemaContext);
+ this.transaction = transaction;
+ }
+
+ @Override
+ public void handleReceive(Object message) throws Exception {
+ if (WriteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ writeData(transaction, WriteData.fromSerializable(message, schemaContext));
+ } else if (MergeData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ mergeData(transaction, MergeData.fromSerializable(message, schemaContext));
+ } else if (DeleteData.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ deleteData(transaction,DeleteData.fromSerizalizable(message));
+ } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
+ readyTransaction(transaction,new ReadyTransaction());
+ }else {
+ super.handleReceive(message);
+ }
+ }
+
+ protected void closeTransaction(CloseTransaction message) {
+ transaction.close();
+ getSender().tell(new CloseTransactionReply().toSerializable(), getSelf());
+ getSelf().tell(PoisonPill.getInstance(), getSelf());
+ }
+}
CanCommitTransactionReply reply =
CanCommitTransactionReply.fromSerializable(response);
if (!reply.getCanCommit()) {
- System.out.println("**TOM - failed: false");
return false;
}
}
try {
Object response = actorContext.executeShardOperation(shardName,
- new CreateTransaction(identifier).toSerializable(),
+ new CreateTransaction(identifier,this.transactionType.ordinal() ).toSerializable(),
ActorContext.ASK_DURATION);
if (response.getClass()
.equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
private Long committedTransactionsCount;
private Long journalMessagesCount;
final private String shardName;
+ private String leader;
+ private String raftState;
ShardStats(String shardName){
this.shardName = shardName;
return journalMessagesCount;
}
+ @Override public String getLeader() {
+ return leader;
+ }
+
+ @Override public String getRaftState() {
+ return raftState;
+ }
public Long incrementCommittedTransactionCount() {
return committedTransactionsCount++;
}
+ public void setLeader(String leader){
+ this.leader = leader;
+ }
+
+ public void setRaftState(String raftState){
+ this.raftState = raftState;
+ }
@Override
String getShardName();
Long getCommittedTransactionsCount();
Long getJournalMessagesCount();
-
+ String getLeader();
+ String getRaftState();
}
import org.opendaylight.controller.protobuff.messages.cohort3pc.ThreePhaseCommitCohortMessages;
public class AbortTransaction implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.AbortTransaction.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.AbortTransaction.class;
@Override
public Object toSerializable() {
import org.opendaylight.controller.protobuff.messages.cohort3pc.ThreePhaseCommitCohortMessages;
public class AbortTransactionReply implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.AbortTransactionReply.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.AbortTransactionReply.class;
@Override
import org.opendaylight.controller.protobuff.messages.cohort3pc.ThreePhaseCommitCohortMessages;
public class CanCommitTransaction implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.CanCommitTransaction.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.CanCommitTransaction.class;
@Override
public Object toSerializable() {
import org.opendaylight.controller.protobuff.messages.registration.ListenerRegistrationMessages;
public class CloseDataChangeListenerRegistration implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ListenerRegistrationMessages.CloseDataChangeListenerRegistration.class;
+ public static final Class SERIALIZABLE_CLASS = ListenerRegistrationMessages.CloseDataChangeListenerRegistration.class;
@Override
public Object toSerializable() {
return ListenerRegistrationMessages.CloseDataChangeListenerRegistration.newBuilder().build();
import org.opendaylight.controller.protobuff.messages.cohort3pc.ThreePhaseCommitCohortMessages;
public class CommitTransaction implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.CommitTransaction.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.CommitTransaction.class;
@Override
public Object toSerializable() {
public class CommitTransactionReply implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.CommitTransactionReply.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.CommitTransactionReply.class;
@Override
public Object toSerializable() {
public class CreateTransaction implements SerializableMessage {
- public static Class SERIALIZABLE_CLASS = ShardTransactionMessages.CreateTransaction.class;
+ public static final Class SERIALIZABLE_CLASS = ShardTransactionMessages.CreateTransaction.class;
private final String transactionId;
+ private final int transactionType;
- public CreateTransaction(String transactionId){
+ public CreateTransaction(String transactionId, int transactionType){
this.transactionId = transactionId;
+ this.transactionType = transactionType;
}
public String getTransactionId() {
return transactionId;
}
+ public int getTransactionType() { return transactionType;}
+
@Override
public Object toSerializable() {
- return ShardTransactionMessages.CreateTransaction.newBuilder().setTransactionId(transactionId).build();
+ return ShardTransactionMessages.CreateTransaction.newBuilder().setTransactionId(transactionId).setTransactionType(transactionType).build();
}
public static CreateTransaction fromSerializable(Object message){
- return new CreateTransaction(((ShardTransactionMessages.CreateTransaction)message).getTransactionId());
+ ShardTransactionMessages.CreateTransaction createTransaction = (ShardTransactionMessages.CreateTransaction)message;
+ return new CreateTransaction(createTransaction.getTransactionId(),createTransaction.getTransactionType() );
}
}
import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionChainMessages;
public class CreateTransactionChain implements SerializableMessage{
- public static Class SERIALIZABLE_CLASS = ShardTransactionChainMessages.CreateTransactionChain.class;
+ public static final Class SERIALIZABLE_CLASS = ShardTransactionChainMessages.CreateTransactionChain.class;
@Override
public Object toSerializable() {
public class PreCommitTransaction implements SerializableMessage{
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.PreCommitTransaction.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.PreCommitTransaction.class;
@Override
public Object toSerializable() {
public class PreCommitTransactionReply implements SerializableMessage{
- public static Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.PreCommitTransactionReply.class;
+ public static final Class SERIALIZABLE_CLASS = ThreePhaseCommitCohortMessages.PreCommitTransactionReply.class;
@Override
public Object toSerializable() {
import org.opendaylight.controller.cluster.datastore.Configuration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import java.util.List;
+
public class ModuleShardStrategy implements ShardStrategy {
public static final String NAME = "module";
}
@Override public String findShard(YangInstanceIdentifier path) {
- return configuration.getShardNamesFromModuleName(moduleName).get(0);
+ List<String> shardNames =
+ configuration.getShardNamesFromModuleName(moduleName);
+ if(shardNames.size() == 0){
+ return DefaultShardStrategy.DEFAULT_SHARD;
+ }
+ return shardNames.get(0);
}
}
public interface ShardStrategy {
/**
* Find the name of the shard in which the data pointed to by the specified path belongs in
+ * <p>
+ * Should return the name of the default shard DefaultShardStrategy.DEFAULT_SHARD
+ * if no matching shard was found
*
* @param path The location of the data in the logical tree
* @return
.getLogger(InstanceIdentifierUtils.class);
public static String getParentPath(String currentElementPath) {
- String parentPath = "";
+
+ StringBuilder parentPath = new StringBuilder();
if (currentElementPath != null) {
String[] parentPaths = currentElementPath.split("/");
if (parentPaths.length > 2) {
for (int i = 0; i < parentPaths.length - 1; i++) {
if (parentPaths[i].length() > 0) {
- parentPath += "/" + parentPaths[i];
+ parentPath.append( "/");
+ parentPath.append( parentPaths[i]);
}
}
}
}
- return parentPath;
+ return parentPath.toString();
}
@Deprecated
@Override
public java.lang.AutoCloseable createInstance() {
return DistributedDataStoreFactory
- .createInstance("config", getSchemaServiceDependency());
+ .createInstance("config", getConfigSchemaServiceDependency());
}
}
@Override
public java.lang.AutoCloseable createInstance() {
return DistributedDataStoreFactory
- .createInstance("operational", getSchemaServiceDependency());
+ .createInstance("operational", getOperationalSchemaServiceDependency());
}
}
-ODLCluster{
-actor {
- serializers {
- java = "akka.serialization.JavaSerializer"
- proto = "akka.remote.serialization.ProtobufSerializer"
- }
+odl-cluster-data {
+ akka {
+ cluster {
+ roles = [
+ "member-1"
+ ]
+ }
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ serializers {
+ java = "akka.serialization.JavaSerializer"
+ proto = "akka.remote.serialization.ProtobufSerializer"
+ }
+
+ serialization-bindings {
+ "com.google.protobuf.Message" = proto
+
+ }
+ }
+ remote {
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2550
+ maximum-frame-size = 2097152
+ send-buffer-size = 52428800
+ receive-buffer-size = 52428800
+ }
+ }
- serialization-bindings {
- "com.google.protobuf.Message" = proto
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
- }
+ auto-down-unreachable-after = 10s
}
+ }
+}
+
+odl-cluster-rpc {
+ akka {
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
-}
\ No newline at end of file
+ }
+ remote {
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2551
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
modules = [
{
name = "inventory"
- namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:people"
+ namespace = "urn:opendaylight:inventory"
shard-strategy = "module"
}
]
augment "/config:modules/config:module/config:configuration" {
case distributed-config-datastore-provider {
when "/config:modules/config:module/config:type = 'distributed-config-datastore-provider'";
- container schema-service {
+ container config-schema-service {
uses config:service-ref {
refine type {
mandatory false;
augment "/config:modules/config:module/config:configuration" {
case distributed-operational-datastore-provider {
when "/config:modules/config:module/config:type = 'distributed-operational-datastore-provider'";
- container schema-service {
+ container operational-schema-service {
uses config:service-ref {
refine type {
mandatory false;
import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import akka.actor.Props;
+import akka.event.Logging;
import akka.testkit.JavaTestKit;
import junit.framework.Assert;
import org.junit.Test;
import java.util.Collections;
+import static junit.framework.Assert.assertEquals;
+
public class BasicIntegrationTest extends AbstractActorTest {
@Test
getRef());
- // Wait for Shard to become a Leader
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ // Wait for a specific log message to show up
+ final boolean result =
+ new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+ ) {
+ protected Boolean run() {
+ return true;
+ }
+ }.from(shard.path().toString())
+ .message("Switching from state Candidate to Leader")
+ .occurrences(1).exec();
+
+ assertEquals(true, result);
+
// 1. Create a TransactionChain
shard.tell(new CreateTransactionChain().toSerializable(), getRef());
final ActorSelection transactionChain =
- new ExpectMsg<ActorSelection>("CreateTransactionChainReply") {
+ new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionChainReply") {
protected ActorSelection match(Object in) {
if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)) {
ActorPath transactionChainPath =
System.out.println("Successfully created transaction chain");
// 2. Create a Transaction on the TransactionChain
- transactionChain.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
+ transactionChain.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.WRITE_ONLY.ordinal() ).toSerializable(), getRef());
final ActorSelection transaction =
- new ExpectMsg<ActorSelection>("CreateTransactionReply") {
+ new ExpectMsg<ActorSelection>(duration("1 seconds"), "CreateTransactionReply") {
protected ActorSelection match(Object in) {
if (CreateTransactionReply.SERIALIZABLE_CLASS.equals(in.getClass())) {
CreateTransactionReply reply = CreateTransactionReply.fromSerializable(in);
ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
getRef());
- Boolean writeDone = new ExpectMsg<Boolean>("WriteDataReply") {
+ Boolean writeDone = new ExpectMsg<Boolean>(duration("1 seconds"), "WriteDataReply") {
protected Boolean match(Object in) {
if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
return true;
transaction.tell(new ReadyTransaction().toSerializable(), getRef());
final ActorSelection cohort =
- new ExpectMsg<ActorSelection>("ReadyTransactionReply") {
+ new ExpectMsg<ActorSelection>(duration("1 seconds"), "ReadyTransactionReply") {
protected ActorSelection match(Object in) {
if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
ActorPath cohortPath =
cohort.tell(new PreCommitTransaction().toSerializable(), getRef());
Boolean preCommitDone =
- new ExpectMsg<Boolean>("PreCommitTransactionReply") {
+ new ExpectMsg<Boolean>(duration("1 seconds"), "PreCommitTransactionReply") {
protected Boolean match(Object in) {
if (in.getClass().equals(PreCommitTransactionReply.SERIALIZABLE_CLASS)) {
return true;
Assert.assertEquals(1, listMessages.size());
- Assert.assertTrue(listMessages.get(0).getClass().equals(DataChanged.SERIALIZABLE_CLASS));
+ Assert.assertTrue(listMessages.get(0).getClass().equals(DataChanged.class));
}
}
subject.tell(new CloseDataChangeListenerRegistration().toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(CloseDataChangeListenerRegistrationReply.SERIALIZABLE_CLASS)) {
subject.tell(new EnableNotification(true), getRef());
subject.tell(
- new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()).toSerializable(),
+ new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()),
getRef());
final Boolean out = new ExpectMsg<Boolean>(duration("800 millis"), "dataChanged") {
// do not put code outside this method, will run afterwards
protected Boolean match(Object in) {
- if (in != null && in.getClass().equals(DataChangedReply.SERIALIZABLE_CLASS)) {
+ if (in != null && in.getClass().equals(DataChangedReply.class)) {
return true;
} else {
protected void run() {
subject.tell(
- new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()).toSerializable(),
+ new DataChanged(CompositeModel.createTestContext(),new MockDataChangedEvent()),
getRef());
expectNoMsg();
package org.opendaylight.controller.cluster.datastore;
import akka.actor.ActorSystem;
+import akka.event.Logging;
import akka.testkit.JavaTestKit;
-
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
import junit.framework.Assert;
+import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import java.io.File;
+import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
-public class DistributedDataStoreIntegrationTest{
+public class DistributedDataStoreIntegrationTest {
private static ActorSystem system;
@Before
- public void setUp() {
+ public void setUp() throws IOException {
+ File journal = new File("journal");
+
+ if(journal.exists()) {
+ FileUtils.deleteDirectory(journal);
+ }
+
+
System.setProperty("shard.persistent", "false");
system = ActorSystem.create("test");
}
@Test
public void integrationTest() throws Exception {
- Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+ final Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
ShardStrategyFactory.setConfiguration(configuration);
- DistributedDataStore distributedDataStore =
- new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
- distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
- Thread.sleep(1500);
- DOMStoreReadWriteTransaction transaction =
- distributedDataStore.newReadWriteTransaction();
+ new JavaTestKit(getSystem()) {
+ {
+
+ new Within(duration("10 seconds")) {
+ protected void run() {
+ try {
+ final DistributedDataStore distributedDataStore =
+ new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
+
+ distributedDataStore.onGlobalContextUpdated(TestModel.createTestContext());
+
+ // Wait for a specific log message to show up
+ final boolean result =
+ new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+ ) {
+ protected Boolean run() {
+ return true;
+ }
+ }.from("akka://test/user/shardmanager-config/member-1-shard-test-1-config")
+ .message("Switching from state Candidate to Leader")
+ .occurrences(1).exec();
+
+ assertEquals(true, result);
+
+ DOMStoreReadWriteTransaction transaction =
+ distributedDataStore.newReadWriteTransaction();
- transaction.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
+ transaction
+ .write(TestModel.TEST_PATH, ImmutableNodes
+ .containerNode(TestModel.TEST_QNAME));
- ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
- transaction.read(TestModel.TEST_PATH);
+ ListenableFuture<Optional<NormalizedNode<?, ?>>>
+ future =
+ transaction.read(TestModel.TEST_PATH);
- Optional<NormalizedNode<?, ?>> optional = future.get();
+ Optional<NormalizedNode<?, ?>> optional =
+ future.get();
- Assert.assertTrue(optional.isPresent());
+ Assert.assertTrue("Node not found", optional.isPresent());
- NormalizedNode<?, ?> normalizedNode = optional.get();
+ NormalizedNode<?, ?> normalizedNode =
+ optional.get();
- assertEquals(TestModel.TEST_QNAME, normalizedNode.getNodeType());
+ assertEquals(TestModel.TEST_QNAME,
+ normalizedNode.getNodeType());
- DOMStoreThreePhaseCommitCohort ready = transaction.ready();
+ DOMStoreThreePhaseCommitCohort ready =
+ transaction.ready();
- ListenableFuture<Boolean> canCommit = ready.canCommit();
+ ListenableFuture<Boolean> canCommit =
+ ready.canCommit();
- assertTrue(canCommit.get(5, TimeUnit.SECONDS));
+ assertTrue(canCommit.get(5, TimeUnit.SECONDS));
- ListenableFuture<Void> preCommit = ready.preCommit();
+ ListenableFuture<Void> preCommit =
+ ready.preCommit();
- preCommit.get(5, TimeUnit.SECONDS);
+ preCommit.get(5, TimeUnit.SECONDS);
- ListenableFuture<Void> commit = ready.commit();
+ ListenableFuture<Void> commit = ready.commit();
+
+ commit.get(5, TimeUnit.SECONDS);
+ } catch (ExecutionException | TimeoutException | InterruptedException e){
+ fail(e.getMessage());
+ }
+ }
+ };
+ }
+ };
- commit.get(5, TimeUnit.SECONDS);
}
- @Test
+ //FIXME : Disabling test because it's flaky
+ //@Test
public void integrationTestWithMultiShardConfiguration()
throws ExecutionException, InterruptedException, TimeoutException {
- Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
+ final Configuration configuration = new ConfigurationImpl("module-shards.conf", "modules.conf");
ShardStrategyFactory.setConfiguration(configuration);
- DistributedDataStore distributedDataStore =
- new DistributedDataStore(getSystem(), "config", new MockClusterWrapper(), configuration);
+ new JavaTestKit(getSystem()) {
+ {
+
+ new Within(duration("10 seconds")) {
+ protected void run() {
+ try {
+ final DistributedDataStore distributedDataStore =
+ new DistributedDataStore(getSystem(), "config",
+ new MockClusterWrapper(), configuration);
+
+ distributedDataStore.onGlobalContextUpdated(
+ SchemaContextHelper.full());
+
+ // Wait for a specific log message to show up
+ final boolean result =
+ new JavaTestKit.EventFilter<Boolean>(
+ Logging.Info.class
+ ) {
+ protected Boolean run() {
+ return true;
+ }
+ }.from(
+ "akka://test/user/shardmanager-config/member-1-shard-cars-1-config")
+ .message(
+ "Switching from state Candidate to Leader")
+ .occurrences(1)
+ .exec();
+
+ Thread.sleep(1000);
+
+
+ DOMStoreReadWriteTransaction transaction =
+ distributedDataStore.newReadWriteTransaction();
- distributedDataStore.onGlobalContextUpdated(SchemaContextHelper.full());
+ transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
+ transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
- // This sleep is fragile - test can fail intermittently if all Shards aren't updated with
- // the SchemaContext in time. Is there any way we can make this deterministic?
- Thread.sleep(2000);
+ DOMStoreThreePhaseCommitCohort ready = transaction.ready();
- DOMStoreReadWriteTransaction transaction =
- distributedDataStore.newReadWriteTransaction();
+ ListenableFuture<Boolean> canCommit = ready.canCommit();
- transaction.write(CarsModel.BASE_PATH, CarsModel.emptyContainer());
- transaction.write(PeopleModel.BASE_PATH, PeopleModel.emptyContainer());
+ assertTrue(canCommit.get(5, TimeUnit.SECONDS));
- DOMStoreThreePhaseCommitCohort ready = transaction.ready();
+ ListenableFuture<Void> preCommit = ready.preCommit();
- ListenableFuture<Boolean> canCommit = ready.canCommit();
+ preCommit.get(5, TimeUnit.SECONDS);
- assertTrue(canCommit.get(5, TimeUnit.SECONDS));
+ ListenableFuture<Void> commit = ready.commit();
- ListenableFuture<Void> preCommit = ready.preCommit();
+ commit.get(5, TimeUnit.SECONDS);
- preCommit.get(5, TimeUnit.SECONDS);
+ assertEquals(true, result);
+ } catch(ExecutionException | TimeoutException | InterruptedException e){
+ fail(e.getMessage());
+ }
+ }
+ };
+ }
+ };
- ListenableFuture<Void> commit = ready.commit();
- commit.get(5, TimeUnit.SECONDS);
}
}
@org.junit.Test
public void testRegisterChangeListenerWhenShardIsLocal() throws Exception {
- mockActorContext.setExecuteLocalShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()).toSerializable());
+ mockActorContext.setExecuteLocalShardOperationResponse(new RegisterChangeListenerReply(doNothingActorRef.path()));
ListenerRegistration registration =
distributedDataStore.registerChangeListener(TestModel.TEST_PATH, new AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>() {
subject.tell(new FindPrimary(Shard.DEFAULT_NAME).toSerializable(), getRef());
- expectMsgClass(PrimaryFound.SERIALIZABLE_CLASS);
+ expectMsgClass(duration("1 seconds"), PrimaryFound.SERIALIZABLE_CLASS);
expectNoMsg();
}
subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
- final String out = new ExpectMsg<String>("primary found") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "primary found") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(PrimaryFound.SERIALIZABLE_CLASS)) {
subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
- expectMsgClass(PrimaryFound.SERIALIZABLE_CLASS);
+ expectMsgClass(duration("1 seconds"), PrimaryFound.SERIALIZABLE_CLASS);
MockClusterWrapper.sendMemberRemoved(subject, "member-2", getRef().path().toString());
subject.tell(new FindPrimary("astronauts").toSerializable(), getRef());
- expectMsgClass(PrimaryNotFound.SERIALIZABLE_CLASS);
+ expectMsgClass(duration("1 seconds"), PrimaryNotFound.SERIALIZABLE_CLASS);
expectNoMsg();
}
import akka.actor.ActorRef;
import akka.actor.Props;
+import akka.event.Logging;
import akka.testkit.JavaTestKit;
+import junit.framework.Assert;
import org.junit.Test;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
getSystem().actorOf(props, "testCreateTransactionChain");
- // Wait for Shard to become a Leader
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ // Wait for a specific log message to show up
+ final boolean result =
+ new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+ ) {
+ protected Boolean run() {
+ return true;
+ }
+ }.from(subject.path().toString())
+ .message("Switching from state Candidate to Leader")
+ .occurrences(1).exec();
+
+ Assert.assertEquals(true, result);
new Within(duration("1 seconds")) {
protected void run() {
subject.tell(new CreateTransactionChain().toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(CreateTransactionChainReply.SERIALIZABLE_CLASS)){
getRef());
subject.tell(new RegisterChangeListener(TestModel.TEST_PATH,
- getRef().path(), AsyncDataBroker.DataChangeScope.BASE).toSerializable(),
+ getRef().path(), AsyncDataBroker.DataChangeScope.BASE),
getRef());
final Boolean notificationEnabled = new ExpectMsg<Boolean>("enable notification") {
assertFalse(notificationEnabled);
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
- if (in.getClass().equals(RegisterChangeListenerReply.SERIALIZABLE_CLASS)) {
+ if (in.getClass().equals(RegisterChangeListenerReply.class)) {
RegisterChangeListenerReply reply =
- RegisterChangeListenerReply.fromSerializable(getSystem(),in);
+ (RegisterChangeListenerReply) in;
return reply.getListenerRegistrationPath()
.toString();
} else {
getSystem().actorOf(props, "testCreateTransaction");
- // Wait for Shard to become a Leader
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ // Wait for a specific log message to show up
+ final boolean result =
+ new JavaTestKit.EventFilter<Boolean>(Logging.Info.class
+ ) {
+ protected Boolean run() {
+ return true;
+ }
+ }.from(subject.path().toString())
+ .message("Switching from state Candidate to Leader")
+ .occurrences(1).exec();
+ Assert.assertEquals(true, result);
new Within(duration("1 seconds")) {
protected void run() {
new UpdateSchemaContext(TestModel.createTestContext()),
getRef());
- subject.tell(new CreateTransaction("txn-1").toSerializable(),
+ subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(),
getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in instanceof CreateTransactionReply) {
new Within(duration("1 seconds")) {
protected void run() {
- subject.tell(new CreateTransaction("txn-1").toSerializable(), getRef());
+ subject.tell(new CreateTransaction("txn-1", TransactionProxy.TransactionType.READ_ONLY.ordinal() ).toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(CreateTransactionReply.SERIALIZABLE_CLASS)) {
subject.tell(new CloseTransactionChain().toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(CloseTransactionChainReply.SERIALIZABLE_CLASS)) {
import akka.actor.Props;
import akka.actor.Terminated;
import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Assert;
import org.junit.Test;
import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
new JavaTestKit(getSystem()) {{
final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
- ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+ ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
final ActorRef subject = getSystem().actorOf(props, "testReadData");
new Within(duration("1 seconds")) {
new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
new JavaTestKit(getSystem()) {{
final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
- ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
+ ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
new Within(duration("1 seconds")) {
new ReadData(TestModel.TEST_PATH).toSerializable(),
getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
getRef());
final CompositeModification compositeModification =
- new ExpectMsg<CompositeModification>("match hint") {
+ new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected CompositeModification match(Object in) {
if (in instanceof ShardTransaction.GetCompositeModificationReply) {
new JavaTestKit(getSystem()) {{
final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
- ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+ ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
getSystem().actorOf(props, "testWriteData");
ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
new JavaTestKit(getSystem()) {{
final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
- ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+ ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
getSystem().actorOf(props, "testDeleteData");
subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
new JavaTestKit(getSystem()) {{
final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
final Props props =
- ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
+ ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
final ActorRef subject =
getSystem().actorOf(props, "testReadyTransaction");
subject.tell(new ReadyTransaction().toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
subject.tell(new CloseTransaction().toSerializable(), getRef());
- final String out = new ExpectMsg<String>("match hint") {
+ final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
assertEquals("match", out);
- final String termination = new ExpectMsg<String>("match hint") {
+ final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
// do not put code outside this method, will run afterwards
protected String match(Object in) {
if (in instanceof Terminated) {
}};
}
+
+
+ @Test
+ public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
+ try {
+
+ final ActorRef shard = getSystem().actorOf(Shard.props("config", Collections.EMPTY_MAP));
+ final Props props =
+ ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
+ final TestActorRef subject = TestActorRef.apply(props,getSystem());
+
+ subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
+ Assert.assertFalse(true);
+
+
+ } catch (Exception cs) {
+ assertEquals(cs.getClass().getSimpleName(), Exception.class.getSimpleName());
+ assertTrue(cs.getMessage().startsWith("ShardTransaction:handleRecieve received an unknown message"));
+ }
+ }
}
package org.opendaylight.controller.cluster.datastore.shardstrategy;
-import junit.framework.Assert;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.opendaylight.controller.cluster.datastore.Configuration;
import org.opendaylight.controller.cluster.datastore.ConfigurationImpl;
import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+import static junit.framework.Assert.assertEquals;
public class ModuleShardStrategyTest {
@Rule
String shard = moduleShardStrategy.findShard(CarsModel.BASE_PATH);
- Assert.assertEquals("cars-1", shard);
+ assertEquals("cars-1", shard);
+ }
+
+ @Test
+ public void testFindShardWhenModuleConfigurationPresentInModulesButMissingInModuleShards() {
+
+ final QName BASE_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test:missing", "2014-03-13",
+ "missing");
+
+ final YangInstanceIdentifier BASE_PATH = YangInstanceIdentifier.of(BASE_QNAME);
+
+ ModuleShardStrategy moduleShardStrategy =
+ new ModuleShardStrategy("missing", configuration);
+
+ String shard = moduleShardStrategy.findShard(BASE_PATH);
+
+ assertEquals(DefaultShardStrategy.DEFAULT_SHARD, shard);
+
}
}
akka {
+ loggers = [akka.testkit.TestEventListener]
actor {
serializers {
java = "akka.serialization.JavaSerializer"
shard-strategy = "module"
}
+ {
+ name = "missing"
+ namespace = "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:missing"
+ shard-strategy = "module"
+ }
+
]
--- /dev/null
+/*
+ * Copyright (c) 2014 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.core.api;
+
+/**
+ * Exception reported when no RPC implementation is found in the system.
+ */
+public class RpcImplementationUnavailableException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public RpcImplementationUnavailableException(final String message) {
+ super(message);
+ }
+
+ public RpcImplementationUnavailableException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
import java.util.concurrent.Executors;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListeningExecutorService;
.<LogicalDatastoreType, DOMStore> builder().put(LogicalDatastoreType.OPERATIONAL, operStore)
.put(LogicalDatastoreType.CONFIGURATION, configStore).build();
- DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores, MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
+ DOMDataBrokerImpl newDataBroker = new DOMDataBrokerImpl(datastores,
+ new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+ TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION));
return newDataBroker;
}
import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.ObjectRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
public class BackwardsCompatibleMountPointManager implements MountProvisionService, MountProvisionListener {
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.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionListener;
import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@Deprecated
package org.opendaylight.controller.sal.dom.broker.impl;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
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.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable<RpcRoutingContext> {
}
if (potential == null) {
return router.invokeRpc(rpc, (YangInstanceIdentifier) route, input);
+ } else {
+ return potential.invokeRpc(rpc, input);
}
- checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route);
- return potential.invokeRpc(rpc, input);
}
public void addPath(final QName context, final YangInstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) {
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
+import org.opendaylight.controller.sal.core.api.RpcImplementationUnavailableException;
import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
import org.opendaylight.controller.sal.core.api.RpcRoutingContext;
import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
-
+/**
+ * RPC broker responsible for routing requests to remote systems.
+ */
public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, RoutedRpcDefaultImplementation {
private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareRpcBroker.class);
@Override
public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final YangInstanceIdentifier route, final CompositeNode input) {
- checkState(defaultDelegate != null, "No implementation is available for rpc:%s path:%s", rpc, route);
- return defaultDelegate.invokeRpc(rpc, route, input);
+ if (defaultDelegate == null) {
+ return Futures.immediateFailedCheckedFuture(new RpcImplementationUnavailableException("No RPC implementation found"));
+ }
+
+ LOG.debug("Forwarding RPC {} path {} to delegate {}", rpc, route);
+ return defaultDelegate.invokeRpc(rpc, route, input);
}
void remove(final GlobalRpcRegistration registration) {
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
private SchemaContext schemaContext;
private DOMDataBrokerImpl domBroker;
+ private ListeningExecutorService executor;
@Before
public void setupStore() {
.put(OPERATIONAL, operStore) //
.build();
- ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
+ executor = new DeadlockDetectingListeningExecutorService(Executors.newSingleThreadExecutor(),
+ TransactionCommitDeadlockException.DEADLOCK_EXECUTOR_FUNCTION);
domBroker = new DOMDataBrokerImpl(stores, executor);
}
- @Test
+ @After
+ public void tearDown() {
+ if( executor != null ) {
+ executor.shutdownNow();
+ }
+ }
+
+ @Test(timeout=10000)
public void testTransactionIsolation() throws InterruptedException, ExecutionException {
assertNotNull(domBroker);
assertFalse(readTxContainer.get().isPresent());
}
- @Test
+ @Test(timeout=10000)
public void testTransactionCommit() throws InterruptedException, ExecutionException {
DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
assertTrue(afterCommitRead.isPresent());
}
+ /**
+ * Tests a simple DataChangeListener notification after a write.
+ */
+ @Test
+ public void testDataChangeListener() throws Throwable {
+
+ final NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode( TestModel.TEST_QNAME );
+
+ TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener();
+
+ domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+ dcListener, DataChangeScope.BASE );
+
+ final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ assertNotNull( writeTx );
+
+ writeTx.put( OPERATIONAL, TestModel.TEST_PATH, testNode );
+
+ AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+ dcListener.waitForChange();
+
+ if( caughtEx.get() != null ) {
+ throw caughtEx.get();
+ }
+
+ NormalizedNode<?, ?> actualNode = dcListener.change.getCreatedData().get( TestModel.TEST_PATH );
+ assertEquals( "Created node", testNode, actualNode );
+ }
+
+ /**
+ * Tests a DataChangeListener that does an async submit of a write Tx in its onDataChanged method.
+ * This should succeed without deadlock.
+ */
+ @Test
+ public void testDataChangeListenerDoingAsyncWriteTxSubmit() throws Throwable {
+
+ final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+ final CountDownLatch commitCompletedLatch = new CountDownLatch( 1 );
+
+ TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+ @Override
+ public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+
+ DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+ ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+ Futures.addCallback( writeTx.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onSuccess( Void result ) {
+ commitCompletedLatch.countDown();
+ }
+
+ @Override
+ public void onFailure( Throwable t ) {
+ caughtCommitEx.set( t );
+ commitCompletedLatch.countDown();
+ }
+ } );
+
+ super.onDataChanged( change );
+ }
+ };
+
+ domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+ dcListener, DataChangeScope.BASE );
+
+ final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ assertNotNull( writeTx );
+
+ writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+ AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+
+ dcListener.waitForChange();
+
+ if( caughtEx.get() != null ) {
+ throw caughtEx.get();
+ }
+
+ assertTrue( "Commit Future was not invoked", commitCompletedLatch.await( 5, TimeUnit.SECONDS ) );
+
+ if( caughtCommitEx.get() != null ) {
+ throw caughtCommitEx.get();
+ }
+ }
+
+ /**
+ * Tests a DataChangeListener that does a blocking submit of a write Tx in its onDataChanged method.
+ * This should throw an exception and not deadlock.
+ */
+ @Test(expected=TransactionCommitDeadlockException.class)
+ public void testDataChangeListenerDoingBlockingWriteTxSubmit() throws Throwable {
+
+ final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
+
+ TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
+ @Override
+ public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+ DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ writeTx.put( OPERATIONAL, TestModel.TEST2_PATH,
+ ImmutableNodes.containerNode( TestModel.TEST2_QNAME ) );
+ try {
+ writeTx.submit().get();
+ } catch( ExecutionException e ) {
+ caughtCommitEx.set( e.getCause() );
+ } catch( Exception e ) {
+ caughtCommitEx.set( e );
+ }
+ finally {
+ super.onDataChanged( change );
+ }
+ }
+ };
+
+ domBroker.registerDataChangeListener( OPERATIONAL, TestModel.TEST_PATH,
+ dcListener, DataChangeScope.BASE );
+
+ final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
+ assertNotNull( writeTx );
+
+ writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode( TestModel.TEST_QNAME ) );
+
+ AtomicReference<Throwable> caughtEx = submitTxAsync( writeTx );
+ dcListener.waitForChange();
+ if( caughtEx.get() != null ) {
+ throw caughtEx.get();
+ }
+
+ if( caughtCommitEx.get() != null ) {
+ throw caughtCommitEx.get();
+ }
+ }
+
+ AtomicReference<Throwable> submitTxAsync( final DOMDataWriteTransaction writeTx ) {
+ final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
+ new Thread() {
+ @Override
+ public void run() {
+
+ try {
+ writeTx.submit();
+ } catch( Throwable e ) {
+ caughtEx.set( e );
+ }
+ }
+
+ }.start();
+
+ return caughtEx;
+ }
+
+ static class TestDOMDataChangeListener implements DOMDataChangeListener {
+
+ volatile AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change;
+ private final CountDownLatch latch = new CountDownLatch( 1 );
+
+ @Override
+ public void onDataChanged( AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change ) {
+ this.change = change;
+ latch.countDown();
+ }
+
+ void waitForChange() throws InterruptedException {
+ assertTrue( "onDataChanged was not called", latch.await( 5, TimeUnit.SECONDS ) );
+ }
+ }
}
public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
"test");
+ public static final QName TEST2_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+ "test2");
public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+ public static final YangInstanceIdentifier TEST2_PATH = YangInstanceIdentifier.of(TEST2_QNAME);
public static final YangInstanceIdentifier OUTER_LIST_PATH = YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
public static final QName TWO_QNAME = QName.create(TEST_QNAME,"two");
public static final QName THREE_QNAME = QName.create(TEST_QNAME,"three");
}
}
}
+
+ container test2 {
+ }
}
\ No newline at end of file
import static org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.builder;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Multimap;
-
/**
* Resolve Data Change Events based on modifications and listeners
*
final Collection<Node> listeners, final NormalizedNode<?, ?> beforeData,
final NormalizedNode<?, ?> afterData) {
+ // FIXME: BUG-1493: check the listeners to prune unneeded changes:
+ // for subtrees, we have to do all
+ // for one, we need to expand children
+ // for base, we just report replacement
+
if (beforeData instanceof NormalizedNodeContainer<?, ?, ?>) {
// Node is container (contains child) and we have interested
// listeners registered for it, that means we need to do
final Collection<Node> listeners,
final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> beforeCont,
final NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont) {
- final Set<PathArgument> alreadyProcessed = new HashSet<>();
final List<DOMImmutableDataChangeEvent> childChanges = new LinkedList<>();
- DataChangeScope potentialScope = DataChangeScope.BASE;
// We look at all children from before and compare it with after state.
for (NormalizedNode<PathArgument, ?> beforeChild : beforeCont.getValue()) {
- PathArgument childId = beforeChild.getIdentifier();
- alreadyProcessed.add(childId);
+ final PathArgument childId = beforeChild.getIdentifier();
+
YangInstanceIdentifier childPath = path.node(childId);
Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
Optional<NormalizedNode<PathArgument, ?>> afterChild = afterCont.getChild(childId);
if (childChange != NO_CHANGE) {
childChanges.add(childChange);
}
-
}
for (NormalizedNode<PathArgument, ?> afterChild : afterCont.getValue()) {
- PathArgument childId = afterChild.getIdentifier();
- if (!alreadyProcessed.contains(childId)) {
- // We did not processed that child already
- // and it was not present in previous loop, that means it is
- // created.
+ final PathArgument childId = afterChild.getIdentifier();
+
+ /*
+ * We have already iterated of the before-children, so have already
+ * emitted modify/delete events. This means the child has been
+ * created.
+ */
+ if (!beforeCont.getChild(childId).isPresent()) {
Collection<ListenerTree.Node> childListeners = getListenerChildrenWildcarded(listeners, childId);
YangInstanceIdentifier childPath = path.node(childId);
childChanges.add(resolveSameEventRecursivelly(childPath , childListeners, afterChild,
return NO_CHANGE;
}
- Builder eventBuilder = builder(potentialScope) //
+ Builder eventBuilder = builder(DataChangeScope.BASE) //
.setBefore(beforeCont) //
.setAfter(afterCont)
.addUpdated(path, beforeCont, afterCont);
/**
* A walking context, pretty much equivalent to an iterator, but it
- * exposes the undelying tree structure.
+ * exposes the underlying tree structure.
+ */
+ /*
+ * FIXME: BUG-1511: split this class out as ListenerWalker.
*/
public static final class Walker implements AutoCloseable {
private final Lock lock;
* only as long as the {@link org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker} instance through which it is reached remains
* unclosed.
*/
+ /*
+ * FIXME: BUG-1511: split this class out as ListenerNode.
+ */
public static final class Node implements StoreTreeNode<Node>, Identifiable<PathArgument> {
private final Collection<DataChangeListenerRegistration<?>> listeners = new ArrayList<>();
private final Map<PathArgument, Node> children = new HashMap<>();
*/
package org.opendaylight.controller.sal.connect.netconf;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
+
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
import org.opendaylight.controller.sal.connect.api.MessageTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
/**
* This is a mediator between NetconfDeviceCommunicator and NetconfDeviceSalFacade
*/
private final MessageTransformer<NetconfMessage> messageTransformer;
private final SchemaContextProviderFactory schemaContextProviderFactory;
private final SchemaSourceProviderFactory<InputStream> sourceProviderFactory;
+ private final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver;
private final NotificationHandler notificationHandler;
public static NetconfDevice createNetconfDevice(final RemoteDeviceId id,
final AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider,
final ExecutorService executor, final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade) {
+ return createNetconfDevice(id, schemaSourceProvider, executor, salFacade, new NetconfStateSchemas.NetconfStateSchemasResolverImpl());
+ }
+
+ @VisibleForTesting
+ protected static NetconfDevice createNetconfDevice(final RemoteDeviceId id,
+ final AbstractCachingSchemaSourceProvider<String, InputStream> schemaSourceProvider,
+ final ExecutorService executor, final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade,
+ final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver) {
return new NetconfDevice(id, salFacade, executor, new NetconfMessageTransformer(),
new NetconfDeviceSchemaProviderFactory(id), new SchemaSourceProviderFactory<InputStream>() {
return schemaSourceProvider.createInstanceFor(new NetconfRemoteSchemaSourceProvider(id,
deviceRpc));
}
- });
+ }, stateSchemasResolver);
}
@VisibleForTesting
protected NetconfDevice(final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionCapabilities> salFacade,
- final ExecutorService processingExecutor, final MessageTransformer<NetconfMessage> messageTransformer,
- final SchemaContextProviderFactory schemaContextProviderFactory,
- final SchemaSourceProviderFactory<InputStream> sourceProviderFactory) {
+ final ExecutorService processingExecutor, final MessageTransformer<NetconfMessage> messageTransformer,
+ final SchemaContextProviderFactory schemaContextProviderFactory,
+ final SchemaSourceProviderFactory<InputStream> sourceProviderFactory,
+ final NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver) {
this.id = id;
this.messageTransformer = messageTransformer;
this.salFacade = salFacade;
this.sourceProviderFactory = sourceProviderFactory;
+ this.stateSchemasResolver = stateSchemasResolver;
this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor);
this.schemaContextProviderFactory = schemaContextProviderFactory;
this.notificationHandler = new NotificationHandler(salFacade, messageTransformer, id);
@Override
public void run() {
final NetconfDeviceRpc deviceRpc = setUpDeviceRpc(remoteSessionCapabilities, listener);
+
+ final NetconfStateSchemas availableSchemas = stateSchemasResolver.resolve(deviceRpc, remoteSessionCapabilities, id);
+ logger.warn("{}: Schemas exposed by ietf-netconf-monitoring: {}", id, availableSchemas.getAvailableYangSchemasQNames());
+ // TODO use this for shared schema context
+
final SchemaSourceProvider<InputStream> delegate = sourceProviderFactory.createSourceProvider(deviceRpc);
final SchemaContextProvider schemaContextProvider = setUpSchemaContext(delegate, remoteSessionCapabilities);
updateMessageTransformer(schemaContextProvider);
Preconditions.checkNotNull(parsedNotification);
salFacade.onNotification(parsedNotification);
}
-
}
+
}
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import com.google.common.annotations.VisibleForTesting;
+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.Lists;
+import com.google.common.collect.Sets;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
+import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceRpc;
+import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+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.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Holds QNames for all yang modules reported by ietf-netconf-monitoring/state/schemas
+ */
+public final class NetconfStateSchemas {
+
+ private static final Logger logger = LoggerFactory.getLogger(NetconfStateSchemas.class);
+
+ /**
+ * Factory for NetconfStateSchemas
+ */
+ public interface NetconfStateSchemasResolver {
+ NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id);
+ }
+
+ /**
+ * Default implementation resolving schemas QNames from netconf-state
+ */
+ public static final class NetconfStateSchemasResolverImpl implements NetconfStateSchemasResolver {
+
+ @Override
+ public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id) {
+ return NetconfStateSchemas.create(deviceRpc, remoteSessionCapabilities, id);
+ }
+ }
+
+ public static final NetconfStateSchemas EMPTY = new NetconfStateSchemas(Collections.<RemoteYangSchema>emptySet());
+
+ private static final YangInstanceIdentifier STATE_SCHEMAS_IDENTIFIER =
+ YangInstanceIdentifier.builder().node(NetconfState.QNAME).node(Schemas.QNAME).build();
+ private static final YangInstanceIdentifier DATA_STATE_SCHEMAS_IDENTIFIER =
+ YangInstanceIdentifier.builder().node(NetconfMessageTransformUtil.NETCONF_DATA_QNAME)
+ .node(NetconfState.QNAME).node(Schemas.QNAME).build();
+
+ private static final CompositeNode GET_SCHEMAS_RPC;
+ static {
+ final Node<?> filter = NetconfMessageTransformUtil.toFilterStructure(STATE_SCHEMAS_IDENTIFIER);
+ GET_SCHEMAS_RPC
+ = NodeFactory.createImmutableCompositeNode(NetconfMessageTransformUtil.NETCONF_GET_QNAME, null, Lists.<Node<?>>newArrayList(filter));
+ }
+
+ private final Set<RemoteYangSchema> availableYangSchemas;
+
+ public NetconfStateSchemas(final Set<RemoteYangSchema> availableYangSchemas) {
+ this.availableYangSchemas = availableYangSchemas;
+ }
+
+ public Set<RemoteYangSchema> getAvailableYangSchemas() {
+ return availableYangSchemas;
+ }
+
+ public Set<QName> getAvailableYangSchemasQNames() {
+ return Sets.newHashSet(Collections2.transform(getAvailableYangSchemas(), new Function<RemoteYangSchema, QName>() {
+ @Override
+ public QName apply(final RemoteYangSchema input) {
+ return input.getQName();
+ }
+ }));
+ }
+
+ /**
+ * Issue get request to remote device and parse response to find all schemas under netconf-state/schemas
+ */
+ private static NetconfStateSchemas create(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id) {
+ if(remoteSessionCapabilities.isMonitoringSupported() == false) {
+ logger.warn("{}: Netconf monitoring not supported on device, cannot detect available schemas");
+ return EMPTY;
+ }
+
+ final RpcResult<CompositeNode> schemasNodeResult;
+ try {
+ schemasNodeResult = deviceRpc.invokeRpc(NetconfMessageTransformUtil.NETCONF_GET_QNAME, GET_SCHEMAS_RPC).get();
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(id + ": Interrupted while waiting for response to " + STATE_SCHEMAS_IDENTIFIER, e);
+ } catch (final ExecutionException e) {
+ logger.warn("{}: Unable to detect available schemas, get to {} failed", id, STATE_SCHEMAS_IDENTIFIER, e);
+ return EMPTY;
+ }
+
+ if(schemasNodeResult.isSuccessful() == false) {
+ logger.warn("{}: Unable to detect available schemas, get to {} failed, {}", id, STATE_SCHEMAS_IDENTIFIER, schemasNodeResult.getErrors());
+ return EMPTY;
+ }
+
+ final CompositeNode schemasNode =
+ (CompositeNode) NetconfMessageTransformUtil.findNode(schemasNodeResult.getResult(), DATA_STATE_SCHEMAS_IDENTIFIER);
+ return create(schemasNode);
+ }
+
+ /**
+ * Parse response of get(netconf-state/schemas) to find all schemas under netconf-state/schemas
+ */
+ @VisibleForTesting
+ protected static NetconfStateSchemas create(final CompositeNode schemasNode) {
+ final Set<RemoteYangSchema> availableYangSchemas = Sets.newHashSet();
+
+ for (final CompositeNode schemaNode : schemasNode.getCompositesByName(Schema.QNAME.withoutRevision())) {
+ availableYangSchemas.add(RemoteYangSchema.createFromCompositeNode(schemaNode));
+ }
+
+ return new NetconfStateSchemas(availableYangSchemas);
+ }
+
+ public final static class RemoteYangSchema {
+ private final QName qname;
+
+ private RemoteYangSchema(final QName qname) {
+ this.qname = qname;
+ }
+
+ public QName getQName() {
+ return qname;
+ }
+
+ static RemoteYangSchema createFromCompositeNode(final CompositeNode schemaNode) {
+ Preconditions.checkArgument(schemaNode.getKey().equals(Schema.QNAME.withoutRevision()), "Wrong QName %s", schemaNode.getKey());
+
+ QName childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_FORMAT.withoutRevision();
+
+ final String formatAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+ Preconditions.checkArgument(formatAsString.equals(Yang.QNAME.getLocalName()),
+ "Expecting format to be only %s, not %s", Yang.QNAME.getLocalName(), formatAsString);
+
+ childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_LOCATION.withoutRevision();
+ final Set<String> locationsAsString = getAllChildNodeValues(schemaNode, childNode);
+ Preconditions.checkArgument(locationsAsString.contains(Schema.Location.Enumeration.NETCONF.toString()),
+ "Expecting location to be %s, not %s", Schema.Location.Enumeration.NETCONF.toString(), locationsAsString);
+
+ childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_NAMESPACE.withoutRevision();
+ final String namespaceAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+
+ childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_VERSION.withoutRevision();
+ // Revision does not have to be filled
+ final Optional<String> revisionAsString = getSingleChildNodeValue(schemaNode, childNode);
+
+ childNode = NetconfMessageTransformUtil.IETF_NETCONF_MONITORING_SCHEMA_IDENTIFIER.withoutRevision();
+ final String moduleNameAsString = getSingleChildNodeValue(schemaNode, childNode).get();
+
+ final QName moduleQName = revisionAsString.isPresent()
+ ? QName.create(namespaceAsString, revisionAsString.get(), moduleNameAsString)
+ : QName.create(URI.create(namespaceAsString), null, moduleNameAsString).withoutRevision();
+
+ return new RemoteYangSchema(moduleQName);
+ }
+
+ private static Set<String> getAllChildNodeValues(final CompositeNode schemaNode, final QName childNodeQName) {
+ final Set<String> extractedValues = Sets.newHashSet();
+ for (final SimpleNode<?> childNode : schemaNode.getSimpleNodesByName(childNodeQName)) {
+ extractedValues.add(getValueOfSimpleNode(childNodeQName, childNode).get());
+ }
+ return extractedValues;
+ }
+
+ private static Optional<String> getSingleChildNodeValue(final CompositeNode schemaNode, final QName childNode) {
+ final SimpleNode<?> node = schemaNode.getFirstSimpleByName(childNode);
+ return getValueOfSimpleNode(childNode, node);
+ }
+
+ private static Optional<String> getValueOfSimpleNode(final QName childNode, final SimpleNode<?> node) {
+ Preconditions.checkNotNull(node, "Child node %s not present", childNode);
+ final Object value = node.getValue();
+ return value == null ? Optional.<String>absent() : Optional.of(value.toString().trim());
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final RemoteYangSchema that = (RemoteYangSchema) o;
+
+ if (!qname.equals(that.qname)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return qname.hashCode();
+ }
+ }
+}
try {
NetconfMessageTransformUtil.checkSuccessReply(message);
}
- catch( NetconfDocumentedException e ) {
+ catch(final NetconfDocumentedException e) {
logger.warn( "{}: Error reply from remote device, request: {}, response: {}", id,
msgToS( request.request ), msgToS( message ), e );
import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
import org.opendaylight.yangtools.yang.common.RpcResult;
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.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
checkReadSuccess(result, path);
final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
- final CompositeNode node = (CompositeNode) findNode(data, path);
+ final CompositeNode node = (CompositeNode) NetconfMessageTransformUtil.findNode(data, path);
return data == null ?
Optional.<NormalizedNode<?, ?>>absent() :
checkReadSuccess(result, path);
final CompositeNode data = result.getResult().getFirstCompositeByName(NETCONF_DATA_QNAME);
- final CompositeNode node = (CompositeNode) findNode(data, path);
+ final CompositeNode node = (CompositeNode) NetconfMessageTransformUtil.findNode(data, path);
return data == null ?
Optional.<NormalizedNode<?, ?>>absent() :
return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER);
}
- private static Node<?> findNode(final CompositeNode node, final YangInstanceIdentifier identifier) {
-
- Node<?> current = node;
- for (final YangInstanceIdentifier.PathArgument arg : identifier.getPathArguments()) {
- if (current instanceof SimpleNode<?>) {
- return null;
- } else if (current instanceof CompositeNode) {
- final CompositeNode currentComposite = (CompositeNode) current;
-
- current = currentComposite.getFirstCompositeByName(arg.getNodeType());
- if (current == null) {
- current = currentComposite.getFirstCompositeByName(arg.getNodeType().withoutRevision());
- }
- if (current == null) {
- current = currentComposite.getFirstSimpleByName(arg.getNodeType());
- }
- if (current == null) {
- current = currentComposite.getFirstSimpleByName(arg.getNodeType().withoutRevision());
- }
- if (current == null) {
- return null;
- }
- }
- }
- return current;
- }
-
@Override
public void close() {
// NOOP
return toRpcResult(message, rpc, schemaContext.get());
} else {
final CompositeNode node = (CompositeNode) XmlDocumentUtils.toDomNode(message.getDocument());
- return RpcResultBuilder.success( node ).build();
+ return RpcResultBuilder.success(node).build();
}
}
import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.util.messages.NetconfMessageUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
private NetconfMessageTransformUtil() {}
- public static final QName IETF_NETCONF_MONITORING = QName.create("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring", "2010-10-04", "ietf-netconf-monitoring");
+ public static final QName IETF_NETCONF_MONITORING = QName.create(NetconfState.QNAME, "ietf-netconf-monitoring");
+ public static final QName IETF_NETCONF_MONITORING_SCHEMA_FORMAT = QName.create(IETF_NETCONF_MONITORING, "format");
+ public static final QName IETF_NETCONF_MONITORING_SCHEMA_LOCATION = QName.create(IETF_NETCONF_MONITORING, "location");
+ public static final QName IETF_NETCONF_MONITORING_SCHEMA_IDENTIFIER = QName.create(IETF_NETCONF_MONITORING, "identifier");
+ public static final QName IETF_NETCONF_MONITORING_SCHEMA_VERSION = QName.create(IETF_NETCONF_MONITORING, "version");
+ public static final QName IETF_NETCONF_MONITORING_SCHEMA_NAMESPACE = QName.create(IETF_NETCONF_MONITORING, "namespace");
+
public static URI NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0");
public static QName NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf");
public static QName NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data");
return it.toInstance();
}
}
+
+ public static Node<?> findNode(final CompositeNode node, final YangInstanceIdentifier identifier) {
+
+ Node<?> current = node;
+ for (final YangInstanceIdentifier.PathArgument arg : identifier.getPathArguments()) {
+ if (current instanceof SimpleNode<?>) {
+ return null;
+ } else if (current instanceof CompositeNode) {
+ final CompositeNode currentComposite = (CompositeNode) current;
+
+ current = currentComposite.getFirstCompositeByName(arg.getNodeType());
+ if (current == null) {
+ current = currentComposite.getFirstCompositeByName(arg.getNodeType().withoutRevision());
+ }
+ if (current == null) {
+ current = currentComposite.getFirstSimpleByName(arg.getNodeType());
+ }
+ if (current == null) {
+ current = currentComposite.getFirstSimpleByName(arg.getNodeType().withoutRevision());
+ }
+ if (current == null) {
+ return null;
+ }
+ }
+ }
+ return current;
+ }
}
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-
import org.junit.Test;
import org.mockito.Mockito;
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.sal.connect.api.SchemaContextProviderFactory;
import org.opendaylight.controller.sal.connect.api.SchemaSourceProviderFactory;
import org.opendaylight.controller.sal.connect.netconf.listener.NetconfSessionCapabilities;
+import org.opendaylight.controller.sal.connect.netconf.sal.NetconfDeviceRpc;
import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
import org.opendaylight.controller.sal.core.api.RpcImplementation;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Futures;
-
public class NetconfDeviceTest {
private static final NetconfMessage netconfMessage;
public static final String TEST_NAMESPACE = "test:namespace";
public static final String TEST_MODULE = "test-module";
public static final String TEST_REVISION = "2013-07-22";
+ private NetconfStateSchemas.NetconfStateSchemasResolver stateSchemasResolver = new NetconfStateSchemas.NetconfStateSchemasResolver() {
+
+ @Override
+ public NetconfStateSchemas resolve(final NetconfDeviceRpc deviceRpc, final NetconfSessionCapabilities remoteSessionCapabilities, final RemoteDeviceId id) {
+ return NetconfStateSchemas.EMPTY;
+ }
+ };
@Test
public void testNetconfDeviceWithoutMonitoring() throws Exception {
final RemoteDeviceHandler<NetconfSessionCapabilities> facade = getFacade();
final RemoteDeviceCommunicator<NetconfMessage> listener = getListener();
- final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), getMessageTransformer(), getSchemaContextProviderFactory(), getSourceProviderFactory());
+ final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), getMessageTransformer(), getSchemaContextProviderFactory(), getSourceProviderFactory(), stateSchemasResolver);
device.onRemoteSessionUp(getSessionCaps(false, Collections.<String>emptyList()), listener);
Mockito.verify(facade, Mockito.timeout(5000)).onDeviceDisconnected();
final RemoteDeviceCommunicator<NetconfMessage> listener = getListener();
final MessageTransformer<NetconfMessage> messageTransformer = getMessageTransformer();
- final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, getSchemaContextProviderFactory(), getSourceProviderFactory());
+ final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, getSchemaContextProviderFactory(), getSourceProviderFactory(), stateSchemasResolver);
device.onNotification(netconfMessage);
device.onNotification(netconfMessage);
final SchemaSourceProviderFactory<InputStream> sourceProviderFactory = getSourceProviderFactory();
final MessageTransformer<NetconfMessage> messageTransformer = getMessageTransformer();
- final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, schemaContextProviderFactory, sourceProviderFactory);
+ final NetconfDevice device = new NetconfDevice(getId(), facade, getExecutor(), messageTransformer, schemaContextProviderFactory, sourceProviderFactory, stateSchemasResolver);
final NetconfSessionCapabilities sessionCaps = getSessionCaps(true,
Lists.newArrayList(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION));
device.onRemoteSessionUp(sessionCaps, listener);
--- /dev/null
+package org.opendaylight.controller.sal.connect.netconf;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItem;
+
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.w3c.dom.Document;
+
+public class NetconfStateSchemasTest {
+
+ @Test
+ public void testCreate() throws Exception {
+ final Document schemasXml = XmlUtil.readXmlToDocument(getClass().getResourceAsStream("/netconf-state.schemas.payload.xml"));
+ final CompositeNode compositeNodeSchemas = (CompositeNode) XmlDocumentUtils.toDomNode(schemasXml);
+ final NetconfStateSchemas schemas = NetconfStateSchemas.create(compositeNodeSchemas);
+
+ final Set<QName> availableYangSchemasQNames = schemas.getAvailableYangSchemasQNames();
+ assertEquals(73, availableYangSchemasQNames.size());
+
+ assertThat(availableYangSchemasQNames,
+ hasItem(QName.create("urn:TBD:params:xml:ns:yang:network-topology", "2013-07-12", "network-topology")));
+ }
+}
--- /dev/null
+<ncm:schemas xmlns:ncm="urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring">
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>threadpool</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-04-09</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:logback:config</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>config-logging</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-07-16</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:model:statistics:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-statistics-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-09-25</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:config-dom-store</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-config-dom-datastore</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-06-17</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:table:statistics</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-flow-table-statistics</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-15</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:meter:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-meter</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-09-18</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>toaster-provider-impl</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-01-31</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:table:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-table-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-26</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:table:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-table</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-26</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:shutdown</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>shutdown</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-18</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:port:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-port</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-07</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>netty-event-executor</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-12</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-remote</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-01-14</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:model:topology:view</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-topology-view</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-30</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty:threadgroup</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>threadgroup</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-07</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:TBD:params:xml:ns:yang:network-topology</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>network-topology</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-07-12</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:fixed</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>threadpool-impl-fixed</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-01</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-sal-binding-broker-impl</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-28</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-restconf</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>ietf-restconf</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:node:error:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>node-error</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-04-10</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:errors</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>flow-errors</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-16</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-flow</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-08-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:rpc-context</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>rpc-context</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-06-17</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:operational-dom-store
+ </ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-operational-dom-datastore</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-06-17</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:types:queue</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-queue-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-09-25</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>ietf-netconf-monitoring</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2010-10-04</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:netconf-node-inventory</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>netconf-node-inventory</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-01-08</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>ietf-yang-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-07-15</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:meter:statistics</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-meter-statistics</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-11</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:inventory</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>flow-node-inventory</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-08-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:connector:netconf</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>odl-sal-netconf-connector-cfg</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-28</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>threadpool-impl-scheduled</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-01</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:TBD:params:xml:ns:yang:network-topology</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>network-topology</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-21</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>http://netconfcentral.org/ns/toaster</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>toaster</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2009-11-20</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:netconf</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>odl-netconf-cfg</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-04-08</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:meter:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-meter-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-09-18</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-sal-dom-broker-impl</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-28</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:topology:discovery</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>flow-topology-discovery</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-08-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:yang:extension:yang-ext</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>yang-ext</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-07-09</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>threadpool-impl</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-04-05</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:types:port</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-port-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-09-25</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-md-sal-binding</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-28</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:packet:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>packet-processing</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-07-09</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>threadpool-impl-flexible</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-01</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:queue:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-queue</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-07</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>ietf-inet-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2010-09-24</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:rest:connector</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-rest-connector</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-07-24</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:transaction</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>flow-capable-transaction</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-03</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:statistics</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-flow-statistics</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-08-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:protocol:framework</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>protocol-framework</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-03-13</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:model:match:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-match-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-26</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>ietf-yang-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2010-09-24</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:group:service</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>sal-group</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-09-18</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:inmemory-datastore-provider</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-inmemory-datastore-provider</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-06-17</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty:timer</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>netty-timer</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:group:statistics</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-group-statistics</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-11</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>config</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-04-05</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>odl-netconfig-client-cfg</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-04-08</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:l2:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-l2-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-08-27</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:action:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-action-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-12</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-md-sal-dom</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-28</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-md-sal-common</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-28</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:group:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-group-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-18</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>ietf-netconf-monitoring-extension</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-10</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:inventory</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-inventory</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-08-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:netty</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>netty</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-11-19</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:model:topology:general</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-topology</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-30</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:port:statistics</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-port-statistics</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version></ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:queue:statistics</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-queue-statistics</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-16</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>kitchen-service-impl</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2014-01-31</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:flow:types</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-flow-types</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-26</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:params:xml:ns:yang:controller:shutdown:impl</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>shutdown-impl</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-12-18</ncm:version>
+ </ncm:schema>
+ <ncm:schema>
+ <ncm:namespace>urn:opendaylight:model:topology:inventory</ncm:namespace>
+ <ncm:location>NETCONF</ncm:location>
+ <ncm:identifier>opendaylight-topology-inventory</ncm:identifier>
+ <ncm:format>yang</ncm:format>
+ <ncm:version>2013-10-30</ncm:version>
+ </ncm:schema>
+</ncm:schemas>
\ No newline at end of file
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-osgi_${scala.version}</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-slf4j_${scala.version}</artifactId>
+ </dependency>
<!-- SAL Dependencies -->
<dependency>
<scope>test</scope>
</dependency>
- <dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
* @param bundleContext
*/
public static final void createInstance(final BundleContext bundleContext) {
-
if(actorSystem == null) {
// Create an OSGi bundle classloader for actor system
BundleDelegatingClassLoader classLoader = new BundleDelegatingClassLoader(bundleContext.getBundle(),
synchronized (ActorSystemFactory.class) {
// Double check
if (actorSystem == null) {
- ActorSystem system = ActorSystem.create("opendaylight-rpc",
- ConfigFactory.load().getConfig("odl-cluster"), classLoader);
+ ActorSystem system = ActorSystem.create("opendaylight-cluster-rpc",
+ ConfigFactory.load().getConfig("odl-cluster-rpc"), classLoader);
actorSystem = system;
}
}
import akka.japi.Function;
import org.opendaylight.controller.remote.rpc.messages.UpdateSchemaContext;
import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistryOld;
import org.opendaylight.controller.sal.core.api.Broker;
import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
import org.opendaylight.yangtools.yang.common.QName;
private void createRpcActors() {
LOG.debug("Create rpc registry and broker actors");
- rpcRegistry = getContext().actorOf(RpcRegistry.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
+ rpcRegistry = getContext().actorOf(RpcRegistryOld.props(clusterWrapper), ActorConstants.RPC_REGISTRY);
rpcBroker = getContext().actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext), ActorConstants.RPC_BROKER);
}
* 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.remote.rpc.registry;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import akka.actor.ActorRef;
+import akka.japi.Option;
+import akka.japi.Pair;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Copier;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import java.io.Serializable;
import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-public class RoutingTable<I, R> {
-
- private final Logger LOG = LoggerFactory.getLogger(RoutingTable.class);
-
- private ConcurrentMap<I,R> globalRpcMap = new ConcurrentHashMap<>();
- private ConcurrentMap<I, LinkedHashSet<R>> routedRpcMap = new ConcurrentHashMap<>();
-
- public ConcurrentMap<I, R> getGlobalRpcMap() {
- return globalRpcMap;
- }
-
- public ConcurrentMap<I, LinkedHashSet<R>> getRoutedRpcMap() {
- return routedRpcMap;
- }
-
- public R getGlobalRoute(final I routeId) {
- Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
- return globalRpcMap.get(routeId);
- }
-
- public void addGlobalRoute(final I routeId, final R route) {
- Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
- Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
- LOG.debug("addGlobalRoute: adding a new route with id[{}] and value [{}]", routeId, route);
- if(globalRpcMap.putIfAbsent(routeId, route) != null) {
- LOG.debug("A route already exist for route id [{}] ", routeId);
- }
- }
+import java.util.HashMap;
+import java.util.Map;
- public void removeGlobalRoute(final I routeId) {
- Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
- LOG.debug("removeGlobalRoute: removing a new route with id [{}]", routeId);
- globalRpcMap.remove(routeId);
- }
+public class RoutingTable implements Copier<RoutingTable>, Serializable {
- public Set<R> getRoutedRpc(final I routeId) {
- Preconditions.checkNotNull(routeId, "getRoutes: routeId cannot be null!");
- Set<R> routes = routedRpcMap.get(routeId);
-
- if (routes == null) {
- return Collections.emptySet();
- }
+ private Map<RpcRouter.RouteIdentifier<?, ?, ?>, Long> table = new HashMap<>();
+ private ActorRef router;
- return ImmutableSet.copyOf(routes);
- }
+ @Override
+ public RoutingTable copy() {
+ RoutingTable copy = new RoutingTable();
+ copy.setTable(Collections.unmodifiableMap(table));
+ copy.setRouter(this.getRouter());
- public R getLastAddedRoutedRpc(final I routeId) {
+ return copy;
+ }
- Set<R> routes = getRoutedRpc(routeId);
+ public Option<Pair<ActorRef, Long>> getRouterFor(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
+ Long updatedTime = table.get(routeId);
- if (routes.isEmpty()) {
- return null;
+ if (updatedTime == null || router == null)
+ return Option.none();
+ else
+ return Option.option(new Pair<>(router, updatedTime));
}
- R route = null;
- Iterator<R> iter = routes.iterator();
- while (iter.hasNext()) {
- route = iter.next();
+ public void addRoute(RpcRouter.RouteIdentifier<?,?,?> routeId){
+ table.put(routeId, System.currentTimeMillis());
}
- return route;
- }
-
- public void addRoutedRpc(final I routeId, final R route) {
- Preconditions.checkNotNull(routeId, "addRoute: routeId cannot be null");
- Preconditions.checkNotNull(route, "addRoute: route cannot be null");
- LOG.debug("addRoute: adding a route with k/v [{}/{}]", routeId, route);
- threadSafeAdd(routeId, route);
- }
-
- public void addRoutedRpcs(final Set<I> routeIds, final R route) {
- Preconditions.checkNotNull(routeIds, "addRoutes: routeIds must not be null");
- for (I routeId : routeIds){
- addRoutedRpc(routeId, route);
+ public void removeRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
+ table.remove(routeId);
}
- }
- public void removeRoute(final I routeId, final R route) {
- Preconditions.checkNotNull(routeId, "removeRoute: routeId cannot be null!");
- Preconditions.checkNotNull(route, "removeRoute: route cannot be null!");
-
- LinkedHashSet<R> routes = routedRpcMap.get(routeId);
- if (routes == null) {
- return;
- }
- LOG.debug("removeRoute: removing a new route with k/v [{}/{}]", routeId, route);
- threadSafeRemove(routeId, route);
- }
-
- public void removeRoutes(final Set<I> routeIds, final R route) {
- Preconditions.checkNotNull(routeIds, "removeRoutes: routeIds must not be null");
- for (I routeId : routeIds){
- removeRoute(routeId, route);
+ public Boolean contains(RpcRouter.RouteIdentifier<?, ?, ?> routeId){
+ return table.containsKey(routeId);
}
- }
-
- /**
- * This method guarantees that no 2 thread over write each other's changes.
- * Just so that we dont end up in infinite loop, it tries for 100 times then throw
- */
- private void threadSafeAdd(final I routeId, final R route) {
- for (int i=0;i<100;i++){
+ ///
+ /// Getter, Setters
+ ///
+ //TODO: Remove public
+ public Map<RpcRouter.RouteIdentifier<?, ?, ?>, Long> getTable() {
+ return table;
+ }
- LinkedHashSet<R> updatedRoutes = new LinkedHashSet<>();
- updatedRoutes.add(route);
- LinkedHashSet<R> oldRoutes = routedRpcMap.putIfAbsent(routeId, updatedRoutes);
- if (oldRoutes == null) {
- return;
- }
+ void setTable(Map<RpcRouter.RouteIdentifier<?, ?, ?>, Long> table) {
+ this.table = table;
+ }
- updatedRoutes = new LinkedHashSet<>(oldRoutes);
- updatedRoutes.add(route);
+ public ActorRef getRouter() {
+ return router;
+ }
- if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
- return;
- }
+ public void setRouter(ActorRef router) {
+ this.router = router;
}
- //the method did not already return means it failed to add route in 100 attempts
- throw new IllegalStateException("Failed to add route [" + routeId + "]");
- }
-
- /**
- * This method guarantees that no 2 thread over write each other's changes.
- * Just so that we dont end up in infinite loop, it tries for 100 times then throw
- */
- private void threadSafeRemove(final I routeId, final R route) {
- LinkedHashSet<R> updatedRoutes = null;
- for (int i=0;i<100;i++){
- LinkedHashSet<R> oldRoutes = routedRpcMap.get(routeId);
-
- // if route to be deleted is the only entry in the set then remove routeId from the cache
- if ((oldRoutes.size() == 1) && oldRoutes.contains(route)){
- routedRpcMap.remove(routeId);
- return;
- }
-
- // if there are multiple routes for this routeId, remove the route to be deleted only from the set.
- updatedRoutes = new LinkedHashSet<>(oldRoutes);
- updatedRoutes.remove(route);
- if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
- return;
- }
+ @Override
+ public String toString() {
+ return "RoutingTable{" +
+ "table=" + table +
+ ", router=" + router +
+ '}';
}
- //the method did not already return means it failed to remove route in 100 attempts
- throw new IllegalStateException("Failed to remove route [" + routeId + "]");
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class RoutingTableOld<I, R> {
+
+ private final Logger LOG = LoggerFactory.getLogger(RoutingTableOld.class);
+
+ private ConcurrentMap<I,R> globalRpcMap = new ConcurrentHashMap<>();
+ private ConcurrentMap<I, LinkedHashSet<R>> routedRpcMap = new ConcurrentHashMap<>();
+
+ public ConcurrentMap<I, R> getGlobalRpcMap() {
+ return globalRpcMap;
+ }
+
+ public ConcurrentMap<I, LinkedHashSet<R>> getRoutedRpcMap() {
+ return routedRpcMap;
+ }
+
+ public R getGlobalRoute(final I routeId) {
+ Preconditions.checkNotNull(routeId, "getGlobalRoute: routeId cannot be null!");
+ return globalRpcMap.get(routeId);
+ }
+
+ public void addGlobalRoute(final I routeId, final R route) {
+ Preconditions.checkNotNull(routeId, "addGlobalRoute: routeId cannot be null!");
+ Preconditions.checkNotNull(route, "addGlobalRoute: route cannot be null!");
+ LOG.debug("addGlobalRoute: adding a new route with id[{}] and value [{}]", routeId, route);
+ if(globalRpcMap.putIfAbsent(routeId, route) != null) {
+ LOG.debug("A route already exist for route id [{}] ", routeId);
+ }
+ }
+
+ public void removeGlobalRoute(final I routeId) {
+ Preconditions.checkNotNull(routeId, "removeGlobalRoute: routeId cannot be null!");
+ LOG.debug("removeGlobalRoute: removing a new route with id [{}]", routeId);
+ globalRpcMap.remove(routeId);
+ }
+
+ public Set<R> getRoutedRpc(final I routeId) {
+ Preconditions.checkNotNull(routeId, "getRoutes: routeId cannot be null!");
+ Set<R> routes = routedRpcMap.get(routeId);
+
+ if (routes == null) {
+ return Collections.emptySet();
+ }
+
+ return ImmutableSet.copyOf(routes);
+ }
+
+ public R getLastAddedRoutedRpc(final I routeId) {
+
+ Set<R> routes = getRoutedRpc(routeId);
+
+ if (routes.isEmpty()) {
+ return null;
+ }
+
+ R route = null;
+ Iterator<R> iter = routes.iterator();
+ while (iter.hasNext()) {
+ route = iter.next();
+ }
+
+ return route;
+ }
+
+ public void addRoutedRpc(final I routeId, final R route) {
+ Preconditions.checkNotNull(routeId, "addRoute: routeId cannot be null");
+ Preconditions.checkNotNull(route, "addRoute: route cannot be null");
+ LOG.debug("addRoute: adding a route with k/v [{}/{}]", routeId, route);
+ threadSafeAdd(routeId, route);
+ }
+
+ public void addRoutedRpcs(final Set<I> routeIds, final R route) {
+ Preconditions.checkNotNull(routeIds, "addRoutes: routeIds must not be null");
+ for (I routeId : routeIds){
+ addRoutedRpc(routeId, route);
+ }
+ }
+
+ public void removeRoute(final I routeId, final R route) {
+ Preconditions.checkNotNull(routeId, "removeRoute: routeId cannot be null!");
+ Preconditions.checkNotNull(route, "removeRoute: route cannot be null!");
+
+ LinkedHashSet<R> routes = routedRpcMap.get(routeId);
+ if (routes == null) {
+ return;
+ }
+ LOG.debug("removeRoute: removing a new route with k/v [{}/{}]", routeId, route);
+ threadSafeRemove(routeId, route);
+ }
+
+ public void removeRoutes(final Set<I> routeIds, final R route) {
+ Preconditions.checkNotNull(routeIds, "removeRoutes: routeIds must not be null");
+ for (I routeId : routeIds){
+ removeRoute(routeId, route);
+ }
+ }
+
+ /**
+ * This method guarantees that no 2 thread over write each other's changes.
+ * Just so that we dont end up in infinite loop, it tries for 100 times then throw
+ */
+ private void threadSafeAdd(final I routeId, final R route) {
+
+ for (int i=0;i<100;i++){
+
+ LinkedHashSet<R> updatedRoutes = new LinkedHashSet<>();
+ updatedRoutes.add(route);
+ LinkedHashSet<R> oldRoutes = routedRpcMap.putIfAbsent(routeId, updatedRoutes);
+ if (oldRoutes == null) {
+ return;
+ }
+
+ updatedRoutes = new LinkedHashSet<>(oldRoutes);
+ updatedRoutes.add(route);
+
+ if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
+ return;
+ }
+ }
+ //the method did not already return means it failed to add route in 100 attempts
+ throw new IllegalStateException("Failed to add route [" + routeId + "]");
+ }
+
+ /**
+ * This method guarantees that no 2 thread over write each other's changes.
+ * Just so that we dont end up in infinite loop, it tries for 100 times then throw
+ */
+ private void threadSafeRemove(final I routeId, final R route) {
+ LinkedHashSet<R> updatedRoutes = null;
+ for (int i=0;i<100;i++){
+ LinkedHashSet<R> oldRoutes = routedRpcMap.get(routeId);
+
+ // if route to be deleted is the only entry in the set then remove routeId from the cache
+ if ((oldRoutes.size() == 1) && oldRoutes.contains(route)){
+ routedRpcMap.remove(routeId);
+ return;
+ }
+
+ // if there are multiple routes for this routeId, remove the route to be deleted only from the set.
+ updatedRoutes = new LinkedHashSet<>(oldRoutes);
+ updatedRoutes.remove(route);
+ if (routedRpcMap.replace(routeId, oldRoutes, updatedRoutes)) {
+ return;
+ }
+
+ }
+ //the method did not already return means it failed to remove route in 100 attempts
+ throw new IllegalStateException("Failed to remove route [" + routeId + "]");
+ }
+}
*/
package org.opendaylight.controller.remote.rpc.registry;
-import akka.actor.ActorSelection;
+import akka.actor.ActorRef;
import akka.actor.Address;
import akka.actor.Props;
-import akka.cluster.ClusterEvent;
-import akka.cluster.Member;
-import akka.japi.Creator;
-import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
-import org.opendaylight.controller.remote.rpc.ActorConstants;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
-import org.opendaylight.controller.remote.rpc.messages.RoutingTableData;
+import akka.actor.UntypedActor;
+import akka.dispatch.Mapper;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Option;
+import akka.japi.Pair;
+import akka.pattern.Patterns;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.remote.rpc.registry.gossip.Bucket;
+import org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import scala.collection.JavaConversions;
+import scala.concurrent.Future;
-import java.util.LinkedHashSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
+
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoute;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.RemoveRoute;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBuckets;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBucketsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucket;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucketReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateBucket;
/**
- * This Actor maintains the routing table state and sync it with other nodes in the cluster.
- *
- * A scheduler runs after an interval of time, which pick a random member from the cluster
- * and send the current state of routing table to the member.
+ * Registry to look up cluster nodes that have registered for a given rpc.
+ * <p>
+ * It uses {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore} to maintain this
+ * cluster wide information.
*
- * when a message of routing table data is received, it gets merged with the local routing table
- * to keep the latest data.
*/
+public class RpcRegistry extends UntypedActor {
+
+ final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+ /**
+ * Store to keep the registry. Bucket store sync's it across nodes in the cluster
+ */
+ private ActorRef bucketStore;
+
+ /**
+ * Rpc broker that would use the registry to route requests.
+ */
+ private ActorRef localRouter;
-public class RpcRegistry extends AbstractUntypedActor {
-
- private static final Logger LOG = LoggerFactory.getLogger(RpcRegistry.class);
- private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable;
- private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
- private final ClusterWrapper clusterWrapper;
- private final ScheduledFuture<?> syncScheduler;
-
- private RpcRegistry(ClusterWrapper clusterWrapper){
- this.routingTable = new RoutingTable<>();
- this.clusterWrapper = clusterWrapper;
- this.syncScheduler = scheduler.scheduleAtFixedRate(new SendRoutingTable(), 10, 10, TimeUnit.SECONDS);
- }
-
- public static Props props(final ClusterWrapper clusterWrapper){
- return Props.create(new Creator<RpcRegistry>(){
-
- @Override
- public RpcRegistry create() throws Exception {
- return new RpcRegistry(clusterWrapper);
- }
- });
- }
-
- @Override
- protected void handleReceive(Object message) throws Exception {
- LOG.debug("Received message {}", message);
- if(message instanceof RoutingTableData) {
- syncRoutingTable((RoutingTableData) message);
- } else if(message instanceof GetRoutedRpc) {
- getRoutedRpc((GetRoutedRpc) message);
- } else if(message instanceof GetRpc) {
- getRpc((GetRpc) message);
- } else if(message instanceof AddRpc) {
- addRpc((AddRpc) message);
- } else if(message instanceof RemoveRpc) {
- removeRpc((RemoveRpc) message);
- } else if(message instanceof AddRoutedRpc) {
- addRoutedRpc((AddRoutedRpc) message);
- } else if(message instanceof RemoveRoutedRpc) {
- removeRoutedRpc((RemoveRoutedRpc) message);
+ public RpcRegistry() {
+ bucketStore = getContext().actorOf(Props.create(BucketStore.class), "store");
}
- }
- private void getRoutedRpc(GetRoutedRpc rpcMsg){
- LOG.debug("Get latest routed Rpc location from routing table {}", rpcMsg);
- String remoteActorPath = routingTable.getLastAddedRoutedRpc(rpcMsg.getRouteId());
- GetRoutedRpcReply routedRpcReply = new GetRoutedRpcReply(remoteActorPath);
+ public RpcRegistry(ActorRef bucketStore) {
+ this.bucketStore = bucketStore;
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
- getSender().tell(routedRpcReply, self());
- }
+ log.debug("Received message: message [{}]", message);
- private void getRpc(GetRpc rpcMsg) {
- LOG.debug("Get global Rpc location from routing table {}", rpcMsg);
- String remoteActorPath = routingTable.getGlobalRoute(rpcMsg.getRouteId());
- GetRpcReply rpcReply = new GetRpcReply(remoteActorPath);
+ //TODO: if sender is remote, reject message
- getSender().tell(rpcReply, self());
- }
+ if (message instanceof SetLocalRouter)
+ receiveSetLocalRouter((SetLocalRouter) message);
- private void addRpc(AddRpc rpcMsg) {
- LOG.debug("Add Rpc to routing table {}", rpcMsg);
- routingTable.addGlobalRoute(rpcMsg.getRouteId(), rpcMsg.getActorPath());
+ if (message instanceof AddOrUpdateRoute)
+ receiveAddRoute((AddOrUpdateRoute) message);
- getSender().tell("Success", self());
- }
+ else if (message instanceof RemoveRoute)
+ receiveRemoveRoute((RemoveRoute) message);
- private void removeRpc(RemoveRpc rpcMsg) {
- LOG.debug("Removing Rpc to routing table {}", rpcMsg);
- routingTable.removeGlobalRoute(rpcMsg.getRouteId());
+ else if (message instanceof Messages.FindRouters)
+ receiveGetRouter((Messages.FindRouters) message);
+
+ else
+ unhandled(message);
+ }
- getSender().tell("Success", self());
- }
+ /**
+ * Register's rpc broker
+ *
+ * @param message contains {@link akka.actor.ActorRef} for rpc broker
+ */
+ private void receiveSetLocalRouter(SetLocalRouter message) {
+ if (message == null || message.getRouter() == null)
+ return;//ignore
- private void addRoutedRpc(AddRoutedRpc rpcMsg) {
- routingTable.addRoutedRpcs(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
- getSender().tell("Success", self());
- }
+ localRouter = message.getRouter();
+ }
- private void removeRoutedRpc(RemoveRoutedRpc rpcMsg) {
- routingTable.removeRoutes(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
- getSender().tell("Success", self());
- }
+ /**
+ * //TODO: update this to accept multiple route registration
+ * @param msg
+ */
+ private void receiveAddRoute(AddOrUpdateRoute msg) {
+ if (msg.getRouteIdentifier() == null)
+ return;//ignore
- private void syncRoutingTable(RoutingTableData routingTableData) {
- LOG.debug("Syncing routing table {}", routingTableData);
+ Preconditions.checkState(localRouter != null, "Router must be set first");
- Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> newRpcMap = routingTableData.getRpcMap();
- Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = newRpcMap.keySet();
- for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
- routingTable.addGlobalRoute(routeId, newRpcMap.get(routeId));
+ Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), 1000);
+ futureReply.map(getMapperToAddRoute(msg.getRouteIdentifier()), getContext().dispatcher());
}
- Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> newRoutedRpcMap =
- routingTableData.getRoutedRpcMap();
- routeIds = newRoutedRpcMap.keySet();
+ /**
+ * //TODO: update this to accept multiple routes
+ * @param msg
+ */
+ private void receiveRemoveRoute(RemoveRoute msg) {
+ if (msg.getRouteIdentifier() == null)
+ return;//ignore
+
+ Future<Object> futureReply = Patterns.ask(bucketStore, new GetLocalBucket(), 1000);
+ futureReply.map(getMapperToRemoveRoute(msg.getRouteIdentifier()), getContext().dispatcher());
- for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
- Set<String> routeAddresses = newRoutedRpcMap.get(routeId);
- for(String routeAddress : routeAddresses) {
- routingTable.addRoutedRpc(routeId, routeAddress);
- }
}
- }
-
- private ActorSelection getRandomRegistryActor() {
- ClusterEvent.CurrentClusterState clusterState = clusterWrapper.getState();
- ActorSelection actor = null;
- Set<Member> members = JavaConversions.asJavaSet(clusterState.members());
- int memberSize = members.size();
- // Don't select yourself
- if(memberSize > 1) {
- Address currentNodeAddress = clusterWrapper.getAddress();
- int index = new Random().nextInt(memberSize);
- int i = 0;
- // keeping previous member, in case when random index member is same as current actor
- // and current actor member is last in set
- Member previousMember = null;
- for(Member member : members){
- if(i == index-1) {
- previousMember = member;
+
+ /**
+ * Finds routers for the given rpc.
+ * @param msg
+ */
+ private void receiveGetRouter(Messages.FindRouters msg) {
+ final ActorRef sender = getSender();
+
+ //if empty message, return empty list
+ if (msg.getRouteIdentifier() == null) {
+ sender.tell(createEmptyReply(), getSelf());
+ return;
}
- if(i == index) {
- if(!currentNodeAddress.equals(member.address())) {
- actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
- break;
- } else if(index < memberSize-1){ // pick the next element in the set
- index++;
- }
+
+ Future<Object> futureReply = Patterns.ask(bucketStore, new GetAllBuckets(), 1000);
+ futureReply.map(getMapperToGetRouter(msg.getRouteIdentifier(), sender), getContext().dispatcher());
+
+ }
+
+ /**
+ * Helper to create empty reply when no routers are found
+ *
+ * @return
+ */
+ private Messages.FindRoutersReply createEmptyReply() {
+ List<Pair<ActorRef, Long>> routerWithUpdateTime = Collections.emptyList();
+ return new Messages.FindRoutersReply(routerWithUpdateTime);
+ }
+
+ /**
+ * Helper to create a reply when routers are found for the given rpc
+ * @param buckets
+ * @param routeId
+ * @return
+ */
+ private Messages.FindRoutersReply createReplyWithRouters(Map<Address, Bucket> buckets, RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
+
+ List<Pair<ActorRef, Long>> routers = new ArrayList<>();
+
+ Option<Pair<ActorRef, Long>> routerWithUpdateTime = null;
+
+ for (Bucket bucket : buckets.values()) {
+
+ RoutingTable table = (RoutingTable) bucket.getData();
+
+ if (table == null)
+ continue;
+
+ routerWithUpdateTime = table.getRouterFor(routeId);
+
+ if (routerWithUpdateTime.isEmpty())
+ continue;
+
+ routers.add(routerWithUpdateTime.get());
}
- i++;
- }
- if(actor == null && previousMember != null) {
- actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
- }
+
+ return new Messages.FindRoutersReply(routers);
}
- return actor;
- }
- private class SendRoutingTable implements Runnable {
- @Override
- public void run() {
- RoutingTableData routingTableData =
- new RoutingTableData(routingTable.getGlobalRpcMap(), routingTable.getRoutedRpcMap());
- LOG.debug("Sending routing table for sync {}", routingTableData);
- ActorSelection actor = getRandomRegistryActor();
- if(actor != null) {
- actor.tell(routingTableData, self());
- }
+ ///
+ ///private factories to create Mapper
+ ///
+
+ /**
+ * Receives all buckets returned from bucket store and finds routers for the buckets where given rpc(routeId) is found
+ *
+ * @param routeId the rpc
+ * @param sender client who asked to find the routers.
+ * @return
+ */
+ private Mapper<Object, Void> getMapperToGetRouter(final RpcRouter.RouteIdentifier<?, ?, ?> routeId, final ActorRef sender) {
+ return new Mapper<Object, Void>() {
+ @Override
+ public Void apply(Object replyMessage) {
+
+ if (replyMessage instanceof GetAllBucketsReply) {
+
+ GetAllBucketsReply reply = (GetAllBucketsReply) replyMessage;
+ Map<Address, Bucket> buckets = reply.getBuckets();
+
+ if (buckets == null || buckets.isEmpty()) {
+ sender.tell(createEmptyReply(), getSelf());
+ return null;
+ }
+
+ sender.tell(createReplyWithRouters(buckets, routeId), getSelf());
+ }
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Receives local bucket from bucket store and updates routing table in it by removing the route. Subsequently,
+ * it updates the local bucket in bucket store.
+ *
+ * @param routeId rpc to remote
+ * @return
+ */
+ private Mapper<Object, Void> getMapperToRemoveRoute(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
+ return new Mapper<Object, Void>() {
+ @Override
+ public Void apply(Object replyMessage) {
+ if (replyMessage instanceof GetLocalBucketReply) {
+
+ GetLocalBucketReply reply = (GetLocalBucketReply) replyMessage;
+ Bucket<RoutingTable> bucket = reply.getBucket();
+
+ if (bucket == null) {
+ log.debug("Local bucket is null");
+ return null;
+ }
+
+ RoutingTable table = bucket.getData();
+ if (table == null)
+ table = new RoutingTable();
+
+ table.setRouter(localRouter);
+ table.removeRoute(routeId);
+
+ bucket.setData(table);
+
+ UpdateBucket updateBucketMessage = new UpdateBucket(bucket);
+ bucketStore.tell(updateBucketMessage, getSelf());
+ }
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Receives local bucket from bucket store and updates routing table in it by adding the route. Subsequently,
+ * it updates the local bucket in bucket store.
+ *
+ * @param routeId rpc to add
+ * @return
+ */
+ private Mapper<Object, Void> getMapperToAddRoute(final RpcRouter.RouteIdentifier<?, ?, ?> routeId) {
+
+ return new Mapper<Object, Void>() {
+ @Override
+ public Void apply(Object replyMessage) {
+ if (replyMessage instanceof GetLocalBucketReply) {
+
+ GetLocalBucketReply reply = (GetLocalBucketReply) replyMessage;
+ Bucket<RoutingTable> bucket = reply.getBucket();
+
+ if (bucket == null) {
+ log.debug("Local bucket is null");
+ return null;
+ }
+
+ RoutingTable table = bucket.getData();
+ if (table == null)
+ table = new RoutingTable();
+
+ table.setRouter(localRouter);
+ table.addRoute(routeId);
+
+ bucket.setData(table);
+
+ UpdateBucket updateBucketMessage = new UpdateBucket(bucket);
+ bucketStore.tell(updateBucketMessage, getSelf());
+ }
+
+ return null;
+ }
+ };
+ }
+
+ /**
+ * All messages used by the RpcRegistry
+ */
+ public static class Messages {
+
+
+ public static class ContainsRoute {
+ final RpcRouter.RouteIdentifier<?,?,?> routeIdentifier;
+
+ public ContainsRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+ Preconditions.checkArgument(routeIdentifier != null);
+ this.routeIdentifier = routeIdentifier;
+ }
+
+ public RpcRouter.RouteIdentifier<?,?,?> getRouteIdentifier(){
+ return this.routeIdentifier;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "{" +
+ "routeIdentifier=" + routeIdentifier +
+ '}';
+ }
+ }
+
+ public static class AddOrUpdateRoute extends ContainsRoute{
+
+ public AddOrUpdateRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+ super(routeIdentifier);
+ }
+ }
+
+ public static class RemoveRoute extends ContainsRoute {
+
+ public RemoveRoute(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+ super(routeIdentifier);
+ }
+ }
+
+ public static class SetLocalRouter{
+ private final ActorRef router;
+
+ public SetLocalRouter(ActorRef router) {
+ this.router = router;
+ }
+
+ public ActorRef getRouter(){
+ return this.router;
+ }
+
+ @Override
+ public String toString() {
+ return "SetLocalRouter{" +
+ "router=" + router +
+ '}';
+ }
+ }
+
+ public static class FindRouters extends ContainsRoute {
+ public FindRouters(RpcRouter.RouteIdentifier<?, ?, ?> routeIdentifier) {
+ super(routeIdentifier);
+ }
+ }
+
+ public static class FindRoutersReply {
+ final List<Pair<ActorRef, Long>> routerWithUpdateTime;
+
+ public FindRoutersReply(List<Pair<ActorRef, Long>> routerWithUpdateTime) {
+ this.routerWithUpdateTime = routerWithUpdateTime;
+ }
+
+ public List<Pair<ActorRef, Long>> getRouterWithUpdateTime(){
+ return routerWithUpdateTime;
+ }
+
+ @Override
+ public String toString() {
+ return "FindRoutersReply{" +
+ "routerWithUpdateTime=" + routerWithUpdateTime +
+ '}';
+ }
+ }
}
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry;
+
+import akka.actor.ActorSelection;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.cluster.ClusterEvent;
+import akka.cluster.Member;
+import akka.japi.Creator;
+import org.opendaylight.controller.remote.rpc.AbstractUntypedActor;
+import org.opendaylight.controller.remote.rpc.ActorConstants;
+import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.AddRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.GetRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
+import org.opendaylight.controller.remote.rpc.messages.RoutingTableData;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.collection.JavaConversions;
+
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This Actor maintains the routing table state and sync it with other nodes in the cluster.
+ *
+ * A scheduler runs after an interval of time, which pick a random member from the cluster
+ * and send the current state of routing table to the member.
+ *
+ * when a message of routing table data is received, it gets merged with the local routing table
+ * to keep the latest data.
+ */
+
+public class RpcRegistryOld extends AbstractUntypedActor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RpcRegistryOld.class);
+ private RoutingTableOld<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable;
+ private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+ private final ClusterWrapper clusterWrapper;
+ private final ScheduledFuture<?> syncScheduler;
+
+ private RpcRegistryOld(ClusterWrapper clusterWrapper){
+ this.routingTable = new RoutingTableOld<>();
+ this.clusterWrapper = clusterWrapper;
+ this.syncScheduler = scheduler.scheduleAtFixedRate(new SendRoutingTable(), 10, 10, TimeUnit.SECONDS);
+ }
+
+ public static Props props(final ClusterWrapper clusterWrapper){
+ return Props.create(new Creator<RpcRegistryOld>(){
+
+ @Override
+ public RpcRegistryOld create() throws Exception {
+ return new RpcRegistryOld(clusterWrapper);
+ }
+ });
+ }
+
+ @Override
+ protected void handleReceive(Object message) throws Exception {
+ LOG.debug("Received message {}", message);
+ if(message instanceof RoutingTableData) {
+ syncRoutingTable((RoutingTableData) message);
+ } else if(message instanceof GetRoutedRpc) {
+ getRoutedRpc((GetRoutedRpc) message);
+ } else if(message instanceof GetRpc) {
+ getRpc((GetRpc) message);
+ } else if(message instanceof AddRpc) {
+ addRpc((AddRpc) message);
+ } else if(message instanceof RemoveRpc) {
+ removeRpc((RemoveRpc) message);
+ } else if(message instanceof AddRoutedRpc) {
+ addRoutedRpc((AddRoutedRpc) message);
+ } else if(message instanceof RemoveRoutedRpc) {
+ removeRoutedRpc((RemoveRoutedRpc) message);
+ }
+ }
+
+ private void getRoutedRpc(GetRoutedRpc rpcMsg){
+ LOG.debug("Get latest routed Rpc location from routing table {}", rpcMsg);
+ String remoteActorPath = routingTable.getLastAddedRoutedRpc(rpcMsg.getRouteId());
+ GetRoutedRpcReply routedRpcReply = new GetRoutedRpcReply(remoteActorPath);
+
+ getSender().tell(routedRpcReply, self());
+ }
+
+ private void getRpc(GetRpc rpcMsg) {
+ LOG.debug("Get global Rpc location from routing table {}", rpcMsg);
+ String remoteActorPath = routingTable.getGlobalRoute(rpcMsg.getRouteId());
+ GetRpcReply rpcReply = new GetRpcReply(remoteActorPath);
+
+ getSender().tell(rpcReply, self());
+ }
+
+ private void addRpc(AddRpc rpcMsg) {
+ LOG.debug("Add Rpc to routing table {}", rpcMsg);
+ routingTable.addGlobalRoute(rpcMsg.getRouteId(), rpcMsg.getActorPath());
+
+ getSender().tell("Success", self());
+ }
+
+ private void removeRpc(RemoveRpc rpcMsg) {
+ LOG.debug("Removing Rpc to routing table {}", rpcMsg);
+ routingTable.removeGlobalRoute(rpcMsg.getRouteId());
+
+ getSender().tell("Success", self());
+ }
+
+ private void addRoutedRpc(AddRoutedRpc rpcMsg) {
+ routingTable.addRoutedRpcs(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
+ getSender().tell("Success", self());
+ }
+
+ private void removeRoutedRpc(RemoveRoutedRpc rpcMsg) {
+ routingTable.removeRoutes(rpcMsg.getAnnouncements(), rpcMsg.getActorPath());
+ getSender().tell("Success", self());
+ }
+
+ private void syncRoutingTable(RoutingTableData routingTableData) {
+ LOG.debug("Syncing routing table {}", routingTableData);
+
+ Map<RpcRouter.RouteIdentifier<?, ?, ?>, String> newRpcMap = routingTableData.getRpcMap();
+ Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = newRpcMap.keySet();
+ for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
+ routingTable.addGlobalRoute(routeId, newRpcMap.get(routeId));
+ }
+
+ Map<RpcRouter.RouteIdentifier<?, ?, ?>, LinkedHashSet<String>> newRoutedRpcMap =
+ routingTableData.getRoutedRpcMap();
+ routeIds = newRoutedRpcMap.keySet();
+
+ for(RpcRouter.RouteIdentifier<?, ?, ?> routeId : routeIds) {
+ Set<String> routeAddresses = newRoutedRpcMap.get(routeId);
+ for(String routeAddress : routeAddresses) {
+ routingTable.addRoutedRpc(routeId, routeAddress);
+ }
+ }
+ }
+
+ private ActorSelection getRandomRegistryActor() {
+ ClusterEvent.CurrentClusterState clusterState = clusterWrapper.getState();
+ ActorSelection actor = null;
+ Set<Member> members = JavaConversions.asJavaSet(clusterState.members());
+ int memberSize = members.size();
+ // Don't select yourself
+ if(memberSize > 1) {
+ Address currentNodeAddress = clusterWrapper.getAddress();
+ int index = new Random().nextInt(memberSize);
+ int i = 0;
+ // keeping previous member, in case when random index member is same as current actor
+ // and current actor member is last in set
+ Member previousMember = null;
+ for(Member member : members){
+ if(i == index-1) {
+ previousMember = member;
+ }
+ if(i == index) {
+ if(!currentNodeAddress.equals(member.address())) {
+ actor = this.context().actorSelection(member.address() + ActorConstants.RPC_REGISTRY_PATH);
+ break;
+ } else if(index < memberSize-1){ // pick the next element in the set
+ index++;
+ }
+ }
+ i++;
+ }
+ if(actor == null && previousMember != null) {
+ actor = this.context().actorSelection(previousMember.address() + ActorConstants.RPC_REGISTRY_PATH);
+ }
+ }
+ return actor;
+ }
+
+ private class SendRoutingTable implements Runnable {
+
+ @Override
+ public void run() {
+ RoutingTableData routingTableData =
+ new RoutingTableData(routingTable.getGlobalRpcMap(), routingTable.getRoutedRpcMap());
+ LOG.debug("Sending routing table for sync {}", routingTableData);
+ ActorSelection actor = getRandomRegistryActor();
+ if(actor != null) {
+ actor.tell(routingTableData, self());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+
+public interface Bucket<T extends Copier<T>> {
+ public Long getVersion();
+ public T getData();
+ public void setData(T data);
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+import java.io.Serializable;
+
+public class BucketImpl<T extends Copier<T>> implements Bucket<T>, Serializable {
+
+ private Long version = System.currentTimeMillis();;
+
+ private T data;
+
+ @Override
+ public Long getVersion() {
+ return version;
+ }
+
+ @Override
+ public T getData() {
+ if (this.data == null)
+ return null;
+
+ return data.copy();
+ }
+
+ public void setData(T data){
+ this.version = System.currentTimeMillis()+1;
+ this.data = data;
+ }
+
+ @Override
+ public String toString() {
+ return "BucketImpl{" +
+ "version=" + version +
+ ", data=" + data +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+import akka.actor.ActorRef;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.cluster.Cluster;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBuckets;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetAllBucketsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersions;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersionsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembers;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembersReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucket;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetLocalBucketReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateBucket;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateRemoteBuckets;
+
+/**
+ * A store that syncs its data across nodes in the cluster.
+ * It maintains a {@link org.opendaylight.controller.remote.rpc.registry.gossip.Bucket} per node. Buckets are versioned.
+ * A node can write ONLY to its bucket. This way, write conflicts are avoided.
+ * <p>
+ * Buckets are sync'ed across nodes using Gossip protocol (http://en.wikipedia.org/wiki/Gossip_protocol)<p>
+ * This store uses a {@link org.opendaylight.controller.remote.rpc.registry.gossip.Gossiper}.
+ *
+ */
+public class BucketStore extends UntypedActor {
+
+ final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+ /**
+ * Bucket owned by the node
+ */
+ private BucketImpl localBucket = new BucketImpl();;
+
+ /**
+ * Buckets ownded by other known nodes in the cluster
+ */
+ private ConcurrentMap<Address, Bucket> remoteBuckets = new ConcurrentHashMap<>();
+
+ /**
+ * Bucket version for every known node in the cluster including this node
+ */
+ private ConcurrentMap<Address, Long> versions = new ConcurrentHashMap<>();
+
+ /**
+ * Cluster address for this node
+ */
+ private final Address selfAddress = Cluster.get(getContext().system()).selfAddress();
+
+ /**
+ * Our private gossiper
+ */
+ private ActorRef gossiper;
+
+ public BucketStore(){
+ gossiper = getContext().actorOf(Props.create(Gossiper.class), "gossiper");
+ }
+
+ /**
+ * This constructor is useful for testing.
+ * TODO: Pass Props instead of ActorRef
+ *
+ * @param gossiper
+ */
+ public BucketStore(ActorRef gossiper){
+ this.gossiper = gossiper;
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+
+ log.debug("Received message: node[{}], message[{}]", selfAddress, message);
+
+ if (message instanceof UpdateBucket)
+ receiveUpdateBucket(((UpdateBucket) message).getBucket());
+
+ else if (message instanceof GetAllBuckets)
+ receiveGetAllBucket();
+
+ else if (message instanceof GetLocalBucket)
+ receiveGetLocalBucket();
+
+ else if (message instanceof GetBucketsByMembers)
+ receiveGetBucketsByMembers(((GetBucketsByMembers) message).getMembers());
+
+ else if (message instanceof GetBucketVersions)
+ receiveGetBucketVersions();
+
+ else if (message instanceof UpdateRemoteBuckets)
+ receiveUpdateRemoteBuckets(((UpdateRemoteBuckets) message).getBuckets());
+
+ else {
+ log.debug("Unhandled message [{}]", message);
+ unhandled(message);
+ }
+
+ }
+
+ /**
+ * Returns a copy of bucket owned by this node
+ */
+ private void receiveGetLocalBucket() {
+ final ActorRef sender = getSender();
+ GetLocalBucketReply reply = new GetLocalBucketReply(localBucket);
+ sender.tell(reply, getSelf());
+ }
+
+ /**
+ * Updates the bucket owned by this node
+ *
+ * @param updatedBucket
+ */
+ void receiveUpdateBucket(Bucket updatedBucket){
+
+ localBucket = (BucketImpl) updatedBucket;
+ versions.put(selfAddress, localBucket.getVersion());
+ }
+
+ /**
+ * Returns all the buckets the this node knows about, self owned + remote
+ */
+ void receiveGetAllBucket(){
+ final ActorRef sender = getSender();
+ sender.tell(new GetAllBucketsReply(getAllBuckets()), getSelf());
+ }
+
+ /**
+ * Helper to collect all known buckets
+ *
+ * @return self owned + remote buckets
+ */
+ Map<Address, Bucket> getAllBuckets(){
+ Map<Address, Bucket> all = new HashMap<>(remoteBuckets.size() + 1);
+
+ //first add the local bucket
+ all.put(selfAddress, localBucket);
+
+ //then get all remote buckets
+ all.putAll(remoteBuckets);
+
+ return all;
+ }
+
+ /**
+ * Returns buckets for requested members that this node knows about
+ *
+ * @param members requested members
+ */
+ void receiveGetBucketsByMembers(Set<Address> members){
+ final ActorRef sender = getSender();
+ Map<Address, Bucket> buckets = getBucketsByMembers(members);
+ sender.tell(new GetBucketsByMembersReply(buckets), getSelf());
+ }
+
+ /**
+ * Helper to collect buckets for requested memebers
+ *
+ * @param members requested members
+ * @return buckets for requested memebers
+ */
+ Map<Address, Bucket> getBucketsByMembers(Set<Address> members) {
+ Map<Address, Bucket> buckets = new HashMap<>();
+
+ //first add the local bucket if asked
+ if (members.contains(selfAddress))
+ buckets.put(selfAddress, localBucket);
+
+ //then get buckets for requested remote nodes
+ for (Address address : members){
+ if (remoteBuckets.containsKey(address))
+ buckets.put(address, remoteBuckets.get(address));
+ }
+
+ return buckets;
+ }
+
+ /**
+ * Returns versions for all buckets known
+ */
+ void receiveGetBucketVersions(){
+ final ActorRef sender = getSender();
+ GetBucketVersionsReply reply = new GetBucketVersionsReply(versions);
+ sender.tell(reply, getSelf());
+ }
+
+ /**
+ * Update local copy of remote buckets where local copy's version is older
+ *
+ * @param receivedBuckets buckets sent by remote
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Gossiper}
+ */
+ void receiveUpdateRemoteBuckets(Map<Address, Bucket> receivedBuckets){
+
+ if (receivedBuckets == null || receivedBuckets.isEmpty())
+ return; //nothing to do
+
+ //Remote cant update self's bucket
+ receivedBuckets.remove(selfAddress);
+
+ for (Map.Entry<Address, Bucket> entry : receivedBuckets.entrySet()){
+
+ Long localVersion = versions.get(entry.getKey());
+ if (localVersion == null) localVersion = -1L;
+
+ Bucket receivedBucket = entry.getValue();
+
+ if (receivedBucket == null)
+ continue;
+
+ Long remoteVersion = receivedBucket.getVersion();
+ if (remoteVersion == null) remoteVersion = -1L;
+
+ //update only if remote version is newer
+ if ( remoteVersion > localVersion ) {
+ remoteBuckets.put(entry.getKey(), receivedBucket);
+ versions.put(entry.getKey(), remoteVersion);
+ }
+ }
+
+ log.debug("State after update - Local Bucket [{}], Remote Buckets [{}]", localBucket, remoteBuckets);
+ }
+
+ ///
+ ///Getter Setters
+ ///
+
+ BucketImpl getLocalBucket() {
+ return localBucket;
+ }
+
+ void setLocalBucket(BucketImpl localBucket) {
+ this.localBucket = localBucket;
+ }
+
+ ConcurrentMap<Address, Bucket> getRemoteBuckets() {
+ return remoteBuckets;
+ }
+
+ void setRemoteBuckets(ConcurrentMap<Address, Bucket> remoteBuckets) {
+ this.remoteBuckets = remoteBuckets;
+ }
+
+ ConcurrentMap<Address, Long> getVersions() {
+ return versions;
+ }
+
+ void setVersions(ConcurrentMap<Address, Long> versions) {
+ this.versions = versions;
+ }
+
+ Address getSelfAddress() {
+ return selfAddress;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+/**
+ * Type of data that goes in {@link org.opendaylight.controller.remote.rpc.registry.gossip.Bucket}.
+ * The implementers should do deep cloning in copy() method.
+ */
+public interface Copier<T> {
+ public T copy();
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
+import akka.actor.Address;
+import akka.actor.Cancellable;
+import akka.actor.UntypedActor;
+import akka.cluster.Cluster;
+import akka.cluster.ClusterEvent;
+import akka.cluster.Member;
+import akka.dispatch.Mapper;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.pattern.Patterns;
+import scala.concurrent.Future;
+import scala.concurrent.duration.FiniteDuration;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersions;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketVersionsReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembers;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.GetBucketsByMembersReply;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.BucketStoreMessages.UpdateRemoteBuckets;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipTick;
+
+/**
+ * Gossiper that syncs bucket store across nodes in the cluster.
+ * <p>
+ * It keeps a local scheduler that periodically sends Gossip ticks to itself to send bucket store's bucket versions
+ * to a randomly selected remote gossiper.
+ * <p>
+ * When bucket versions are received from a remote gossiper, it is compared with bucket store's bucket versions.
+ * Which ever buckets are newer locally, are sent to remote gossiper. If any bucket is older in bucket store, a
+ * gossip status is sent to remote gossiper so that it can send the newer buckets.
+ * <p>
+ * When a bucket is received from a remote gossiper, its sent to the bucket store for update.
+ *
+ */
+
+public class Gossiper extends UntypedActor {
+
+ final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+ Cluster cluster = Cluster.get(getContext().system());
+
+ /**
+ * ActorSystem's address for the current cluster node.
+ */
+ private Address selfAddress = cluster.selfAddress();
+
+ /**
+ * All known cluster members
+ */
+ private List<Address> clusterMembers = new ArrayList<>();
+
+ private Cancellable gossipTask;
+
+ private Boolean autoStartGossipTicks = true;
+
+ public Gossiper(){}
+
+ /**
+ * Helpful for testing
+ * @param autoStartGossipTicks used for turning off gossip ticks during testing. Gossip tick can be manually sent.
+ */
+ public Gossiper(Boolean autoStartGossipTicks){
+ this.autoStartGossipTicks = autoStartGossipTicks;
+ }
+
+ @Override
+ public void preStart(){
+
+ cluster.subscribe(getSelf(),
+ ClusterEvent.initialStateAsEvents(),
+ ClusterEvent.MemberEvent.class,
+ ClusterEvent.UnreachableMember.class);
+
+ if (autoStartGossipTicks) {
+ gossipTask = getContext().system().scheduler().schedule(
+ new FiniteDuration(1, TimeUnit.SECONDS), //initial delay
+ new FiniteDuration(500, TimeUnit.MILLISECONDS), //interval
+ getSelf(), //target
+ new Messages.GossiperMessages.GossipTick(), //message
+ getContext().dispatcher(), //execution context
+ getSelf() //sender
+ );
+ }
+ }
+
+ @Override
+ public void postStop(){
+ if (cluster != null)
+ cluster.unsubscribe(getSelf());
+ if (gossipTask != null)
+ gossipTask.cancel();
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+
+ log.debug("Received message: node[{}], message[{}]", selfAddress, message);
+
+ //Usually sent by self via gossip task defined above. But its not enforced.
+ //These ticks can be sent by another actor as well which is esp. useful while testing
+ if (message instanceof GossipTick)
+ receiveGossipTick();
+
+ //Message from remote gossiper with its bucket versions
+ else if (message instanceof GossipStatus)
+ receiveGossipStatus((GossipStatus) message);
+
+ //Message from remote gossiper with buckets. This is usually in response to GossipStatus message
+ //The contained buckets are newer as determined by the remote gossiper by comparing the GossipStatus
+ //message with its local versions
+ else if (message instanceof GossipEnvelope)
+ receiveGossip((GossipEnvelope) message);
+
+ else if (message instanceof ClusterEvent.MemberUp) {
+ receiveMemberUp(((ClusterEvent.MemberUp) message).member());
+
+ } else if (message instanceof ClusterEvent.MemberRemoved) {
+ receiveMemberRemoveOrUnreachable(((ClusterEvent.MemberRemoved) message).member());
+
+ } else if ( message instanceof ClusterEvent.UnreachableMember){
+ receiveMemberRemoveOrUnreachable(((ClusterEvent.UnreachableMember) message).member());
+
+ } else
+ unhandled(message);
+ }
+
+ /**
+ * Remove member from local copy of member list. If member down is self, then stop the actor
+ *
+ * @param member who went down
+ */
+ void receiveMemberRemoveOrUnreachable(Member member) {
+ //if its self, then stop itself
+ if (selfAddress.equals(member.address())){
+ getContext().stop(getSelf());
+ return;
+ }
+
+ clusterMembers.remove(member.address());
+ log.debug("Removed member [{}], Active member list [{}]", member.address(), clusterMembers);
+ }
+
+ /**
+ * Add member to the local copy of member list if it doesnt already
+ * @param member
+ */
+ void receiveMemberUp(Member member) {
+
+ if (selfAddress.equals(member.address()))
+ return; //ignore up notification for self
+
+ if (!clusterMembers.contains(member.address()))
+ clusterMembers.add(member.address());
+
+ log.debug("Added member [{}], Active member list [{}]", member.address(), clusterMembers);
+ }
+
+ /**
+ * Sends Gossip status to other members in the cluster. <br/>
+ * 1. If there are no member, ignore the tick. </br>
+ * 2. If there's only 1 member, send gossip status (bucket versions) to it. <br/>
+ * 3. If there are more than one member, randomly pick one and send gossip status (bucket versions) to it.
+ */
+ void receiveGossipTick(){
+ if (clusterMembers.size() == 0) return; //no members to send gossip status to
+
+ Address remoteMemberToGossipTo = null;
+
+ if (clusterMembers.size() == 1)
+ remoteMemberToGossipTo = clusterMembers.get(0);
+ else {
+ Integer randomIndex = ThreadLocalRandom.current().nextInt(0, clusterMembers.size());
+ remoteMemberToGossipTo = clusterMembers.get(randomIndex);
+ }
+
+ log.debug("Gossiping to [{}]", remoteMemberToGossipTo);
+ getLocalStatusAndSendTo(remoteMemberToGossipTo);
+ }
+
+ /**
+ * Process gossip status received from a remote gossiper. Remote versions are compared with
+ * the local copy. <p>
+ *
+ * For each bucket
+ * <ul>
+ * <li>If local copy is newer, the newer buckets are sent in GossipEnvelope to remote</li>
+ * <li>If local is older, GossipStatus is sent to remote so that it can reply with GossipEnvelope</li>
+ * <li>If both are same, noop</li>
+ * </ul>
+ *
+ * @param status bucket versions from a remote member
+ */
+ void receiveGossipStatus(GossipStatus status){
+ //Dont want to accept messages from non-members
+ if (!clusterMembers.contains(status.from()))
+ return;
+
+ final ActorRef sender = getSender();
+
+ Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketVersions(), 1000);
+
+ futureReply.map(getMapperToProcessRemoteStatus(sender, status), getContext().dispatcher());
+
+ }
+
+ /**
+ * Sends the received buckets in the envelope to the parent Bucket store.
+ *
+ * @param envelope contains buckets from a remote gossiper
+ */
+ void receiveGossip(GossipEnvelope envelope){
+ //TODO: Add more validations
+ if (!selfAddress.equals(envelope.to())) {
+ log.info("Ignoring message intended for someone else. From [{}] to [{}]", envelope.from(), envelope.to());
+ return;
+ }
+ if (envelope.getBuckets() == null)
+ return; //nothing to do
+
+ updateRemoteBuckets(envelope.getBuckets());
+
+ }
+
+ /**
+ * Helper to send received buckets to bucket store
+ *
+ * @param buckets
+ */
+ void updateRemoteBuckets(Map<Address, Bucket> buckets) {
+
+ if (buckets == null || buckets.isEmpty())
+ return; //nothing to merge
+
+ UpdateRemoteBuckets updateRemoteBuckets = new UpdateRemoteBuckets(buckets);
+
+ getContext().parent().tell(updateRemoteBuckets, getSelf());
+ }
+
+ /**
+ * Gets the buckets from bucket store for the given node addresses and sends them to remote gossiper
+ *
+ * @param remote remote node to send Buckets to
+ * @param addresses node addresses whose buckets needs to be sent
+ */
+ void sendGossipTo(final ActorRef remote, final Set<Address> addresses){
+
+ Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketsByMembers(addresses), 1000);
+
+ futureReply.map(getMapperToSendGossip(remote), getContext().dispatcher());
+
+ }
+
+ /**
+ * Gets bucket versions from bucket store and sends to the supplied address
+ *
+ * @param remoteActorSystemAddress remote gossiper to send to
+ */
+ void getLocalStatusAndSendTo(Address remoteActorSystemAddress){
+
+ //Get local status from bucket store and send to remote
+ Future<Object> futureReply = Patterns.ask(getContext().parent(), new GetBucketVersions(), 1000);
+
+ ActorSelection remoteRef = getContext().system().actorSelection(
+ remoteActorSystemAddress.toString() + getSelf().path().toStringWithoutAddress());
+
+ log.debug("Sending bucket versions to [{}]", remoteRef);
+
+ futureReply.map(getMapperToSendLocalStatus(remoteRef), getContext().dispatcher());
+
+ }
+
+ /**
+ * Helper to send bucket versions received from local store
+ * @param remote remote gossiper to send versions to
+ * @param localVersions bucket versions received from local store
+ */
+ void sendGossipStatusTo(ActorRef remote, Map<Address, Long> localVersions){
+
+ GossipStatus status = new GossipStatus(selfAddress, localVersions);
+ remote.tell(status, getSelf());
+ }
+
+ void sendGossipStatusTo(ActorSelection remote, Map<Address, Long> localVersions){
+
+ GossipStatus status = new GossipStatus(selfAddress, localVersions);
+ remote.tell(status, getSelf());
+ }
+
+ ///
+ /// Private factories to create mappers
+ ///
+
+ private Mapper<Object, Void> getMapperToSendLocalStatus(final ActorSelection remote){
+
+ return new Mapper<Object, Void>() {
+ @Override
+ public Void apply(Object replyMessage) {
+ if (replyMessage instanceof GetBucketVersionsReply) {
+ GetBucketVersionsReply reply = (GetBucketVersionsReply) replyMessage;
+ Map<Address, Long> localVersions = reply.getVersions();
+
+ sendGossipStatusTo(remote, localVersions);
+
+ }
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Process bucket versions received from {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore}.
+ * Then this method compares remote bucket versions with local bucket versions.
+ * <ul>
+ * <li>The buckets that are newer locally, send
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope} to remote
+ * <li>The buckets that are older locally, send
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus} to remote so that
+ * remote sends GossipEnvelop.
+ * </ul>
+ *
+ * @param sender the remote member
+ * @param status bucket versions from a remote member
+ * @return a {@link akka.dispatch.Mapper} that gets evaluated in future
+ *
+ */
+ private Mapper<Object, Void> getMapperToProcessRemoteStatus(final ActorRef sender, final GossipStatus status){
+
+ final Map<Address, Long> remoteVersions = status.getVersions();
+
+ return new Mapper<Object, Void>() {
+ @Override
+ public Void apply(Object replyMessage) {
+ if (replyMessage instanceof GetBucketVersionsReply) {
+ GetBucketVersionsReply reply = (GetBucketVersionsReply) replyMessage;
+ Map<Address, Long> localVersions = reply.getVersions();
+
+ //diff between remote list and local
+ Set<Address> localIsOlder = new HashSet<>();
+ localIsOlder.addAll(remoteVersions.keySet());
+ localIsOlder.removeAll(localVersions.keySet());
+
+ //diff between local list and remote
+ Set<Address> localIsNewer = new HashSet<>();
+ localIsNewer.addAll(localVersions.keySet());
+ localIsNewer.removeAll(remoteVersions.keySet());
+
+
+ for (Address address : remoteVersions.keySet()){
+
+ if (localVersions.get(address) == null || remoteVersions.get(address) == null)
+ continue; //this condition is taken care of by above diffs
+ if (localVersions.get(address) < remoteVersions.get(address))
+ localIsOlder.add(address);
+ else if (localVersions.get(address) > remoteVersions.get(address))
+ localIsNewer.add(address);
+ else
+ continue;
+ }
+
+ if (!localIsOlder.isEmpty())
+ sendGossipStatusTo(sender, localVersions );
+
+ if (!localIsNewer.isEmpty())
+ sendGossipTo(sender, localIsNewer);//send newer buckets to remote
+
+ }
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Processes the message from {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore} that contains
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Bucket}. These buckets are sent to a remote member encapsulated
+ * in {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope}
+ *
+ * @param sender the remote member that sent
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus}
+ * in reply to which bucket is being sent back
+ * @return a {@link akka.dispatch.Mapper} that gets evaluated in future
+ *
+ */
+ private Mapper<Object, Void> getMapperToSendGossip(final ActorRef sender) {
+
+ return new Mapper<Object, Void>() {
+ @Override
+ public Void apply(Object msg) {
+ if (msg instanceof GetBucketsByMembersReply) {
+ Map<Address, Bucket> buckets = ((GetBucketsByMembersReply) msg).getBuckets();
+ log.info("Buckets to send from {}: {}", selfAddress, buckets);
+ GossipEnvelope envelope = new GossipEnvelope(selfAddress, sender.path().address(), buckets);
+ sender.tell(envelope, getSelf());
+ }
+ return null;
+ }
+ };
+ }
+
+ ///
+ ///Getter Setters
+ ///
+ List<Address> getClusterMembers() {
+ return clusterMembers;
+ }
+
+ void setClusterMembers(List<Address> clusterMembers) {
+ this.clusterMembers = clusterMembers;
+ }
+
+ Address getSelfAddress() {
+ return selfAddress;
+ }
+
+ void setSelfAddress(Address selfAddress) {
+ this.selfAddress = selfAddress;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+import akka.actor.Address;
+import com.google.common.base.Preconditions;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * These messages are used by {@link org.opendaylight.controller.remote.rpc.registry.gossip.BucketStore} and
+ * {@link org.opendaylight.controller.remote.rpc.registry.gossip.Gossiper} actors.
+ */
+public class Messages {
+
+ public static class BucketStoreMessages{
+
+ public static class GetLocalBucket implements Serializable{}
+
+ public static class ContainsBucket implements Serializable {
+ final private Bucket bucket;
+
+ public ContainsBucket(Bucket bucket){
+ Preconditions.checkArgument(bucket != null, "bucket can not be null");
+ this.bucket = bucket;
+ }
+
+ public Bucket getBucket(){
+ return bucket;
+ }
+
+ }
+
+ public static class UpdateBucket extends ContainsBucket implements Serializable {
+ public UpdateBucket(Bucket bucket){
+ super(bucket);
+ }
+ }
+
+ public static class GetLocalBucketReply extends ContainsBucket implements Serializable {
+ public GetLocalBucketReply(Bucket bucket){
+ super(bucket);
+ }
+ }
+
+ public static class GetAllBuckets implements Serializable{}
+
+ public static class GetBucketsByMembers implements Serializable{
+ private Set<Address> members;
+
+ public GetBucketsByMembers(Set<Address> members){
+ Preconditions.checkArgument(members != null, "members can not be null");
+ this.members = members;
+ }
+
+ public Set<Address> getMembers() {
+ return new HashSet<>(members);
+ }
+ }
+
+ public static class ContainsBuckets implements Serializable{
+ private Map<Address, Bucket> buckets;
+
+ public ContainsBuckets(Map<Address, Bucket> buckets){
+ Preconditions.checkArgument(buckets != null, "buckets can not be null");
+ this.buckets = buckets;
+ }
+
+ public Map<Address, Bucket> getBuckets() {
+ Map<Address, Bucket> copy = new HashMap<>(buckets.size());
+
+ for (Map.Entry<Address, Bucket> entry : buckets.entrySet()){
+ //ignore null entries
+ if ( (entry.getKey() == null) || (entry.getValue() == null) )
+ continue;
+ copy.put(entry.getKey(), entry.getValue());
+ }
+ return new HashMap<>(copy);
+ }
+ }
+
+ public static class GetAllBucketsReply extends ContainsBuckets implements Serializable{
+ public GetAllBucketsReply(Map<Address, Bucket> buckets) {
+ super(buckets);
+ }
+ }
+
+ public static class GetBucketsByMembersReply extends ContainsBuckets implements Serializable{
+ public GetBucketsByMembersReply(Map<Address, Bucket> buckets) {
+ super(buckets);
+ }
+ }
+
+ public static class GetBucketVersions implements Serializable{}
+
+ public static class ContainsBucketVersions implements Serializable{
+ Map<Address, Long> versions;
+
+ public ContainsBucketVersions(Map<Address, Long> versions) {
+ Preconditions.checkArgument(versions != null, "versions can not be null");
+ this.versions = versions;
+ }
+
+ public Map<Address, Long> getVersions() {
+ return Collections.unmodifiableMap(versions);
+ }
+
+ }
+
+ public static class GetBucketVersionsReply extends ContainsBucketVersions implements Serializable{
+ public GetBucketVersionsReply(Map<Address, Long> versions) {
+ super(versions);
+ }
+ }
+
+ public static class UpdateRemoteBuckets extends ContainsBuckets implements Serializable{
+ public UpdateRemoteBuckets(Map<Address, Bucket> buckets) {
+ super(buckets);
+ }
+ }
+ }
+
+ public static class GossiperMessages{
+ public static class Tick implements Serializable {}
+
+ public static final class GossipTick extends Tick {}
+
+ public static final class GossipStatus extends BucketStoreMessages.ContainsBucketVersions implements Serializable{
+ private Address from;
+
+ public GossipStatus(Address from, Map<Address, Long> versions) {
+ super(versions);
+ this.from = from;
+ }
+
+ public Address from() {
+ return from;
+ }
+ }
+
+ public static final class GossipEnvelope extends BucketStoreMessages.ContainsBuckets implements Serializable {
+ private final Address from;
+ private final Address to;
+
+ public GossipEnvelope(Address from, Address to, Map<Address, Bucket> buckets) {
+ super(buckets);
+ this.to = to;
+ this.from = from;
+ }
+
+ public Address from() {
+ return from;
+ }
+
+ public Address to() {
+ return to;
+ }
+ }
+ }
+}
-odl-cluster{
+
+odl-cluster-data {
+ akka {
+ cluster {
+ roles = [
+ "member-1"
+ ]
+ }
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ serializers {
+ java = "akka.serialization.JavaSerializer"
+ proto = "akka.remote.serialization.ProtobufSerializer"
+ }
+
+ serialization-bindings {
+ "com.google.protobuf.Message" = proto
+
+ }
+ }
+ remote {
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2550
+ maximum-frame-size = 2097152
+ send-buffer-size = 52428800
+ receive-buffer-size = 52428800
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
+
+odl-cluster-rpc {
akka {
actor {
provider = "akka.cluster.ClusterActorRefProvider"
remote {
log-remote-lifecycle-events = off
netty.tcp {
- hostname = "192.168.141.141"
+ hostname = "127.0.0.1"
port = 2551
}
}
cluster {
- seed-nodes = ["akka.tcp://opendaylight-rpc@192.168.141.141:2551"]
+ seed-nodes = ["akka.tcp://opendaylight-cluster-rpc@127.0.0.1:2551"]
auto-down-unreachable-after = 10s
}
}
-}
\ No newline at end of file
+}
import org.opendaylight.controller.remote.rpc.messages.InvokeRpc;
import org.opendaylight.controller.remote.rpc.messages.RpcResponse;
import org.opendaylight.controller.remote.rpc.registry.ClusterWrapper;
-import org.opendaylight.controller.remote.rpc.registry.RpcRegistry;
+import org.opendaylight.controller.remote.rpc.registry.RpcRegistryOld;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.controller.sal.core.api.Broker;
@Test
public void testInvokeRpcError() throws URISyntaxException {
new JavaTestKit(system) {{
- ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
+ ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
Broker.ProviderSession brokerSession = Mockito.mock(Broker.ProviderSession.class);
SchemaContext schemaContext = mock(SchemaContext.class);
ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@Test
public void testInvokeRpc() throws URISyntaxException {
new JavaTestKit(system) {{
- ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(mock(ClusterWrapper.class)));
+ ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(mock(ClusterWrapper.class)));
Broker.ProviderSession brokerSession = mock(Broker.ProviderSession.class);
SchemaContext schemaContext = mock(SchemaContext.class);
ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@Test
public void testInvokeRoutedRpcError() throws URISyntaxException {
new JavaTestKit(system) {{
- ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
+ ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
Broker.ProviderSession brokerSession = Mockito.mock(Broker.ProviderSession.class);
SchemaContext schemaContext = mock(SchemaContext.class);
ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
@Test
public void testInvokeRoutedRpc() throws URISyntaxException {
new JavaTestKit(system) {{
- ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(mock(ClusterWrapper.class)));
+ ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(mock(ClusterWrapper.class)));
Broker.ProviderSession brokerSession = mock(Broker.ProviderSession.class);
SchemaContext schemaContext = mock(SchemaContext.class);
ActorRef rpcBroker = system.actorOf(RpcBroker.props(brokerSession, rpcRegistry, schemaContext));
import java.util.HashSet;
import java.util.Set;
-public class RoutingTableTest {
+public class RoutingTableOldTest {
- private RoutingTable<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable =
- new RoutingTable<>();
+ private RoutingTableOld<RpcRouter.RouteIdentifier<?, ?, ?>, String> routingTable =
+ new RoutingTableOld<>();
@Test
public void addGlobalRouteNullRouteIdTest() {
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.testkit.JavaTestKit;
+import junit.framework.Assert;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
+import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.AddRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.GetRpc;
+import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
+import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
+import org.opendaylight.controller.sal.connector.api.RpcRouter;
+import org.opendaylight.yangtools.yang.common.QName;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class RpcRegistryOldTest {
+
+ static ActorSystem system;
+
+
+ @BeforeClass
+ public static void setup() {
+ system = ActorSystem.create();
+ }
+
+ @AfterClass
+ public static void teardown() {
+ JavaTestKit.shutdownActorSystem(system);
+ system = null;
+ }
+
+ /**
+ This test add, read and remove an entry in global rpc
+ */
+ @Test
+ public void testGlobalRpc() throws URISyntaxException {
+ new JavaTestKit(system) {{
+ ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
+ QName type = new QName(new URI("actor1"), "actor1");
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
+ final String route = "actor1";
+
+ AddRpc rpcMsg = new AddRpc(routeId, route);
+ rpcRegistry.tell(rpcMsg, getRef());
+ expectMsgEquals(duration("2 second"), "Success");
+
+ GetRpc getRpc = new GetRpc(routeId);
+ rpcRegistry.tell(getRpc, getRef());
+
+ Boolean getMsg = new ExpectMsg<Boolean>("GetRpcReply") {
+ protected Boolean match(Object in) {
+ if (in instanceof GetRpcReply) {
+ GetRpcReply reply = (GetRpcReply)in;
+ return route.equals(reply.getRoutePath());
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ Assert.assertTrue(getMsg);
+
+ RemoveRpc removeMsg = new RemoveRpc(routeId);
+ rpcRegistry.tell(removeMsg, getRef());
+ expectMsgEquals(duration("2 second"), "Success");
+
+ rpcRegistry.tell(getRpc, getRef());
+
+ Boolean getNullMsg = new ExpectMsg<Boolean>("GetRpcReply") {
+ protected Boolean match(Object in) {
+ if (in instanceof GetRpcReply) {
+ GetRpcReply reply = (GetRpcReply)in;
+ return reply.getRoutePath() == null;
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get();
+ Assert.assertTrue(getNullMsg);
+ }};
+
+ }
+
+ /**
+ This test add, read and remove an entry in routed rpc
+ */
+ @Test
+ public void testRoutedRpc() throws URISyntaxException {
+ new JavaTestKit(system) {{
+ ActorRef rpcRegistry = system.actorOf(RpcRegistryOld.props(Mockito.mock(ClusterWrapper.class)));
+ QName type = new QName(new URI("actor1"), "actor1");
+ RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
+ final String route = "actor1";
+
+ Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
+ routeIds.add(routeId);
+
+ AddRoutedRpc rpcMsg = new AddRoutedRpc(routeIds, route);
+ rpcRegistry.tell(rpcMsg, getRef());
+ expectMsgEquals(duration("2 second"), "Success");
+
+ GetRoutedRpc getRpc = new GetRoutedRpc(routeId);
+ rpcRegistry.tell(getRpc, getRef());
+
+ Boolean getMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
+ protected Boolean match(Object in) {
+ if (in instanceof GetRoutedRpcReply) {
+ GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
+ return route.equals(reply.getRoutePath());
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ Assert.assertTrue(getMsg);
+
+ RemoveRoutedRpc removeMsg = new RemoveRoutedRpc(routeIds, route);
+ rpcRegistry.tell(removeMsg, getRef());
+ expectMsgEquals(duration("2 second"), "Success");
+
+ rpcRegistry.tell(getRpc, getRef());
+
+ Boolean getNullMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
+ protected Boolean match(Object in) {
+ if (in instanceof GetRoutedRpcReply) {
+ GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
+ return reply.getRoutePath() == null;
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get();
+ Assert.assertTrue(getNullMsg);
+ }};
+
+ }
+
+}
-/*
- * Copyright (c) 2014 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.remote.rpc.registry;
+import akka.actor.ActorPath;
import akka.actor.ActorRef;
+import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
+import akka.actor.ChildActorPath;
+import akka.actor.Props;
+import akka.japi.Pair;
import akka.testkit.JavaTestKit;
-import junit.framework.Assert;
+import com.typesafe.config.ConfigFactory;
+import org.junit.After;
import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.mockito.Mockito;
import org.opendaylight.controller.remote.rpc.RouteIdentifierImpl;
-import org.opendaylight.controller.remote.rpc.messages.AddRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.AddRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRoutedRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.GetRpc;
-import org.opendaylight.controller.remote.rpc.messages.GetRpcReply;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRoutedRpc;
-import org.opendaylight.controller.remote.rpc.messages.RemoveRpc;
import org.opendaylight.controller.sal.connector.api.RpcRouter;
import org.opendaylight.yangtools.yang.common.QName;
+import scala.concurrent.Await;
+import scala.concurrent.Future;
+import scala.concurrent.duration.FiniteDuration;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.AddOrUpdateRoute;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.FindRouters;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.FindRoutersReply;
+import static org.opendaylight.controller.remote.rpc.registry.RpcRegistry.Messages.SetLocalRouter;
public class RpcRegistryTest {
- static ActorSystem system;
-
-
- @BeforeClass
- public static void setup() {
- system = ActorSystem.create();
- }
-
- @AfterClass
- public static void teardown() {
- JavaTestKit.shutdownActorSystem(system);
- system = null;
- }
-
- /**
- This test add, read and remove an entry in global rpc
- */
- @Test
- public void testGlobalRpc() throws URISyntaxException {
- new JavaTestKit(system) {{
- ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
- QName type = new QName(new URI("actor1"), "actor1");
- RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
- final String route = "actor1";
-
- AddRpc rpcMsg = new AddRpc(routeId, route);
- rpcRegistry.tell(rpcMsg, getRef());
- expectMsgEquals(duration("2 second"), "Success");
-
- GetRpc getRpc = new GetRpc(routeId);
- rpcRegistry.tell(getRpc, getRef());
-
- Boolean getMsg = new ExpectMsg<Boolean>("GetRpcReply") {
- protected Boolean match(Object in) {
- if (in instanceof GetRpcReply) {
- GetRpcReply reply = (GetRpcReply)in;
- return route.equals(reply.getRoutePath());
- } else {
- throw noMatch();
- }
- }
- }.get(); // this extracts the received message
+ private static ActorSystem node1;
+ private static ActorSystem node2;
+ private static ActorSystem node3;
+
+ private ActorRef registry1;
+ private ActorRef registry2;
+ private ActorRef registry3;
+
+ @BeforeClass
+ public static void setup() throws InterruptedException {
+ Thread.sleep(1000); //give some time for previous test to close netty ports
+ node1 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberA"));
+ node2 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberB"));
+ node3 = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("memberC"));
+ }
+
+ @AfterClass
+ public static void teardown(){
+ JavaTestKit.shutdownActorSystem(node1);
+ JavaTestKit.shutdownActorSystem(node2);
+ JavaTestKit.shutdownActorSystem(node3);
+ if (node1 != null)
+ node1.shutdown();
+ if (node2 != null)
+ node2.shutdown();
+ if (node3 != null)
+ node3.shutdown();
+
+ }
+
+ @Before
+ public void createRpcRegistry() throws InterruptedException {
+ registry1 = node1.actorOf(Props.create(RpcRegistry.class));
+ registry2 = node2.actorOf(Props.create(RpcRegistry.class));
+ registry3 = node3.actorOf(Props.create(RpcRegistry.class));
+ }
+
+ @After
+ public void stopRpcRegistry() throws InterruptedException {
+ if (registry1 != null)
+ node1.stop(registry1);
+ if (registry2 != null)
+ node2.stop(registry2);
+ if (registry3 != null)
+ node3.stop(registry3);
+ }
+
+ /**
+ * One node cluster.
+ * Register rpc. Ensure router can be found
+ *
+ * @throws URISyntaxException
+ * @throws InterruptedException
+ */
+ @Test
+ public void testWhenRpcAddedOneNodeShouldAppearOnSameNode() throws URISyntaxException, InterruptedException {
+
+ final JavaTestKit mockBroker = new JavaTestKit(node1);
+
+ //Add rpc on node 1
+ registry1.tell(new SetLocalRouter(mockBroker.getRef()), mockBroker.getRef());
+ registry1.tell(getAddRouteMessage(), mockBroker.getRef());
+
+ Thread.sleep(1000);//
+
+ //find the route on node 1's registry
+ registry1.tell(new FindRouters(createRouteId()), mockBroker.getRef());
+ FindRoutersReply message = mockBroker.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+ List<Pair<ActorRef, Long>> pairs = message.getRouterWithUpdateTime();
+
+ validateRouterReceived(pairs, mockBroker.getRef());
+ }
+
+ /**
+ * Three node cluster.
+ * Register rpc on 1 node. Ensure its router can be found on other 2.
+ *
+ * @throws URISyntaxException
+ * @throws InterruptedException
+ */
+ @Test
+ public void testWhenRpcAddedOneNodeShouldAppearOnAnother() throws URISyntaxException, InterruptedException {
+
+ validateSystemStartup();
+
+ final JavaTestKit mockBroker1 = new JavaTestKit(node1);
+ final JavaTestKit mockBroker2 = new JavaTestKit(node2);
+ final JavaTestKit mockBroker3 = new JavaTestKit(node3);
+
+ //Add rpc on node 1
+ registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
+ registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
+
+ Thread.sleep(5000);// give some time for bucket store data sync
+
+ //find the route in node 2's registry
+ registry2.tell(new FindRouters(createRouteId()), mockBroker2.getRef());
+ FindRoutersReply message = mockBroker2.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+ List<Pair<ActorRef, Long>> pairs = message.getRouterWithUpdateTime();
+
+ validateRouterReceived(pairs, mockBroker1.getRef());
+
+ //find the route in node 3's registry
+ registry3.tell(new FindRouters(createRouteId()), mockBroker3.getRef());
+ message = mockBroker3.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+ pairs = message.getRouterWithUpdateTime();
+
+ validateRouterReceived(pairs, mockBroker1.getRef());
+
+ }
+
+ /**
+ * Three node cluster.
+ * Register rpc on 2 nodes. Ensure 2 routers are found on 3rd.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testAnRpcAddedOnMultiNodesShouldReturnMultiRouter() throws Exception {
+
+ validateSystemStartup();
+
+ final JavaTestKit mockBroker1 = new JavaTestKit(node1);
+ final JavaTestKit mockBroker2 = new JavaTestKit(node2);
+ final JavaTestKit mockBroker3 = new JavaTestKit(node3);
+
+ //Thread.sleep(5000);//let system come up
+
+ //Add rpc on node 1
+ registry1.tell(new SetLocalRouter(mockBroker1.getRef()), mockBroker1.getRef());
+ registry1.tell(getAddRouteMessage(), mockBroker1.getRef());
+
+ //Add same rpc on node 2
+ registry2.tell(new SetLocalRouter(mockBroker2.getRef()), mockBroker2.getRef());
+ registry2.tell(getAddRouteMessage(), mockBroker2.getRef());
+
+ registry3.tell(new SetLocalRouter(mockBroker3.getRef()), mockBroker3.getRef());
+ Thread.sleep(5000);// give some time for bucket store data sync
+
+ //find the route in node 3's registry
+ registry3.tell(new FindRouters(createRouteId()), mockBroker3.getRef());
+ FindRoutersReply message = mockBroker3.expectMsgClass(JavaTestKit.duration("10 second"), FindRoutersReply.class);
+ List<Pair<ActorRef, Long>> pairs = message.getRouterWithUpdateTime();
- Assert.assertTrue(getMsg);
+ validateMultiRouterReceived(pairs, mockBroker1.getRef(), mockBroker2.getRef());
- RemoveRpc removeMsg = new RemoveRpc(routeId);
- rpcRegistry.tell(removeMsg, getRef());
- expectMsgEquals(duration("2 second"), "Success");
+ }
- rpcRegistry.tell(getRpc, getRef());
+ private void validateMultiRouterReceived(List<Pair<ActorRef, Long>> actual, ActorRef... expected) {
+ Assert.assertTrue(actual != null);
+ Assert.assertTrue(actual.size() == expected.length);
+ }
- Boolean getNullMsg = new ExpectMsg<Boolean>("GetRpcReply") {
- protected Boolean match(Object in) {
- if (in instanceof GetRpcReply) {
- GetRpcReply reply = (GetRpcReply)in;
- return reply.getRoutePath() == null;
- } else {
- throw noMatch();
- }
- }
- }.get();
- Assert.assertTrue(getNullMsg);
- }};
-
- }
-
- /**
- This test add, read and remove an entry in routed rpc
- */
- @Test
- public void testRoutedRpc() throws URISyntaxException {
- new JavaTestKit(system) {{
- ActorRef rpcRegistry = system.actorOf(RpcRegistry.props(Mockito.mock(ClusterWrapper.class)));
- QName type = new QName(new URI("actor1"), "actor1");
- RouteIdentifierImpl routeId = new RouteIdentifierImpl(null, type, null);
- final String route = "actor1";
-
- Set<RpcRouter.RouteIdentifier<?, ?, ?>> routeIds = new HashSet<>();
- routeIds.add(routeId);
-
- AddRoutedRpc rpcMsg = new AddRoutedRpc(routeIds, route);
- rpcRegistry.tell(rpcMsg, getRef());
- expectMsgEquals(duration("2 second"), "Success");
-
- GetRoutedRpc getRpc = new GetRoutedRpc(routeId);
- rpcRegistry.tell(getRpc, getRef());
-
- Boolean getMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
- protected Boolean match(Object in) {
- if (in instanceof GetRoutedRpcReply) {
- GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
- return route.equals(reply.getRoutePath());
- } else {
- throw noMatch();
- }
+ private void validateRouterReceived(List<Pair<ActorRef, Long>> actual, ActorRef expected){
+ Assert.assertTrue(actual != null);
+ Assert.assertTrue(actual.size() == 1);
+
+ for (Pair<ActorRef, Long> pair : actual){
+ Assert.assertTrue(expected.path().uid() == pair.first().path().uid());
}
- }.get(); // this extracts the received message
+ }
- Assert.assertTrue(getMsg);
+ private void validateSystemStartup() throws InterruptedException {
- RemoveRoutedRpc removeMsg = new RemoveRoutedRpc(routeIds, route);
- rpcRegistry.tell(removeMsg, getRef());
- expectMsgEquals(duration("2 second"), "Success");
+ Thread.sleep(5000);
+ ActorPath gossiper1Path = new ChildActorPath(new ChildActorPath(registry1.path(), "store"), "gossiper");
+ ActorPath gossiper2Path = new ChildActorPath(new ChildActorPath(registry2.path(), "store"), "gossiper");
+ ActorPath gossiper3Path = new ChildActorPath(new ChildActorPath(registry3.path(), "store"), "gossiper");
- rpcRegistry.tell(getRpc, getRef());
+ ActorSelection gossiper1 = node1.actorSelection(gossiper1Path);
+ ActorSelection gossiper2 = node2.actorSelection(gossiper2Path);
+ ActorSelection gossiper3 = node3.actorSelection(gossiper3Path);
- Boolean getNullMsg = new ExpectMsg<Boolean>("GetRoutedRpcReply") {
- protected Boolean match(Object in) {
- if (in instanceof GetRoutedRpcReply) {
- GetRoutedRpcReply reply = (GetRoutedRpcReply)in;
- return reply.getRoutePath() == null;
- } else {
- throw noMatch();
- }
- }
- }.get();
- Assert.assertTrue(getNullMsg);
- }};
- }
+ if (!resolveReference(gossiper1, gossiper2, gossiper3))
+ Assert.fail("Could not find gossipers");
+ }
-}
+ private Boolean resolveReference(ActorSelection... gossipers) throws InterruptedException {
+
+ Boolean resolved = true;
+
+ for (int i=0; i< 5; i++) {
+ Thread.sleep(1000);
+ for (ActorSelection gossiper : gossipers) {
+ Future<ActorRef> future = gossiper.resolveOne(new FiniteDuration(5000, TimeUnit.MILLISECONDS));
+
+ ActorRef ref = null;
+ try {
+ ref = Await.result(future, new FiniteDuration(10000, TimeUnit.MILLISECONDS));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ if (ref == null)
+ resolved = false;
+ }
+
+ if (resolved) break;
+ }
+ return resolved;
+ }
+
+ private AddOrUpdateRoute getAddRouteMessage() throws URISyntaxException {
+ return new AddOrUpdateRoute(createRouteId());
+ }
+
+ private RpcRouter.RouteIdentifier<?,?,?> createRouteId() throws URISyntaxException {
+ QName type = new QName(new URI("/mockrpc"), "mockrpc");
+ return new RouteIdentifierImpl(null, type, null);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.testkit.TestActorRef;
+import akka.testkit.TestProbe;
+import com.typesafe.config.ConfigFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.remote.rpc.TerminationMonitor;
+
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+
+public class BucketStoreTest {
+
+ private static ActorSystem system;
+ private static BucketStore store;
+
+ private BucketStore mockStore;
+
+ @BeforeClass
+ public static void setup() {
+
+ system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("unit-test"));
+ system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
+
+ store = createStore();
+ }
+
+ @AfterClass
+ public static void teardown() {
+ system.shutdown();
+ }
+
+ @Before
+ public void createMocks(){
+ mockStore = spy(store);
+ }
+
+ @After
+ public void resetMocks(){
+ reset(mockStore);
+ }
+
+ @Test
+ public void testReceiveUpdateBucket_WhenInputBucketShouldUpdateVersion(){
+ Bucket bucket = new BucketImpl();
+ Long expectedVersion = bucket.getVersion();
+
+ mockStore.receiveUpdateBucket(bucket);
+
+ Assert.assertEquals(bucket, mockStore.getLocalBucket());
+ Assert.assertEquals(expectedVersion, mockStore.getLocalBucket().getVersion());
+ }
+
+ /**
+ * Create BucketStore actor and returns the underlying instance of BucketStore class.
+ *
+ * @return instance of BucketStore class
+ */
+ private static BucketStore createStore(){
+ TestProbe mockActor = new TestProbe(system);
+ ActorRef mockGossiper = mockActor.ref();
+ final Props props = Props.create(BucketStore.class, mockGossiper);
+ final TestActorRef<BucketStore> testRef = TestActorRef.create(system, props, "testStore");
+
+ return testRef.underlyingActor();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.remote.rpc.registry.gossip;
+
+import akka.actor.ActorSystem;
+import akka.actor.Address;
+import akka.actor.Props;
+import akka.testkit.TestActorRef;
+import com.typesafe.config.ConfigFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.remote.rpc.TerminationMonitor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyMap;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipEnvelope;
+import static org.opendaylight.controller.remote.rpc.registry.gossip.Messages.GossiperMessages.GossipStatus;
+
+
+public class GossiperTest {
+
+ private static ActorSystem system;
+ private static Gossiper gossiper;
+
+ private Gossiper mockGossiper;
+
+ @BeforeClass
+ public static void setup() throws InterruptedException {
+ Thread.sleep(1000);//give some time for previous test to stop the system. Netty port conflict arises otherwise.
+ system = ActorSystem.create("opendaylight-rpc", ConfigFactory.load().getConfig("unit-test"));
+ system.actorOf(Props.create(TerminationMonitor.class), "termination-monitor");
+
+ gossiper = createGossiper();
+ }
+
+ @AfterClass
+ public static void teardown() {
+ if (system != null)
+ system.shutdown();
+ }
+
+ @Before
+ public void createMocks(){
+ mockGossiper = spy(gossiper);
+ }
+
+ @After
+ public void resetMocks(){
+ reset(mockGossiper);
+
+ }
+
+ @Test
+ public void testReceiveGossipTick_WhenNoRemoteMemberShouldIgnore(){
+
+ mockGossiper.setClusterMembers(Collections.EMPTY_LIST);
+ doNothing().when(mockGossiper).getLocalStatusAndSendTo(any(Address.class));
+ mockGossiper.receiveGossipTick();
+ verify(mockGossiper, times(0)).getLocalStatusAndSendTo(any(Address.class));
+ }
+
+ @Test
+ public void testReceiveGossipTick_WhenRemoteMemberExistsShouldSendStatus(){
+ List<Address> members = new ArrayList<>();
+ Address remote = new Address("tcp", "member");
+ members.add(remote);
+
+ mockGossiper.setClusterMembers(members);
+ doNothing().when(mockGossiper).getLocalStatusAndSendTo(any(Address.class));
+ mockGossiper.receiveGossipTick();
+ verify(mockGossiper, times(1)).getLocalStatusAndSendTo(any(Address.class));
+ }
+
+ @Test
+ public void testReceiveGossipStatus_WhenSenderIsNonMemberShouldIgnore(){
+
+ Address nonMember = new Address("tcp", "non-member");
+ GossipStatus remoteStatus = new GossipStatus(nonMember, mock(Map.class));
+
+ //add a member
+ List<Address> members = new ArrayList<>();
+ members.add(new Address("tcp", "member"));
+
+ mockGossiper.setClusterMembers(members);
+ mockGossiper.receiveGossipStatus(remoteStatus);
+ verify(mockGossiper, times(0)).getSender();
+ }
+
+ @Test
+ public void testReceiveGossip_WhenNotAddressedToSelfShouldIgnore(){
+ Address notSelf = new Address("tcp", "not-self");
+
+ GossipEnvelope envelope = new GossipEnvelope(notSelf, notSelf, mock(Map.class));
+ doNothing().when(mockGossiper).updateRemoteBuckets(anyMap());
+ mockGossiper.receiveGossip(envelope);
+ verify(mockGossiper, times(0)).updateRemoteBuckets(anyMap());
+ }
+
+ @Test
+ public void testUpdateRemoteBuckets_WhenNoBucketShouldIgnore(){
+
+ mockGossiper.updateRemoteBuckets(null);
+ verify(mockGossiper, times(0)).getContext();
+
+ Map<Address, Bucket> empty = Collections.emptyMap();
+ mockGossiper.updateRemoteBuckets(empty);
+ verify(mockGossiper, times(0)).getContext();
+ }
+
+ /**
+ * Create Gossiper actor and return the underlying instance of Gossiper class.
+ *
+ * @return instance of Gossiper class
+ */
+ private static Gossiper createGossiper(){
+
+ final Props props = Props.create(Gossiper.class, false);
+ final TestActorRef<Gossiper> testRef = TestActorRef.create(system, props, "testGossiper");
+
+ return testRef.underlyingActor();
+ }
+}
\ No newline at end of file
--- /dev/null
+odl-cluster{
+ akka {
+ loglevel = "INFO"
+ #log-config-on-start = on
+
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ debug{
+ #autoreceive = on
+ #lifecycle = on
+
+ }
+ }
+ remote {
+ log-received-messages = on
+ log-sent-messages = on
+
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "localhost"
+ port = 2551
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
+unit-test{
+ akka {
+ loglevel = "INFO"
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ }
+ }
+}
+
+memberA{
+ akka {
+ loglevel = "INFO"
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ }
+ remote {
+ log-received-messages = off
+ log-sent-messages = off
+
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "localhost"
+ port = 2551
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
+memberB{
+ akka {
+ loglevel = "INFO"
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ }
+ remote {
+ log-received-messages = off
+ log-sent-messages = off
+
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "localhost"
+ port = 2552
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
+memberC{
+ akka {
+ loglevel = "INFO"
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+ actor {
+ provider = "akka.cluster.ClusterActorRefProvider"
+ }
+ remote {
+ log-received-messages = off
+ log-sent-messages = off
+
+ log-remote-lifecycle-events = off
+ netty.tcp {
+ hostname = "localhost"
+ port = 2553
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-rpc@localhost:2551"]
+
+ auto-down-unreachable-after = 10s
+ }
+ }
+}
\ No newline at end of file
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import java.io.UnsupportedEncodingException;
private static final Splitter SLASH_SPLITTER = Splitter.on('/');
- private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
-
- private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
-
private final AtomicReference<Map<QName, RpcDefinition>> qnameToRpc =
new AtomicReference<>(Collections.<QName, RpcDefinition>emptyMap());
public String findModuleNameByNamespace(final URI namespace) {
this.checkPreconditions();
- String moduleName = this.uriToModuleName.get(namespace);
- if (moduleName == null) {
- final Module module = this.findModuleByNamespace(namespace);
- if (module != null) {
- moduleName = module.getName();
- this.uriToModuleName.put(namespace, moduleName);
- }
- }
-
- return moduleName;
+ final Module module = this.findModuleByNamespace(namespace);
+ return module == null ? null : module.getName();
}
public String findModuleNameByNamespace(final DOMMountPoint mountPoint, final URI namespace) {
}
public URI findNamespaceByModuleName(final String moduleName) {
- URI namespace = this.moduleNameToUri.get(moduleName);
- if (namespace == null) {
- Module module = this.findModuleByName(moduleName);
- if (module != null) {
- URI _namespace = module.getNamespace();
- namespace = _namespace;
- this.uriToModuleName.put(namespace, moduleName);
- }
- }
- return namespace;
+ final Module module = this.findModuleByName(moduleName);
+ return module == null ? null : module.getNamespace();
}
public URI findNamespaceByModuleName(final DOMMountPoint mountPoint, final String moduleName) {
return globalSchema.getModules();
}
+ private static final CharSequence toRestconfIdentifier(final SchemaContext context, final QName qname) {
+ final Module schema = context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+ return schema == null ? null : schema.getName() + ':' + qname.getLocalName();
+ }
+
public CharSequence toRestconfIdentifier(final QName qname) {
this.checkPreconditions();
- String module = this.uriToModuleName.get(qname.getNamespace());
- if (module == null) {
- final Module moduleSchema = globalSchema.findModuleByNamespaceAndRevision(qname.getNamespace(),
- qname.getRevision());
- if (moduleSchema == null) {
- return null;
- }
-
- this.uriToModuleName.put(qname.getNamespace(), moduleSchema.getName());
- module = moduleSchema.getName();
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append(module);
- builder.append(":");
- builder.append(qname.getLocalName());
- return builder.toString();
+ return toRestconfIdentifier(globalSchema, qname);
}
public CharSequence toRestconfIdentifier(final DOMMountPoint mountPoint, final QName qname) {
return null;
}
- SchemaContext schemaContext = mountPoint.getSchemaContext();
-
- final Module moduleSchema = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
- qname.getRevision());
- if (moduleSchema == null) {
- return null;
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append(moduleSchema.getName());
- builder.append(":");
- builder.append(qname.getLocalName());
- return builder.toString();
+ return toRestconfIdentifier(mountPoint.getSchemaContext(), qname);
}
public Module getRestconfModule() {
final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
- List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+ List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
Draft02.RestConfModule.ERRORS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instanceDataChildrenByName, null);
}
Iterable<GroupingDefinition> filteredGroups = Iterables.filter(groupings, GROUPING_FILTER);
final GroupingDefinition restconfGrouping = Iterables.getFirst(filteredGroups, null);
- List<DataSchemaNode> instanceDataChildrenByName = this.findInstanceDataChildrenByName(restconfGrouping,
+ List<DataSchemaNode> instanceDataChildrenByName = findInstanceDataChildrenByName(restconfGrouping,
Draft02.RestConfModule.RESTCONF_CONTAINER_SCHEMA_NODE);
final DataSchemaNode restconfContainer = Iterables.getFirst(instanceDataChildrenByName, null);
if (Objects.equal(schemaNodeName, Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.OPERATIONS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
final DataSchemaNode modules = Iterables.getFirst(instances, null);
- instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
Draft02.RestConfModule.STREAM_LIST_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.MODULES_CONTAINER_SCHEMA_NODE);
final DataSchemaNode modules = Iterables.getFirst(instances, null);
- instances = this.findInstanceDataChildrenByName(((DataNodeContainer) modules),
+ instances = findInstanceDataChildrenByName(((DataNodeContainer) modules),
Draft02.RestConfModule.MODULE_LIST_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
} else if (Objects.equal(schemaNodeName, Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE)) {
- List<DataSchemaNode> instances = this.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instances = findInstanceDataChildrenByName(
((DataNodeContainer) restconfContainer), Draft02.RestConfModule.STREAMS_CONTAINER_SCHEMA_NODE);
return Iterables.getFirst(instances, null);
}
}
}
- targetNode = this.findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
+ targetNode = findInstanceDataChildByNameAndNamespace(parentNode, nodeName, module.getNamespace());
if (targetNode == null) {
throw new RestconfDocumentedException("URI has bad format. Possible reasons:\n" + " 1. \"" + head
+ "\" was not found in parent data node.\n" + " 2. \"" + head
ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
}
} else {
- final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(parentNode, nodeName);
+ final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(parentNode, nodeName);
if (potentialSchemaNodes.size() > 1) {
final StringBuilder strBuilder = new StringBuilder();
for (final DataSchemaNode potentialNodeSchema : potentialSchemaNodes) {
return new InstanceIdWithSchemaNode(builder.toInstance(), targetNode, mountPoint);
}
- public DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
+ public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
final URI namespace) {
Preconditions.<URI> checkNotNull(namespace);
- final List<DataSchemaNode> potentialSchemaNodes = this.findInstanceDataChildrenByName(container, name);
+ final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(container, name);
Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
@Override
return Iterables.getFirst(result, null);
}
- public List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
+ public static List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
Preconditions.<DataNodeContainer> checkNotNull(container);
Preconditions.<String> checkNotNull(name);
List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
- this.collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
+ collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
return instantiatedDataNodeContainers;
}
}
};
- private void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
+ private static void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
final DataNodeContainer container, final String name) {
Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
// Can't combine this loop with the filter above because the filter is
// lazily-applied by Iterables.filter.
for (final DataSchemaNode potentialNode : nodes) {
- if (this.isInstantiatedDataSchema(potentialNode)) {
+ if (isInstantiatedDataSchema(potentialNode)) {
potentialSchemaNodes.add(potentialNode);
}
}
final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat(map);
for (final ChoiceCaseNode caze : allCases) {
- this.collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
+ collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
}
}
- public boolean isInstantiatedDataSchema(final DataSchemaNode node) {
+ public static boolean isInstantiatedDataSchema(final DataSchemaNode node) {
return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode
|| node instanceof ContainerSchemaNode || node instanceof ListSchemaNode
|| node instanceof AnyXmlSchemaNode;
}
private CharSequence convertToRestconfIdentifier(final NodeIdentifier argument, final ContainerSchemaNode node) {
- StringBuilder builder = new StringBuilder();
- builder.append("/");
- QName nodeType = argument.getNodeType();
- builder.append(this.toRestconfIdentifier(nodeType));
- return builder.toString();
+ return "/" + this.toRestconfIdentifier(argument.getNodeType());
}
private CharSequence convertToRestconfIdentifier(final NodeIdentifierWithPredicates argument,
final Map<QName, Object> keyValues = argument.getKeyValues();
StringBuilder builder = new StringBuilder();
- builder.append("/");
+ builder.append('/');
builder.append(nodeIdentifier);
- builder.append("/");
+ builder.append('/');
List<QName> keyDefinition = node.getKeyDefinition();
boolean hasElements = false;
if (!hasElements) {
hasElements = true;
} else {
- builder.append("/");
+ builder.append('/');
}
try {
for (int i = 0; i < identities.size(); i++) {
IdentityValue identityValue = identities.get(i);
URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint);
- DataSchemaNode node = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace(
+ DataSchemaNode node = ControllerContext.findInstanceDataChildByNameAndNamespace(
parentContainer, identityValue.getValue(), validNamespace);
if (node == null) {
logger.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
Map<QName, Object> predicatesMap = new HashMap<>();
for (Predicate predicate : identityValue.getPredicates()) {
validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint);
- DataSchemaNode listKey = ControllerContext.getInstance()
+ DataSchemaNode listKey = ControllerContext
.findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
validNamespace);
predicatesMap.put(listKey.getQName(), predicate.getValue());
}
result.add(pathArgument);
if (i < identities.size() - 1) { // last element in instance-identifier can be other than
- // DataNodeContainer
+ // DataNodeContainer
if (node instanceof DataNodeContainer) {
parentContainer = (DataNodeContainer) node;
} else {
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
-import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.serializer.CnSnFromNormalizedNodeSerializerFactory;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
private CompositeNode toStreamCompositeNode(final String streamName, final DataSchemaNode streamSchemaNode) {
final List<Node<?>> streamNodeValues = new ArrayList<Node<?>>();
- List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "name");
final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues
- .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
+ .add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null, streamName));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "description");
final DataSchemaNode descriptionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(descriptionSchemaNode.getQName(), null,
"DESCRIPTION_PLACEHOLDER"));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "replay-support");
final DataSchemaNode replaySupportSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<Boolean> createImmutableSimpleNode(replaySupportSchemaNode.getQName(), null,
Boolean.valueOf(true)));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "replay-log-creation-time");
final DataSchemaNode replayLogCreationTimeSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(replayLogCreationTimeSchemaNode.getQName(),
null, ""));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) streamSchemaNode), "events");
final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
streamNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(eventsSchemaNode.getQName(), null, ""));
private CompositeNode toModuleCompositeNode(final Module module, final DataSchemaNode moduleSchemaNode) {
final List<Node<?>> moduleNodeValues = new ArrayList<Node<?>>();
- List<DataSchemaNode> instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ List<DataSchemaNode> instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "name");
final DataSchemaNode nameSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(nameSchemaNode.getQName(), null,
module.getName()));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "revision");
final DataSchemaNode revisionSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
Date _revision = module.getRevision();
moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(revisionSchemaNode.getQName(), null,
REVISION_FORMAT.format(_revision)));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "namespace");
final DataSchemaNode namespaceSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
moduleNodeValues.add(NodeFactory.<String> createImmutableSimpleNode(namespaceSchemaNode.getQName(), null,
module.getNamespace().toString()));
- instanceDataChildrenByName = this.controllerContext.findInstanceDataChildrenByName(
+ instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(
((DataNodeContainer) moduleSchemaNode), "feature");
final DataSchemaNode featureSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
for (final FeatureDefinition feature : module.getFeatures()) {
NormalizedNode<?, ?> data = null;
YangInstanceIdentifier normalizedII;
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+ normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
+ .getInstanceIdentifier());
data = broker.readConfigurationData(mountPoint, normalizedII);
} else {
normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
NormalizedNode<?, ?> data = null;
YangInstanceIdentifier normalizedII;
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+ normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
+ .getInstanceIdentifier());
data = broker.readOperationalData(mountPoint, normalizedII);
} else {
normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
try {
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+ normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
+ .getInstanceIdentifier());
broker.commitConfigurationDataPut(mountPoint, normalizedII, datastoreNormalizedNode).get();
} else {
normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
}
String payloadName = this.getName(payload);
- final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(
+ final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(
parentSchema, payloadName, module.getNamespace());
value = this.normalizeNode(payload, schemaNode, mountPoint);
try {
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+ normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
+ .getInstanceIdentifier());
broker.commitConfigurationDataPost(mountPoint, normalizedII, datastoreNormalizedData);
} else {
normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
}
String payloadName = this.getName(payload);
- final DataSchemaNode schemaNode = this.controllerContext.findInstanceDataChildByNameAndNamespace(module,
+ final DataSchemaNode schemaNode = ControllerContext.findInstanceDataChildByNameAndNamespace(module,
payloadName, module.getNamespace());
final CompositeNode value = this.normalizeNode(payload, schemaNode, null);
final InstanceIdWithSchemaNode iiWithData = this.addLastIdentifierFromData(null, value, schemaNode);
try {
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+ normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
+ .getInstanceIdentifier());
broker.commitConfigurationDataPost(mountPoint, normalizedII, datastoreNormalizedData);
} else {
try {
if (mountPoint != null) {
- normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData.getInstanceIdentifier());
+ normalizedII = new DataNormalizer(mountPoint.getSchemaContext()).toNormalized(iiWithData
+ .getInstanceIdentifier());
broker.commitConfigurationDataDelete(mountPoint, normalizedII);
} else {
normalizedII = controllerContext.toNormalized(iiWithData.getInstanceIdentifier());
iiBuilder = YangInstanceIdentifier.builder(iiOriginal);
}
- iiBuilder.node(schemaOfData.getQName());
+ if ((schemaOfData instanceof ListSchemaNode)) {
+ HashMap<QName, Object> keys = this.resolveKeysFromData(((ListSchemaNode) schemaOfData), data);
+ iiBuilder.nodeWithKey(schemaOfData.getQName(), keys);
+ } else {
+ iiBuilder.node(schemaOfData.getQName());
+ }
YangInstanceIdentifier instance = iiBuilder.toInstance();
DOMMountPoint mountPoint = null;
return new InstanceIdWithSchemaNode(instance, schemaOfData, mountPoint);
}
+ private HashMap<QName, Object> resolveKeysFromData(final ListSchemaNode listNode, final CompositeNode dataNode) {
+ final HashMap<QName, Object> keyValues = new HashMap<QName, Object>();
+ List<QName> _keyDefinition = listNode.getKeyDefinition();
+ for (final QName key : _keyDefinition) {
+ SimpleNode<? extends Object> head = null;
+ String localName = key.getLocalName();
+ List<SimpleNode<? extends Object>> simpleNodesByName = dataNode.getSimpleNodesByName(localName);
+ if (simpleNodesByName != null) {
+ head = Iterables.getFirst(simpleNodesByName, null);
+ }
+
+ Object dataNodeKeyValueObject = null;
+ if (head != null) {
+ dataNodeKeyValueObject = head.getValue();
+ }
+
+ if (dataNodeKeyValueObject == null) {
+ throw new RestconfDocumentedException("Data contains list \"" + dataNode.getNodeType().getLocalName()
+ + "\" which does not contain key: \"" + key.getLocalName() + "\"", ErrorType.PROTOCOL,
+ ErrorTag.INVALID_VALUE);
+ }
+
+ keyValues.put(key, dataNodeKeyValueObject);
+ }
+
+ return keyValues;
+ }
+
private boolean endsWithMountPoint(final String identifier) {
return identifier.endsWith(ControllerContext.MOUNT) || identifier.endsWith(ControllerContext.MOUNT + "/");
}
private boolean representsMountPointRootData(final Node<?> data) {
URI namespace = this.namespace(data);
return (SchemaContext.NAME.getNamespace().equals(namespace) /*
- * || MOUNT_POINT_MODULE_NAME .equals( namespace .
- * toString( ) )
- */)
- && SchemaContext.NAME.getLocalName().equals(this.localName(data));
+ * || MOUNT_POINT_MODULE_NAME .equals( namespace .
+ * toString( ) )
+ */)
+ && SchemaContext.NAME.getLocalName().equals(this.localName(data));
}
private String addMountPointIdentifier(final String identifier) {
final List<NodeWrapper<?>> children = compositeNodeBuilder.getValues();
checkNodeMultiplicityAccordingToSchema(schema, children);
for (final NodeWrapper<? extends Object> child : children) {
- final List<DataSchemaNode> potentialSchemaNodes = this.controllerContext.findInstanceDataChildrenByName(
+ final List<DataSchemaNode> potentialSchemaNodes = ControllerContext.findInstanceDataChildrenByName(
schema, child.getLocalName());
if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) {
}
if (nodeBuilder.getNamespace() == null || Objects.equal(nodeBuilder.getNamespace(), validQName.getNamespace())
- || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName) /*
- * || Note : this check is wrong -
- * can never be true as it compares
- * a URI with a String not sure what
- * the intention is so commented out
- * ... Objects . equal ( nodeBuilder
- * . getNamespace ( ) ,
- * MOUNT_POINT_MODULE_NAME )
- */) {
+ || Objects.equal(nodeBuilder.getNamespace().toString(), moduleName)) {
+ /*
+ * || Note : this check is wrong -
+ * can never be true as it compares
+ * a URI with a String not sure what
+ * the intention is so commented out
+ * ... Objects . equal ( nodeBuilder
+ * . getNamespace ( ) ,
+ * MOUNT_POINT_MODULE_NAME )
+ */
nodeBuilder.setQname(validQName);
}
}
private CompositeNode datastoreNormalizedNodeToCompositeNode(final NormalizedNode<?, ?> dataNode, final DataSchemaNode schema) {
- Iterable<Node<?>> nodes = null;
+ Node<?> nodes = null;
if (dataNode == null) {
throw new RestconfDocumentedException(new RestconfError(ErrorType.APPLICATION, ErrorTag.DATA_MISSING,
"No data was found."));
}
- if (schema instanceof ContainerSchemaNode && dataNode instanceof ContainerNode) {
- nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getContainerNodeSerializer()
- .serialize((ContainerSchemaNode) schema, (ContainerNode) dataNode);
- } else if (schema instanceof ListSchemaNode && dataNode instanceof MapNode) {
- nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getMapNodeSerializer()
- .serialize((ListSchemaNode) schema, (MapNode) dataNode);
- } else if (schema instanceof ListSchemaNode && dataNode instanceof MapEntryNode) {
- nodes = CnSnFromNormalizedNodeSerializerFactory.getInstance().getMapEntryNodeSerializer()
- .serialize((ListSchemaNode) schema, (MapEntryNode) dataNode);
- }
+ nodes = DataNormalizer.toLegacy(dataNode);
if (nodes != null) {
- if (nodes.iterator().hasNext()) {
- Node<?> nodeOldStruct = nodes.iterator().next();
- return (CompositeNode) nodeOldStruct;
+ if (nodes instanceof CompositeNode) {
+ return (CompositeNode) nodes;
} else {
LOG.error("The node " + dataNode.getNodeType() + " couldn't be transformed to compositenode.");
}
"It wasn't possible to correctly interpret data."));
}
- private NormalizedNode<?, ?> compositeNodeToDatastoreNormalizedNode(final CompositeNode compNode, final DataSchemaNode schema) {
+ private NormalizedNode<?, ?> compositeNodeToDatastoreNormalizedNode(final CompositeNode compNode,
+ final DataSchemaNode schema) {
List<Node<?>> lst = new ArrayList<Node<?>>();
lst.add(compNode);
if (schema instanceof ContainerSchemaNode) {
"It wasn't possible to translate specified data to datastore readable form."));
}
- private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode(final InstanceIdWithSchemaNode iiWithSchemaNode) {
+ private InstanceIdWithSchemaNode normalizeInstanceIdentifierWithSchemaNode(
+ final InstanceIdWithSchemaNode iiWithSchemaNode) {
return normalizeInstanceIdentifierWithSchemaNode(iiWithSchemaNode, false);
}
iiWithSchemaNode.getMountPoint());
}
- private YangInstanceIdentifier instanceIdentifierToReadableFormForNormalizeNode(final YangInstanceIdentifier instIdentifier,
- final boolean unwrapLastListNode) {
+ private YangInstanceIdentifier instanceIdentifierToReadableFormForNormalizeNode(
+ final YangInstanceIdentifier instIdentifier, final boolean unwrapLastListNode) {
Preconditions.checkNotNull(instIdentifier, "Instance identifier can't be null");
final List<PathArgument> result = new ArrayList<PathArgument>();
final Iterator<PathArgument> iter = instIdentifier.getPathArguments().iterator();
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
}
private NormalizedNode prepareCnDataForSlashesBehindMountPointTest() throws ParseException {
- CollectionNodeBuilder<MapEntryNode, MapNode> lst1 = ImmutableMapNodeBuilder.create();
- lst1.withNodeIdentifier(TestUtils.getNodeIdentifier("lst1", "test:module", "2014-01-09"));
- lst1.withChild(ImmutableMapEntryNodeBuilder
+ return ImmutableMapEntryNodeBuilder
.create()
.withNodeIdentifier(
TestUtils.getNodeIdentifierPredicate("lst1", "test:module", "2014-01-09", "lf11",
.withChild(
ImmutableLeafNodeBuilder.create()
.withNodeIdentifier(TestUtils.getNodeIdentifier("lf11", "test:module", "2014-01-09"))
- .withValue("GigabitEthernet0/0/0/0").build()).build());
+ .withValue("GigabitEthernet0/0/0/0").build()).build();
- return lst1.build();
}
/**
expectLeaf("depth3-leaf1", "depth3-leaf1-value")));
}
+ /**
+ * Tests behavior when invalid value of depth URI parameter
+ */
@Test
public void getDataWithInvalidDepthParameterTest() {
private void getDataWithInvalidDepthParameterTest(final UriInfo uriInfo) {
try {
+ QName qNameDepth1Cont = QName.create("urn:nested:module", "2014-06-3", "depth1-cont");
+ YangInstanceIdentifier ii = YangInstanceIdentifier.builder().node(qNameDepth1Cont).build();
+ NormalizedNode value = (NormalizedNode<?,?>)(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(qNameDepth1Cont)).build());
+ when(brokerFacade.readConfigurationData(eq(ii))).thenReturn(value);
restconfImpl.readConfigurationData("nested-module:depth1-cont", uriInfo);
fail("Expected RestconfDocumentedException");
} catch (RestconfDocumentedException e) {
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
static NormalizedNode prepareNormalizedNodeWithIetfInterfacesInterfacesData() throws ParseException {
String ietfInterfacesDate = "2013-07-04";
- CollectionNodeBuilder<MapEntryNode, MapNode> intface = ImmutableMapNodeBuilder.create();
String namespace = "urn:ietf:params:xml:ns:yang:ietf-interfaces";
- intface.withNodeIdentifier(getNodeIdentifier("interface", namespace, ietfInterfacesDate));
DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryNode = ImmutableMapEntryNodeBuilder.create();
Map<String, Object> predicates = new HashMap<>();
.withNodeIdentifier(getNodeIdentifier("description", namespace, ietfInterfacesDate))
.withValue("some interface").build());
- intface.withChild(mapEntryNode.build());
-
- return intface.build();
+ return mapEntryNode.build();
}
}
*/
package org.opendaylight.controller.md.sal.test.model.util;
-import java.util.Arrays;
-
+import com.google.common.collect.ImmutableList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
public class ListsBindingUtils {
return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
}
+ public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+ return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+ }
+
}
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-base</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller.model</groupId>
<artifactId>model-flow-service</artifactId>
LinkedHashMap<ConfigSnapshotHolder, EditAndCommitResponse> result = new LinkedHashMap<>();
// start pushing snapshots:
for (ConfigSnapshotHolder configSnapshotHolder : configs) {
- EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
- logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
- result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+ if(configSnapshotHolder != null) {
+ EditAndCommitResponse editAndCommitResponseWithRetries = pushConfigWithConflictingVersionRetries(configSnapshotHolder);
+ logger.debug("Config snapshot pushed successfully: {}, result: {}", configSnapshotHolder, result);
+ result.put(configSnapshotHolder, editAndCommitResponseWithRetries);
+ }
}
logger.debug("All configuration snapshots have been pushed successfully.");
return result;
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
- <!-- <version>0.6.2-SNAPSHOT</version>-->
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-data-json</artifactId>
- <version>0.6.2-SNAPSHOT</version>
+ <artifactId>yang-data-composite-node</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher;
import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
-import org.opendaylight.yangtools.yang.data.json.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.composite.node.schema.cnsn.parser.CnSnToNormalizedNodeParserFactory;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
<build>
<plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <forkCount>1</forkCount>
- <reuseForks>false</reuseForks>
- <perCoreThreadCount>false</perCoreThreadCount>
- </configuration>
- <executions>
- <execution>
- <id>default-test</id>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- <execution>
- <id>integration-tests</id>
- <goals>
- <goal>test</goal>
- </goals>
- <phase>integration-test</phase>
- <configuration>
- <skip>false</skip>
- <argLine>-Dlogback.configurationFile=${maven.test.dest}/logback.xml</argLine>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>maven-paxexam-plugin</artifactId>
import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallPolicyCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronFirewallRuleCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerHealthMonitorCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerListenerCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
NeutronSecurityRuleInterface.class,
NeutronFirewallInterface.class,
NeutronFirewallPolicyInterface.class,
- NeutronFirewallRuleInterface.class};
+ NeutronFirewallRuleInterface.class,
+ NeutronLoadBalancerInterface.class,
+ NeutronLoadBalancerPoolInterface.class,
+ NeutronLoadBalancerListenerInterface.class,
+ NeutronLoadBalancerHealthMonitorInterface.class,
+ NeutronLoadBalancerPoolMemberInterface.class};
return res;
}
"setConfigurationContainerService",
"unsetConfigurationContainerService").setRequired(true));
}
+ if (imp.equals(NeutronLoadBalancerInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronLoadBalancerCRUD.class.getName(),
+ IConfigurationContainerAware.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));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronLoadBalancerListenerInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronLoadBalancerListenerCRUD.class.getName(),
+ IConfigurationContainerAware.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));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronLoadBalancerPoolInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronLoadBalancerPoolCRUD.class.getName(),
+ IConfigurationContainerAware.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));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronLoadBalancerHealthMonitorInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronLoadBalancerHealthMonitorCRUD.class.getName(),
+ IConfigurationContainerAware.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));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
+ if (imp.equals(NeutronLoadBalancerPoolMemberInterface.class)) {
+ // export the service
+ c.setInterface(
+ new String[] { INeutronLoadBalancerPoolMemberCRUD.class.getName(),
+ IConfigurationContainerAware.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));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
+ }
}
}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 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.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerHealthMonitorCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerHealthMonitor;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+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.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronLoadBalancerHealthMonitorInterface implements INeutronLoadBalancerHealthMonitorCRUD, IConfigurationContainerAware,
+ IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancerHealthMonitorInterface.class);
+ private static final String FILE_NAME = "neutron.loadBalancerHealthMonitor.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronLoadBalancerHealthMonitor> loadBalancerHealthMonitorDB;
+
+ // 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;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron LoadBalancerHealthMonitor");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronLoadBalancerHealthMonitors",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron LoadBalancerHealthMonitor - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron LoadBalancerHealthMonitor already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron LoadBalancerHealthMonitor");
+ }
+
+ @SuppressWarnings ({"unchecked"})
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron LoadBalancerHealthMonitor");
+ loadBalancerHealthMonitorDB = (ConcurrentMap<String, NeutronLoadBalancerHealthMonitor>) clusterContainerService
+ .getCache("neutronLoadBalancerHealthMonitors");
+ if (loadBalancerHealthMonitorDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron LoadBalancerHealthMonitor");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron LoadBalancerHealthMonitor");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for LoadBalancerHealthMonitor");
+ clusterContainerService.destroyCache("neutronLoadBalancerHealthMonitors");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public boolean neutronLoadBalancerHealthMonitorExists(String uuid) {
+ return loadBalancerHealthMonitorDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronLoadBalancerHealthMonitor getNeutronLoadBalancerHealthMonitor(String uuid) {
+ if (!neutronLoadBalancerHealthMonitorExists(uuid)) {
+ logger.debug("No LoadBalancerHealthMonitor has Been Defined");
+ return null;
+ }
+ return loadBalancerHealthMonitorDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronLoadBalancerHealthMonitor> getAllNeutronLoadBalancerHealthMonitors() {
+ Set<NeutronLoadBalancerHealthMonitor> allLoadBalancerHealthMonitors = new HashSet<NeutronLoadBalancerHealthMonitor>();
+ for (Entry<String, NeutronLoadBalancerHealthMonitor> entry : loadBalancerHealthMonitorDB.entrySet()) {
+ NeutronLoadBalancerHealthMonitor loadBalancerHealthMonitor = entry.getValue();
+ allLoadBalancerHealthMonitors.add(loadBalancerHealthMonitor);
+ }
+ logger.debug("Exiting getLoadBalancerHealthMonitors, Found {} OpenStackLoadBalancerHealthMonitor", allLoadBalancerHealthMonitors.size());
+ List<NeutronLoadBalancerHealthMonitor> ans = new ArrayList<NeutronLoadBalancerHealthMonitor>();
+ ans.addAll(allLoadBalancerHealthMonitors);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronLoadBalancerHealthMonitor(NeutronLoadBalancerHealthMonitor input) {
+ if (neutronLoadBalancerHealthMonitorExists(input.getLoadBalancerHealthMonitorID())) {
+ return false;
+ }
+ loadBalancerHealthMonitorDB.putIfAbsent(input.getLoadBalancerHealthMonitorID(), input);
+ //TODO: add code to find INeutronLoadBalancerHealthMonitorAware services and call newtorkCreated on them
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronLoadBalancerHealthMonitor(String uuid) {
+ if (!neutronLoadBalancerHealthMonitorExists(uuid)) {
+ return false;
+ }
+ loadBalancerHealthMonitorDB.remove(uuid);
+ //TODO: add code to find INeutronLoadBalancerHealthMonitorAware services and call newtorkDeleted on them
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronLoadBalancerHealthMonitor(String uuid, NeutronLoadBalancerHealthMonitor delta) {
+ if (!neutronLoadBalancerHealthMonitorExists(uuid)) {
+ return false;
+ }
+ NeutronLoadBalancerHealthMonitor target = loadBalancerHealthMonitorDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronLoadBalancerHealthMonitorInUse(String loadBalancerHealthMonitorUUID) {
+ return !neutronLoadBalancerHealthMonitorExists(loadBalancerHealthMonitorUUID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronLoadBalancerHealthMonitor nn = (NeutronLoadBalancerHealthMonitor) conf;
+ loadBalancerHealthMonitorDB.put(nn.getLoadBalancerHealthMonitorID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(loadBalancerHealthMonitorDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 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.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+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.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronLoadBalancerInterface implements INeutronLoadBalancerCRUD, IConfigurationContainerAware,
+ IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancerInterface.class);
+ private static final String FILE_NAME = "neutron.loadBalancer.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronLoadBalancer> loadBalancerDB;
+
+ // 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;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron LoadBalancer");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronLoadBalancers",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron LoadBalancer - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron LoadBalancer already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron LoadBalancer");
+ }
+
+ @SuppressWarnings ({"unchecked"})
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron LoadBalancer");
+ loadBalancerDB = (ConcurrentMap<String, NeutronLoadBalancer>) clusterContainerService
+ .getCache("neutronLoadBalancers");
+ if (loadBalancerDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron LoadBalancer");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron LoadBalancer");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for LoadBalancer");
+ clusterContainerService.destroyCache("neutronLoadBalancers");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public boolean neutronLoadBalancerExists(String uuid) {
+ return loadBalancerDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronLoadBalancer getNeutronLoadBalancer(String uuid) {
+ if (!neutronLoadBalancerExists(uuid)) {
+ logger.debug("No LoadBalancer Have Been Defined");
+ return null;
+ }
+ return loadBalancerDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronLoadBalancer> getAllNeutronLoadBalancers() {
+ Set<NeutronLoadBalancer> allLoadBalancers = new HashSet<NeutronLoadBalancer>();
+ for (Entry<String, NeutronLoadBalancer> entry : loadBalancerDB.entrySet()) {
+ NeutronLoadBalancer loadBalancer = entry.getValue();
+ allLoadBalancers.add(loadBalancer);
+ }
+ logger.debug("Exiting getLoadBalancers, Found {} OpenStackLoadBalancer", allLoadBalancers.size());
+ List<NeutronLoadBalancer> ans = new ArrayList<NeutronLoadBalancer>();
+ ans.addAll(allLoadBalancers);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronLoadBalancer(NeutronLoadBalancer input) {
+ if (neutronLoadBalancerExists(input.getLoadBalancerID())) {
+ return false;
+ }
+ loadBalancerDB.putIfAbsent(input.getLoadBalancerID(), input);
+ //TODO: add code to find INeutronLoadBalancerAware services and call newtorkCreated on them
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronLoadBalancer(String uuid) {
+ if (!neutronLoadBalancerExists(uuid)) {
+ return false;
+ }
+ loadBalancerDB.remove(uuid);
+ //TODO: add code to find INeutronLoadBalancerAware services and call newtorkDeleted on them
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronLoadBalancer(String uuid, NeutronLoadBalancer delta) {
+ if (!neutronLoadBalancerExists(uuid)) {
+ return false;
+ }
+ NeutronLoadBalancer target = loadBalancerDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronLoadBalancerInUse(String loadBalancerUUID) {
+ return !neutronLoadBalancerExists(loadBalancerUUID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronLoadBalancer nn = (NeutronLoadBalancer) conf;
+ loadBalancerDB.put(nn.getLoadBalancerID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(loadBalancerDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 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.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerListenerCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerListener;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+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.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronLoadBalancerListenerInterface implements INeutronLoadBalancerListenerCRUD, IConfigurationContainerAware,
+ IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancerListenerInterface.class);
+ private static final String FILE_NAME = "neutron.loadBalancerListener.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronLoadBalancerListener> loadBalancerListenerDB;
+
+ // 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;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron LoadBalancerListener");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronLoadBalancerListeners",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron LoadBalancerListener - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron LoadBalancerListener already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron LoadBalancerListener");
+ }
+
+ @SuppressWarnings ({"unchecked"})
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron LoadBalancerListener");
+ loadBalancerListenerDB = (ConcurrentMap<String, NeutronLoadBalancerListener>) clusterContainerService
+ .getCache("neutronLoadBalancerListeners");
+ if (loadBalancerListenerDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron LoadBalancerListener");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron LoadBalancerListener");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for LoadBalancerListener");
+ clusterContainerService.destroyCache("neutronLoadBalancerListeners");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public boolean neutronLoadBalancerListenerExists(String uuid) {
+ return loadBalancerListenerDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronLoadBalancerListener getNeutronLoadBalancerListener(String uuid) {
+ if (!neutronLoadBalancerListenerExists(uuid)) {
+ logger.debug("No LoadBalancerListener Have Been Defined");
+ return null;
+ }
+ return loadBalancerListenerDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronLoadBalancerListener> getAllNeutronLoadBalancerListeners() {
+ Set<NeutronLoadBalancerListener> allLoadBalancerListeners = new HashSet<NeutronLoadBalancerListener>();
+ for (Entry<String, NeutronLoadBalancerListener> entry : loadBalancerListenerDB.entrySet()) {
+ NeutronLoadBalancerListener loadBalancerListener = entry.getValue();
+ allLoadBalancerListeners.add(loadBalancerListener);
+ }
+ logger.debug("Exiting getLoadBalancerListeners, Found {} OpenStackLoadBalancerListener", allLoadBalancerListeners.size());
+ List<NeutronLoadBalancerListener> ans = new ArrayList<NeutronLoadBalancerListener>();
+ ans.addAll(allLoadBalancerListeners);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronLoadBalancerListener(NeutronLoadBalancerListener input) {
+ if (neutronLoadBalancerListenerExists(input.getLoadBalancerListenerID())) {
+ return false;
+ }
+ loadBalancerListenerDB.putIfAbsent(input.getLoadBalancerListenerID(), input);
+ //TODO: add code to find INeutronLoadBalancerListenerAware services and call newtorkCreated on them
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronLoadBalancerListener(String uuid) {
+ if (!neutronLoadBalancerListenerExists(uuid)) {
+ return false;
+ }
+ loadBalancerListenerDB.remove(uuid);
+ //TODO: add code to find INeutronLoadBalancerListenerAware services and call newtorkDeleted on them
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronLoadBalancerListener(String uuid, NeutronLoadBalancerListener delta) {
+ if (!neutronLoadBalancerListenerExists(uuid)) {
+ return false;
+ }
+ NeutronLoadBalancerListener target = loadBalancerListenerDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronLoadBalancerListenerInUse(String loadBalancerListenerUUID) {
+ return !neutronLoadBalancerListenerExists(loadBalancerListenerUUID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronLoadBalancerListener nn = (NeutronLoadBalancerListener) conf;
+ loadBalancerListenerDB.put(nn.getLoadBalancerListenerID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(loadBalancerListenerDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 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.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+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.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronLoadBalancerPoolInterface implements INeutronLoadBalancerPoolCRUD, IConfigurationContainerAware,
+ IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancerPoolInterface.class);
+ private static final String FILE_NAME = "neutron.loadBalancerPool.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronLoadBalancerPool> loadBalancerPoolDB;
+
+ // 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;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron LoadBalancerPool");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronLoadBalancerPools",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron LoadBalancerPool - check cache mode");
+ } catch (CacheExistException cce) {
+ logger.error("Cache for Neutron LoadBalancerPool already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron LoadBalancerPool");
+ }
+
+ @SuppressWarnings ({"unchecked"})
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron LoadBalancerPool");
+ loadBalancerPoolDB = (ConcurrentMap<String, NeutronLoadBalancerPool>) clusterContainerService
+ .getCache("neutronLoadBalancerPools");
+ if (loadBalancerPoolDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron LoadBalancerPool");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron LoadBalancerPool");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for LoadBalancerPool");
+ clusterContainerService.destroyCache("neutronLoadBalancerPools");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public boolean neutronLoadBalancerPoolExists(String uuid) {
+ return loadBalancerPoolDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronLoadBalancerPool getNeutronLoadBalancerPool(String uuid) {
+ if (!neutronLoadBalancerPoolExists(uuid)) {
+ logger.debug("No LoadBalancerPool has Been Defined");
+ return null;
+ }
+ return loadBalancerPoolDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronLoadBalancerPool> getAllNeutronLoadBalancerPools() {
+ Set<NeutronLoadBalancerPool> allLoadBalancerPools = new HashSet<NeutronLoadBalancerPool>();
+ for (Entry<String, NeutronLoadBalancerPool> entry : loadBalancerPoolDB.entrySet()) {
+ NeutronLoadBalancerPool loadBalancerPool = entry.getValue();
+ allLoadBalancerPools.add(loadBalancerPool);
+ }
+ logger.debug("Exiting getLoadBalancerPools, Found {} OpenStackLoadBalancerPool", allLoadBalancerPools.size());
+ List<NeutronLoadBalancerPool> ans = new ArrayList<NeutronLoadBalancerPool>();
+ ans.addAll(allLoadBalancerPools);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronLoadBalancerPool(NeutronLoadBalancerPool input) {
+ if (neutronLoadBalancerPoolExists(input.getLoadBalancerPoolID())) {
+ return false;
+ }
+ loadBalancerPoolDB.putIfAbsent(input.getLoadBalancerPoolID(), input);
+ //TODO: add code to find INeutronLoadBalancerPoolAware services and call newtorkCreated on them
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronLoadBalancerPool(String uuid) {
+ if (!neutronLoadBalancerPoolExists(uuid)) {
+ return false;
+ }
+ loadBalancerPoolDB.remove(uuid);
+ //TODO: add code to find INeutronLoadBalancerPoolAware services and call newtorkDeleted on them
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronLoadBalancerPool(String uuid, NeutronLoadBalancerPool delta) {
+ if (!neutronLoadBalancerPoolExists(uuid)) {
+ return false;
+ }
+ NeutronLoadBalancerPool target = loadBalancerPoolDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronLoadBalancerPoolInUse(String loadBalancerPoolUUID) {
+ return !neutronLoadBalancerPoolExists(loadBalancerPoolUUID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronLoadBalancerPool nn = (NeutronLoadBalancerPool) conf;
+ loadBalancerPoolDB.put(nn.getLoadBalancerPoolID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(loadBalancerPoolDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 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.configuration.ConfigurationObject;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+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.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+public class NeutronLoadBalancerPoolMemberInterface
+ implements INeutronLoadBalancerPoolMemberCRUD, IConfigurationContainerAware,
+ IObjectReader {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancerPoolMemberInterface.class);
+ private static final String FILE_NAME = "neutron.loadBalancerPoolMember.conf";
+ private String containerName = null;
+
+ private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
+ private ConcurrentMap<String, NeutronLoadBalancerPoolMember> loadBalancerPoolMemberDB;
+
+ // 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;
+ }
+ }
+
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
+ private void allocateCache() {
+ if (this.clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ logger.debug("Creating Cache for Neutron LoadBalancerPoolMember");
+ try {
+ // neutron caches
+ this.clusterContainerService.createCache("neutronLoadBalancerPoolMembers",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch(CacheConfigException cce) {
+ logger.error("Cache couldn't be created for Neutron LoadBalancerPoolMember - check cache mode");
+ } catch(CacheExistException cce) {
+ logger.error("Cache for Neutron LoadBalancerPoolMember already exists, destroy and recreate");
+ }
+ logger.debug("Cache successfully created for Neutron LoadBalancerPoolMember");
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void retrieveCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterContainerService, can't retrieve cache");
+ return;
+ }
+
+ logger.debug("Retrieving cache for Neutron LoadBalancerPoolMember");
+ loadBalancerPoolMemberDB = (ConcurrentMap<String, NeutronLoadBalancerPoolMember>) clusterContainerService
+ .getCache("neutronLoadBalancerPoolMembers");
+ if (loadBalancerPoolMemberDB == null) {
+ logger.error("Cache couldn't be retrieved for Neutron LoadBalancerPoolMember");
+ }
+ logger.debug("Cache was successfully retrieved for Neutron LoadBalancerPoolMember");
+ }
+
+ private void destroyCache() {
+ if (clusterContainerService == null) {
+ logger.error("un-initialized clusterMger, can't destroy cache");
+ return;
+ }
+ logger.debug("Destroying Cache for HostTracker");
+ clusterContainerService.destroyCache("neutronLoadBalancerPoolMembers");
+ }
+
+ private void startUp() {
+ allocateCache();
+ retrieveCache();
+ loadConfiguration();
+ }
+
+ /**
+ * 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;
+ }
+
+ @Override
+ public boolean neutronLoadBalancerPoolMemberExists(String uuid) {
+ return loadBalancerPoolMemberDB.containsKey(uuid);
+ }
+
+ @Override
+ public NeutronLoadBalancerPoolMember getNeutronLoadBalancerPoolMember(String uuid) {
+ if (!neutronLoadBalancerPoolMemberExists(uuid)) {
+ logger.debug("No LoadBalancerPoolMember Have Been Defined");
+ return null;
+ }
+ return loadBalancerPoolMemberDB.get(uuid);
+ }
+
+ @Override
+ public List<NeutronLoadBalancerPoolMember> getAllNeutronLoadBalancerPoolMembers() {
+ Set<NeutronLoadBalancerPoolMember> allLoadBalancerPoolMembers = new HashSet<NeutronLoadBalancerPoolMember>();
+ for (Map.Entry<String, NeutronLoadBalancerPoolMember> entry : loadBalancerPoolMemberDB.entrySet()) {
+ NeutronLoadBalancerPoolMember loadBalancerPoolMember = entry.getValue();
+ allLoadBalancerPoolMembers.add(loadBalancerPoolMember);
+ }
+ logger.debug("Exiting getLoadBalancerPoolMembers, Found {} OpenStackLoadBalancerPoolMember",
+ allLoadBalancerPoolMembers.size());
+ List<NeutronLoadBalancerPoolMember> ans = new ArrayList<NeutronLoadBalancerPoolMember>();
+ ans.addAll(allLoadBalancerPoolMembers);
+ return ans;
+ }
+
+ @Override
+ public boolean addNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember input) {
+ if (neutronLoadBalancerPoolMemberExists(input.getPoolMemberID())) {
+ return false;
+ }
+ loadBalancerPoolMemberDB.putIfAbsent(input.getPoolMemberID(), input);
+ return true;
+ }
+
+ @Override
+ public boolean removeNeutronLoadBalancerPoolMember(String uuid) {
+ if (!neutronLoadBalancerPoolMemberExists(uuid)) {
+ return false;
+ }
+ loadBalancerPoolMemberDB.remove(uuid);
+ return true;
+ }
+
+ @Override
+ public boolean updateNeutronLoadBalancerPoolMember(String uuid, NeutronLoadBalancerPoolMember delta) {
+ if (!neutronLoadBalancerPoolMemberExists(uuid)) {
+ return false;
+ }
+ NeutronLoadBalancerPoolMember target = loadBalancerPoolMemberDB.get(uuid);
+ return overwrite(target, delta);
+ }
+
+ @Override
+ public boolean neutronLoadBalancerPoolMemberInUse(String loadBalancerPoolMemberID) {
+ return !neutronLoadBalancerPoolMemberExists(loadBalancerPoolMemberID);
+ }
+
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronLoadBalancerPoolMember nn = (NeutronLoadBalancerPoolMember) conf;
+ loadBalancerPoolMemberDB.put(nn.getPoolMemberID(), nn);
+ }
+ }
+
+ @Override
+ public Status saveConfiguration() {
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(loadBalancerPoolMemberDB.values()),
+ FILE_NAME);
+ }
+
+ @Override
+ public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException {
+ return ois.readObject();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 LoadBalancer Rules needs to implement
+ *
+ */
+
+public interface INeutronLoadBalancerAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancer can be created
+ *
+ * @param loadBalancer
+ * instance of proposed new LoadBalancer 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 canCreateNeutronLoadBalancer(NeutronLoadBalancer loadBalancer);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancer has been created
+ *
+ * @param loadBalancer
+ * instance of new LoadBalancer object
+ * @return void
+ */
+ public void neutronLoadBalancerCreated(NeutronLoadBalancer loadBalancer);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancer can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the loadBalancer object using patch semantics
+ * @param original
+ * instance of the LoadBalancer 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 canUpdateNeutronLoadBalancer(NeutronLoadBalancer delta, NeutronLoadBalancer original);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancer has been updated
+ *
+ * @param loadBalancer
+ * instance of modified LoadBalancer object
+ * @return void
+ */
+ public void neutronLoadBalancerUpdated(NeutronLoadBalancer loadBalancer);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancer can be deleted
+ *
+ * @param loadBalancer
+ * instance of the LoadBalancer 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 canDeleteNeutronLoadBalancer(NeutronLoadBalancer loadBalancer);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancer has been deleted
+ *
+ * @param loadBalancer
+ * instance of deleted LoadBalancer object
+ * @return void
+ */
+ public void neutronLoadBalancerDeleted(NeutronLoadBalancer loadBalancer);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 OpenStack LoadBalancer objects
+ *
+ */
+
+public interface INeutronLoadBalancerCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ *LoadBalancer object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancer object
+ * @return boolean
+ */
+
+ public boolean neutronLoadBalancerExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * LoadBalancer object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancer object
+ * @return {@link NeutronLoadBalancer}
+ * OpenStackLoadBalancer class
+ */
+
+ public NeutronLoadBalancer getNeutronLoadBalancer(String uuid);
+
+ /**
+ * Applications call this interface method to return all LoadBalancer objects
+ *
+ * @return List of OpenStackNetworks objects
+ */
+
+ public List<NeutronLoadBalancer> getAllNeutronLoadBalancers();
+
+ /**
+ * Applications call this interface method to add a LoadBalancer object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackNetwork object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronLoadBalancer(NeutronLoadBalancer input);
+
+ /**
+ * Applications call this interface method to remove a Neutron LoadBalancer object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the LoadBalancer object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronLoadBalancer(String uuid);
+
+ /**
+ * Applications call this interface method to edit a LoadBalancer object
+ *
+ * @param uuid
+ * identifier of the LoadBalancer object
+ * @param delta
+ * OpenStackLoadBalancer object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronLoadBalancer(String uuid, NeutronLoadBalancer delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid
+ * identifier of the LoadBalancer object
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean neutronLoadBalancerInUse(String uuid);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 LoadBalancerHealthMonitor Rules needs to implement
+ *
+ */
+
+public interface INeutronLoadBalancerHealthMonitorAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerHealthMonitor can be created
+ *
+ * @param loadBalancerHealthMonitor
+ * instance of proposed new LoadBalancerHealthMonitor 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 canCreateNeutronLoadBalancerHealthMonitor(NeutronLoadBalancerHealthMonitor loadBalancerHealthMonitor);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerHealthMonitor has been created
+ *
+ * @param loadBalancerHealthMonitor
+ * instance of new LoadBalancerHealthMonitor object
+ * @return void
+ */
+ public void neutronLoadBalancerHealthMonitorCreated(NeutronLoadBalancerHealthMonitor loadBalancerHealthMonitor);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerHealthMonitor can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the loadBalancerHealthMonitor object using patch semantics
+ * @param original
+ * instance of the LoadBalancerHealthMonitor 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 canUpdateNeutronLoadBalancerHealthMonitor(NeutronLoadBalancerHealthMonitor delta,
+ NeutronLoadBalancerHealthMonitor original);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerHealthMonitor has been updated
+ *
+ * @param loadBalancerHealthMonitor
+ * instance of modified LoadBalancerHealthMonitor object
+ * @return void
+ */
+ public void neutronLoadBalancerHealthMonitorUpdated(NeutronLoadBalancerHealthMonitor loadBalancerHealthMonitor);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerHealthMonitor can be deleted
+ *
+ * @param loadBalancerHealthMonitor
+ * instance of the LoadBalancerHealthMonitor 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 canDeleteNeutronLoadBalancerHealthMonitor(NeutronLoadBalancerHealthMonitor loadBalancerHealthMonitor);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerHealthMonitor has been deleted
+ *
+ * @param loadBalancerHealthMonitor
+ * instance of deleted LoadBalancerHealthMonitor object
+ * @return void
+ */
+ public void neutronLoadBalancerHealthMonitorDeleted(NeutronLoadBalancerHealthMonitor loadBalancerHealthMonitor);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 OpenStack LoadBalancerHealthMonitor objects
+ *
+ */
+
+public interface INeutronLoadBalancerHealthMonitorCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ *LoadBalancerHealthMonitor object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancerHealthMonitor object
+ * @return boolean
+ */
+
+ public boolean neutronLoadBalancerHealthMonitorExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * LoadBalancerHealthMonitor object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancerHealthMonitor object
+ * @return {@link NeutronLoadBalancerHealthMonitor}
+ * OpenStackLoadBalancerHealthMonitor class
+ */
+
+ public NeutronLoadBalancerHealthMonitor getNeutronLoadBalancerHealthMonitor(String uuid);
+
+ /**
+ * Applications call this interface method to return all LoadBalancerHealthMonitor objects
+ *
+ * @return List of OpenStackNetworks objects
+ */
+
+ public List<NeutronLoadBalancerHealthMonitor> getAllNeutronLoadBalancerHealthMonitors();
+
+ /**
+ * Applications call this interface method to add a LoadBalancerHealthMonitor object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackNetwork object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronLoadBalancerHealthMonitor(NeutronLoadBalancerHealthMonitor input);
+
+ /**
+ * Applications call this interface method to remove a Neutron LoadBalancerHealthMonitor object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the LoadBalancerHealthMonitor object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronLoadBalancerHealthMonitor(String uuid);
+
+ /**
+ * Applications call this interface method to edit a LoadBalancerHealthMonitor object
+ *
+ * @param uuid
+ * identifier of the LoadBalancerHealthMonitor object
+ * @param delta
+ * OpenStackLoadBalancerHealthMonitor object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronLoadBalancerHealthMonitor(String uuid, NeutronLoadBalancerHealthMonitor delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid
+ * identifier of the LoadBalancerHealthMonitor object
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean neutronLoadBalancerHealthMonitorInUse(String uuid);
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 LoadBalancerListener Rules needs to implement
+ *
+ */
+
+public interface INeutronLoadBalancerListenerAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerListener can be created
+ *
+ * @param loadBalancerListener
+ * instance of proposed new LoadBalancerListener 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 canCreateNeutronLoadBalancerListener(NeutronLoadBalancerListener loadBalancerListener);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerListener has been created
+ *
+ * @param loadBalancerListener
+ * instance of new LoadBalancerListener object
+ * @return void
+ */
+ public void neutronLoadBalancerListenerCreated(NeutronLoadBalancerListener loadBalancerListener);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerListener can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the loadBalancerListener object using patch semantics
+ * @param original
+ * instance of the LoadBalancerListener 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 canUpdateNeutronLoadBalancerListener(NeutronLoadBalancerListener delta,
+ NeutronLoadBalancerListener original);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerListener has been updated
+ *
+ * @param loadBalancerListener
+ * instance of modified LoadBalancerListener object
+ * @return void
+ */
+ public void neutronLoadBalancerListenerUpdated(NeutronLoadBalancerListener loadBalancerListener);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerListener can be deleted
+ *
+ * @param loadBalancerListener
+ * instance of the LoadBalancerListener 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 canDeleteNeutronLoadBalancerListener(NeutronLoadBalancerListener loadBalancerListener);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerListener has been deleted
+ *
+ * @param loadBalancerListener
+ * instance of deleted LoadBalancerListener object
+ * @return void
+ */
+ public void neutronLoadBalancerListenerDeleted(NeutronLoadBalancerListener loadBalancerListener);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 OpenStack LoadBalancerListener objects
+ *
+ */
+
+public interface INeutronLoadBalancerListenerCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ *LoadBalancerListener object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancerListener object
+ * @return boolean
+ */
+
+ public boolean neutronLoadBalancerListenerExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * LoadBalancerListener object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancerListener object
+ * @return {@link NeutronLoadBalancerListener}
+ * OpenStackLoadBalancerListener class
+ */
+
+ public NeutronLoadBalancerListener getNeutronLoadBalancerListener(String uuid);
+
+ /**
+ * Applications call this interface method to return all LoadBalancerListener objects
+ *
+ * @return List of OpenStackNetworks objects
+ */
+
+ public List<NeutronLoadBalancerListener> getAllNeutronLoadBalancerListeners();
+
+ /**
+ * Applications call this interface method to add a LoadBalancerListener object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackNetwork object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronLoadBalancerListener(NeutronLoadBalancerListener input);
+
+ /**
+ * Applications call this interface method to remove a Neutron LoadBalancerListener object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the LoadBalancerListener object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronLoadBalancerListener(String uuid);
+
+ /**
+ * Applications call this interface method to edit a LoadBalancerListener object
+ *
+ * @param uuid
+ * identifier of the LoadBalancerListener object
+ * @param delta
+ * OpenStackLoadBalancerListener object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronLoadBalancerListener(String uuid, NeutronLoadBalancerListener delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid
+ * identifier of the LoadBalancerListener object
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean neutronLoadBalancerListenerInUse(String uuid);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 LoadBalancerPool Rules needs to implement
+ *
+ */
+
+public interface INeutronLoadBalancerPoolAware {
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerPool can be created
+ *
+ * @param loadBalancerPool
+ * instance of proposed new LoadBalancerPool 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 canCreateNeutronLoadBalancerPool(NeutronLoadBalancerPool loadBalancerPool);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerPool has been created
+ *
+ * @param loadBalancerPool
+ * instance of new LoadBalancerPool object
+ * @return void
+ */
+ public void neutronLoadBalancerPoolCreated(NeutronLoadBalancerPool loadBalancerPool);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerPool can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the loadBalancerPool object using patch semantics
+ * @param original
+ * instance of the LoadBalancerPool 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 canUpdateNeutronLoadBalancerPool(NeutronLoadBalancerPool delta, NeutronLoadBalancerPool original);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerPool has been updated
+ *
+ * @param loadBalancerPool
+ * instance of modified LoadBalancerPool object
+ * @return void
+ */
+ public void neutronLoadBalancerPoolUpdated(NeutronLoadBalancerPool loadBalancerPool);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerPool can be deleted
+ *
+ * @param loadBalancerPool
+ * instance of the LoadBalancerPool 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 canDeleteNeutronLoadBalancerPool(NeutronLoadBalancerPool loadBalancerPool);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerPool has been deleted
+ *
+ * @param loadBalancerPool
+ * instance of deleted LoadBalancerPool object
+ * @return void
+ */
+ public void neutronLoadBalancerPoolDeleted(NeutronLoadBalancerPool loadBalancerPool);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 OpenStack LoadBalancerPool objects
+ *
+ */
+
+public interface INeutronLoadBalancerPoolCRUD {
+ /**
+ * Applications call this interface method to determine if a particular
+ *LoadBalancerPool object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancerPool object
+ * @return boolean
+ */
+
+ public boolean neutronLoadBalancerPoolExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * LoadBalancerPool object exists
+ *
+ * @param uuid
+ * UUID of the LoadBalancerPool object
+ * @return {@link NeutronLoadBalancerPool}
+ * OpenStackLoadBalancerPool class
+ */
+
+ public NeutronLoadBalancerPool getNeutronLoadBalancerPool(String uuid);
+
+ /**
+ * Applications call this interface method to return all LoadBalancerPool objects
+ *
+ * @return List of OpenStackNetworks objects
+ */
+
+ public List<NeutronLoadBalancerPool> getAllNeutronLoadBalancerPools();
+
+ /**
+ * Applications call this interface method to add a LoadBalancerPool object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackNetwork object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronLoadBalancerPool(NeutronLoadBalancerPool input);
+
+ /**
+ * Applications call this interface method to remove a Neutron LoadBalancerPool object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the LoadBalancerPool object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronLoadBalancerPool(String uuid);
+
+ /**
+ * Applications call this interface method to edit a LoadBalancerPool object
+ *
+ * @param uuid
+ * identifier of the LoadBalancerPool object
+ * @param delta
+ * OpenStackLoadBalancerPool object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronLoadBalancerPool(String uuid, NeutronLoadBalancerPool delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid
+ * identifier of the LoadBalancerPool object
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean neutronLoadBalancerPoolInUse(String uuid);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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;
+
+public interface INeutronLoadBalancerPoolMemberAware {
+
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerPoolMember can be created
+ *
+ * @param loadBalancerPoolMember
+ * instance of proposed new LoadBalancerPool 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 canCreateNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerPoolMember has been created
+ *
+ * @param loadBalancerPoolMember
+ * instance of new LoadBalancerPool object
+ * @return void
+ */
+ public void neutronLoadBalancerPoolMemberCreated(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerPoolMember can be changed using the specified
+ * delta
+ *
+ * @param delta
+ * updates to the loadBalancerPoolMember object using patch semantics
+ * @param original
+ * instance of the LoadBalancerPool 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 canUpdateNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember delta,
+ NeutronLoadBalancerPoolMember original);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerPoolMember has been updated
+ *
+ * @param loadBalancerPoolMember
+ * instance of modified LoadBalancerPool object
+ * @return void
+ */
+ public void neutronLoadBalancerPoolMemberUpdated(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+
+ /**
+ * Services provide this interface method to indicate if the specified loadBalancerPoolMember can be deleted
+ *
+ * @param loadBalancerPoolMember
+ * instance of the LoadBalancerPool 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 canDeleteNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+
+ /**
+ * Services provide this interface method for taking action after a loadBalancerPoolMember has been deleted
+ *
+ * @param loadBalancerPoolMember
+ * instance of deleted LoadBalancerPool object
+ * @return void
+ */
+ public void NeutronLoadBalancerPoolMemberDeleted(NeutronLoadBalancerPoolMember loadBalancerPoolMember);
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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;
+
+public interface INeutronLoadBalancerPoolMemberCRUD {
+
+ /**
+ * Applications call this interface method to determine if a particular
+ *NeutronLoadBalancerPoolMember object exists
+ *
+ * @param uuid
+ * UUID of the NeutronLoadBalancerPoolMember object
+ * @return boolean
+ */
+
+ public boolean neutronLoadBalancerPoolMemberExists(String uuid);
+
+ /**
+ * Applications call this interface method to return if a particular
+ * NeutronLoadBalancerPoolMember object exists
+ *
+ * @param uuid
+ * UUID of the NeutronLoadBalancerPoolMember object
+ * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember}
+ * OpenStackNeutronLoadBalancerPoolMember class
+ */
+
+ public NeutronLoadBalancerPoolMember getNeutronLoadBalancerPoolMember(String uuid);
+
+ /**
+ * Applications call this interface method to return all NeutronLoadBalancerPoolMember objects
+ *
+ * @return List of OpenStackNetworks objects
+ */
+
+ public List<NeutronLoadBalancerPoolMember> getAllNeutronLoadBalancerPoolMembers();
+
+ /**
+ * Applications call this interface method to add a NeutronLoadBalancerPoolMember object to the
+ * concurrent map
+ *
+ * @param input
+ * OpenStackNetwork object
+ * @return boolean on whether the object was added or not
+ */
+
+ public boolean addNeutronLoadBalancerPoolMember(NeutronLoadBalancerPoolMember input);
+
+ /**
+ * Applications call this interface method to remove a Neutron NeutronLoadBalancerPoolMember object to the
+ * concurrent map
+ *
+ * @param uuid
+ * identifier for the NeutronLoadBalancerPoolMember object
+ * @return boolean on whether the object was removed or not
+ */
+
+ public boolean removeNeutronLoadBalancerPoolMember(String uuid);
+
+ /**
+ * Applications call this interface method to edit a NeutronLoadBalancerPoolMember object
+ *
+ * @param uuid
+ * identifier of the NeutronLoadBalancerPoolMember object
+ * @param delta
+ * OpenStackNeutronLoadBalancerPoolMember object containing changes to apply
+ * @return boolean on whether the object was updated or not
+ */
+
+ public boolean updateNeutronLoadBalancerPoolMember(String uuid, NeutronLoadBalancerPoolMember delta);
+
+ /**
+ * Applications call this interface method to see if a MAC address is in use
+ *
+ * @param uuid
+ * identifier of the NeutronLoadBalancerPoolMember object
+ * @return boolean on whether the macAddress is already associated with a
+ * port or not
+ */
+
+ public boolean neutronLoadBalancerPoolMemberInUse(String uuid);
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.XmlElement;
+import java.util.List;
+
+public class INeutronLoadBalancerPoolMemberRequest {
+
+ /**
+ * See OpenStack Network API v2.0 Reference for description of
+ * http://docs.openstack.org/api/openstack-network/2.0/content/
+ */
+
+ @XmlElement(name="member")
+ NeutronLoadBalancerPoolMember singletonLoadBalancerPoolMember;
+
+ @XmlElement(name="members")
+ List<NeutronLoadBalancerPoolMember> bulkRequest;
+
+ INeutronLoadBalancerPoolMemberRequest() {
+ }
+
+ public INeutronLoadBalancerPoolMemberRequest(List<NeutronLoadBalancerPoolMember> bulk) {
+ bulkRequest = bulk;
+ singletonLoadBalancerPoolMember = null;
+ }
+
+ INeutronLoadBalancerPoolMemberRequest(NeutronLoadBalancerPoolMember group) {
+ singletonLoadBalancerPoolMember = group;
+ }
+
+ public List<NeutronLoadBalancerPoolMember> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronLoadBalancerPoolMember getSingleton() {
+ return singletonLoadBalancerPoolMember;
+ }
+
+ public boolean isSingleton() {
+ return (singletonLoadBalancerPoolMember != null);
+ }
+}
\ No newline at end of file
INeutronFirewallRuleCRUD answer = (INeutronFirewallRuleCRUD) ServiceHelper.getGlobalInstance(INeutronFirewallRuleCRUD.class, o);
return answer;
}
+
+ public static INeutronLoadBalancerCRUD getINeutronLoadBalancerCRUD(Object o) {
+ INeutronLoadBalancerCRUD answer = (INeutronLoadBalancerCRUD) ServiceHelper.getGlobalInstance(INeutronLoadBalancerCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronLoadBalancerPoolCRUD getINeutronLoadBalancerPoolCRUD(Object o) {
+ INeutronLoadBalancerPoolCRUD answer = (INeutronLoadBalancerPoolCRUD) ServiceHelper.getGlobalInstance(INeutronLoadBalancerPoolCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronLoadBalancerListenerCRUD getINeutronLoadBalancerListenerCRUD(Object o) {
+ INeutronLoadBalancerListenerCRUD answer = (INeutronLoadBalancerListenerCRUD) ServiceHelper.getGlobalInstance(INeutronLoadBalancerListenerCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronLoadBalancerHealthMonitorCRUD getINeutronLoadBalancerHealthMonitorCRUD(Object o) {
+ INeutronLoadBalancerHealthMonitorCRUD answer = (INeutronLoadBalancerHealthMonitorCRUD) ServiceHelper.getGlobalInstance(INeutronLoadBalancerHealthMonitorCRUD.class, o);
+ return answer;
+ }
+
+ public static INeutronLoadBalancerPoolMemberCRUD getINeutronLoadBalancerPoolMemberCRUD(Object o) {
+ INeutronLoadBalancerPoolMemberCRUD answer = (INeutronLoadBalancerPoolMemberCRUD) ServiceHelper.getGlobalInstance(INeutronLoadBalancerPoolMemberCRUD.class, o);
+ return answer;
+ }
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.configuration.ConfigurationObject;
+
+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 java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Load Balancer as a service
+ * (LBaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of the fields:
+ * Implemented fields are as follows:
+ *
+ * id uuid-str
+ * tenant_id uuid-str
+ * name String
+ * description String
+ * status String
+ * vip_address IP address
+ * vip_subnet uuid-str
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancer extends ConfigurationObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlElement(name="id")
+ String loadBalancerID;
+
+ @XmlElement (name="tenant_id")
+ String loadBalancerTenantID;
+
+ @XmlElement (name="name")
+ String loadBalancerName;
+
+ @XmlElement (name="description")
+ String loadBalancerDescription;
+
+ @XmlElement (name="status")
+ String loadBalancerStatus;
+
+ @XmlElement (name="vip_address")
+ String loadBalancerVipAddress;
+
+ @XmlElement (name="vip_subnet_id")
+ String loadBalancerVipSubnetID;
+
+ public String getLoadBalancerID() {
+ return loadBalancerID;
+ }
+
+ public void setLoadBalancerID(String loadBalancerID) {
+ this.loadBalancerID = loadBalancerID;
+ }
+
+ public String getLoadBalancerTenantID() {
+ return loadBalancerTenantID;
+ }
+
+ public void setLoadBalancerTenantID(String loadBalancerTenantID) {
+ this.loadBalancerTenantID = loadBalancerTenantID;
+ }
+
+ public String getLoadBalancerName() {
+ return loadBalancerName;
+ }
+
+ public void setLoadBalancerName(String loadBalancerName) {
+ this.loadBalancerName = loadBalancerName;
+ }
+
+ public String getLoadBalancerDescription() {
+ return loadBalancerDescription;
+ }
+
+ public void setLoadBalancerDescription(String loadBalancerDescription) {
+ this.loadBalancerDescription = loadBalancerDescription;
+ }
+
+ public String getLoadBalancerStatus() {
+ return loadBalancerStatus;
+ }
+
+ public void setLoadBalancerStatus(String loadBalancerStatus) {
+ this.loadBalancerStatus = loadBalancerStatus;
+ }
+
+ public String getLoadBalancerVipAddress() {
+ return loadBalancerVipAddress;
+ }
+
+ public void setLoadBalancerVipAddress(String loadBalancerVipAddress) {
+ this.loadBalancerVipAddress = loadBalancerVipAddress;
+ }
+
+ public String getLoadBalancerVipSubnetID() {
+ return loadBalancerVipSubnetID;
+ }
+
+ public void setLoadBalancerVipSubnetID(String loadBalancerVipSubnetID) {
+ this.loadBalancerVipSubnetID = loadBalancerVipSubnetID;
+ }
+
+ public NeutronLoadBalancer extractFields(List<String> fields) {
+ NeutronLoadBalancer ans = new NeutronLoadBalancer();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setLoadBalancerID(this.getLoadBalancerID());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setLoadBalancerTenantID(this.getLoadBalancerTenantID());
+ }
+ if (s.equals("name")) {
+ ans.setLoadBalancerName(this.getLoadBalancerName());
+ }
+ if(s.equals("description")) {
+ ans.setLoadBalancerDescription(this.getLoadBalancerDescription());
+ }
+ if (s.equals("vip_address")) {
+ ans.setLoadBalancerVipAddress(this.getLoadBalancerVipAddress());
+ }
+ if (s.equals("vip_subnet_id")) {
+ ans.setLoadBalancerVipSubnetID(this.getLoadBalancerVipSubnetID());
+ }
+ if (s.equals("status")) {
+ ans.setLoadBalancerStatus(this.getLoadBalancerStatus());
+ }
+ }
+ return ans;
+ }
+
+ @Override public String toString() {
+ return "NeutronLoadBalancer{" +
+ "loadBalancerID='" + loadBalancerID + '\'' +
+ ", loadBalancerTenantID='" + loadBalancerTenantID + '\'' +
+ ", loadBalancerName='" + loadBalancerName + '\'' +
+ ", loadBalancerDescription='" + loadBalancerDescription + '\'' +
+ ", loadBalancerStatus='" + loadBalancerStatus + '\'' +
+ ", loadBalancerVipAddress='" + loadBalancerVipAddress + '\'' +
+ ", loadBalancerVipSubnetID='" + loadBalancerVipSubnetID + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.configuration.ConfigurationObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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 java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Load Balancer as a service
+ * (LBaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of the fields:
+ * Implemented fields are as follows:
+ *
+ *
+ * id uuid-str
+ * tenant_id uuid-str
+ * type String
+ * delay Integer
+ * timeout Integer
+ * max_retries Integer
+ * http_method String
+ * url_path String
+ * expected_codes String
+ * admin_state_up Boolean
+ * status String
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerHealthMonitor extends ConfigurationObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancer.class);
+
+ @XmlElement(name="id")
+ String loadBalancerHealthMonitorID;
+
+ @XmlElement (name="tenant_id")
+ String loadBalancerHealthMonitorTenantID;
+
+ @XmlElement (name="type")
+ String loadBalancerHealthMonitorType;
+
+ @XmlElement (name="delay")
+ Integer loadBalancerHealthMonitorDelay;
+
+ @XmlElement (name="timeout")
+ Integer loadBalancerHealthMonitorTimeout;
+
+ @XmlElement (name="max_retries")
+ Integer loadBalancerHealthMonitorMaxRetries;
+
+ @XmlElement (name="http_method")
+ String loadBalancerHealthMonitorHttpMethod;
+
+ @XmlElement (name="url_path")
+ String loadBalancerHealthMonitorUrlPath;
+
+ @XmlElement (name="expected_codes")
+ String loadBalancerHealthMonitorExpectedCodes;
+
+ @XmlElement (defaultValue="true", name="admin_state_up")
+ Boolean loadBalancerHealthMonitorAdminStateIsUp;
+
+ @XmlElement (name="status")
+ String loadBalancerHealthMonitorStatus;
+
+ public String getLoadBalancerHealthMonitorID() {
+ return loadBalancerHealthMonitorID;
+ }
+
+ public void setLoadBalancerHealthMonitorID(String loadBalancerHealthMonitorID) {
+ this.loadBalancerHealthMonitorID = loadBalancerHealthMonitorID;
+ }
+
+ public String getLoadBalancerHealthMonitorTenantID() {
+ return loadBalancerHealthMonitorTenantID;
+ }
+
+ public void setLoadBalancerHealthMonitorTenantID(String loadBalancerHealthMonitorTenantID) {
+ this.loadBalancerHealthMonitorTenantID = loadBalancerHealthMonitorTenantID;
+ }
+
+ public String getLoadBalancerHealthMonitorType() {
+ return loadBalancerHealthMonitorType;
+ }
+
+ public void setLoadBalancerHealthMonitorType(String loadBalancerHealthMonitorType) {
+ this.loadBalancerHealthMonitorType = loadBalancerHealthMonitorType;
+ }
+
+ public Integer getLoadBalancerHealthMonitorDelay() {
+ return loadBalancerHealthMonitorDelay;
+ }
+
+ public void setLoadBalancerHealthMonitorDelay(Integer loadBalancerHealthMonitorDelay) {
+ this.loadBalancerHealthMonitorDelay = loadBalancerHealthMonitorDelay;
+ }
+
+ public Integer getLoadBalancerHealthMonitorTimeout() {
+ return loadBalancerHealthMonitorTimeout;
+ }
+
+ public void setLoadBalancerHealthMonitorTimeout(Integer loadBalancerHealthMonitorTimeout) {
+ this.loadBalancerHealthMonitorTimeout = loadBalancerHealthMonitorTimeout;
+ }
+
+ public Integer getLoadBalancerHealthMonitorMaxRetries() {
+ return loadBalancerHealthMonitorMaxRetries;
+ }
+
+ public void setLoadBalancerHealthMonitorMaxRetries(Integer loadBalancerHealthMonitorMaxRetries) {
+ this.loadBalancerHealthMonitorMaxRetries = loadBalancerHealthMonitorMaxRetries;
+ }
+
+ public String getLoadBalancerHealthMonitorHttpMethod() {
+ return loadBalancerHealthMonitorHttpMethod;
+ }
+
+ public void setLoadBalancerHealthMonitorHttpMethod(String loadBalancerHealthMonitorHttpMethod) {
+ this.loadBalancerHealthMonitorHttpMethod = loadBalancerHealthMonitorHttpMethod;
+ }
+
+ public String getLoadBalancerHealthMonitorUrlPath() {
+ return loadBalancerHealthMonitorUrlPath;
+ }
+
+ public void setLoadBalancerHealthMonitorUrlPath(String loadBalancerHealthMonitorUrlPath) {
+ this.loadBalancerHealthMonitorUrlPath = loadBalancerHealthMonitorUrlPath;
+ }
+
+ public String getLoadBalancerHealthMonitorExpectedCodes() {
+ return loadBalancerHealthMonitorExpectedCodes;
+ }
+
+ public void setLoadBalancerHealthMonitorExpectedCodes(String loadBalancerHealthMonitorExpectedCodes) {
+ this.loadBalancerHealthMonitorExpectedCodes = loadBalancerHealthMonitorExpectedCodes;
+ }
+
+ public Boolean getLoadBalancerHealthMonitorAdminStateIsUp() {
+ return loadBalancerHealthMonitorAdminStateIsUp;
+ }
+
+ public void setLoadBalancerHealthMonitorAdminStateIsUp(Boolean loadBalancerHealthMonitorAdminStateIsUp) {
+ this.loadBalancerHealthMonitorAdminStateIsUp = loadBalancerHealthMonitorAdminStateIsUp;
+ }
+
+ public String getLoadBalancerHealthMonitorStatus() {
+ return loadBalancerHealthMonitorStatus;
+ }
+
+ public void setLoadBalancerHealthMonitorStatus(String loadBalancerHealthMonitorStatus) {
+ this.loadBalancerHealthMonitorStatus = loadBalancerHealthMonitorStatus;
+ }
+
+ public NeutronLoadBalancerHealthMonitor extractFields(List<String> fields) {
+ NeutronLoadBalancerHealthMonitor ans = new NeutronLoadBalancerHealthMonitor();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setLoadBalancerHealthMonitorID(this.getLoadBalancerHealthMonitorID());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setLoadBalancerHealthMonitorTenantID(this.getLoadBalancerHealthMonitorTenantID());
+ }
+ if (s.equals("type")) {
+ ans.setLoadBalancerHealthMonitorType(this.getLoadBalancerHealthMonitorType());
+ }
+ if (s.equals("delay")) {
+ ans.setLoadBalancerHealthMonitorDelay(this.getLoadBalancerHealthMonitorDelay());
+ }
+ if (s.equals("timeout")) {
+ ans.setLoadBalancerHealthMonitorTimeout(this.getLoadBalancerHealthMonitorTimeout());
+ }
+ if (s.equals("max_retries")) {
+ ans.setLoadBalancerHealthMonitorMaxRetries(this.getLoadBalancerHealthMonitorMaxRetries());
+ }
+ if (s.equals("http_method")) {
+ ans.setLoadBalancerHealthMonitorHttpMethod(this.getLoadBalancerHealthMonitorHttpMethod());
+ }
+ if(s.equals("url_path")) {
+ ans.setLoadBalancerHealthMonitorUrlPath(this.getLoadBalancerHealthMonitorUrlPath());
+ }
+ if (s.equals("expected_codes")) {
+ ans.setLoadBalancerHealthMonitorExpectedCodes(this.getLoadBalancerHealthMonitorExpectedCodes());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setLoadBalancerHealthMonitorAdminStateIsUp(loadBalancerHealthMonitorAdminStateIsUp);
+ }
+ if (s.equals("status")) {
+ ans.setLoadBalancerHealthMonitorStatus(this.getLoadBalancerHealthMonitorStatus());
+ }
+ }
+ return ans;
+ }
+
+ @Override public String toString() {
+ return "NeutronLoadBalancerHealthMonitor{" +
+ "loadBalancerHealthMonitorID='" + loadBalancerHealthMonitorID + '\'' +
+ ", loadBalancerHealthMonitorTenantID='" + loadBalancerHealthMonitorTenantID + '\'' +
+ ", loadBalancerHealthMonitorType='" + loadBalancerHealthMonitorType + '\'' +
+ ", loadBalancerHealthMonitorDelay=" + loadBalancerHealthMonitorDelay +
+ ", loadBalancerHealthMonitorTimeout=" + loadBalancerHealthMonitorTimeout +
+ ", loadBalancerHealthMonitorMaxRetries=" + loadBalancerHealthMonitorMaxRetries +
+ ", loadBalancerHealthMonitorHttpMethod='" + loadBalancerHealthMonitorHttpMethod + '\'' +
+ ", loadBalancerHealthMonitorUrlPath='" + loadBalancerHealthMonitorUrlPath + '\'' +
+ ", loadBalancerHealthMonitorExpectedCodes='" + loadBalancerHealthMonitorExpectedCodes + '\'' +
+ ", loadBalancerHealthMonitorAdminStateIsUp=" + loadBalancerHealthMonitorAdminStateIsUp +
+ ", loadBalancerHealthMonitorStatus='" + loadBalancerHealthMonitorStatus + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.configuration.ConfigurationObject;
+
+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 java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Load Balancer as a service
+ * (LBaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of the fields:
+ * Implemented fields are as follows:
+ *
+ * id uuid-str
+ * default_pool_id String
+ * tenant_id uuid-str
+ * name String
+ * description String
+ * shared Bool
+ * protocol String
+ * protocol_port String
+ * load_balancer_id String
+ * admin_state_up Boolean
+ * status String
+ *
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerListener extends ConfigurationObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlElement(name="id")
+ String loadBalancerListenerID;
+
+ @XmlElement (name="default_pool_id")
+ String neutronLoadBalancerListenerDefaultPoolID;
+
+ @XmlElement (name="tenant_id")
+ String loadBalancerListenerTenantID;
+
+ @XmlElement (name="name")
+ String loadBalancerListenerName;
+
+ @XmlElement (name="description")
+ String loadBalancerListenerDescription;
+
+ @XmlElement (defaultValue="true", name="admin_state_up")
+ Boolean loadBalancerListenerAdminStateIsUp;
+
+ @XmlElement (name="status")
+ String loadBalancerListenerStatus;
+
+ @XmlElement (defaultValue="false", name="shared")
+ Boolean loadBalancerListenerIsShared;
+
+ @XmlElement (name="protocol")
+ String neutronLoadBalancerListenerProtocol;
+
+ @XmlElement (name="protocol_port")
+ String neutronLoadBalancerListenerProtocolPort;
+
+ @XmlElement (name="load_balancer_id")
+ String neutronLoadBalancerListenerLoadBalancerID;
+
+
+ public String getLoadBalancerListenerID() {
+ return loadBalancerListenerID;
+ }
+
+ public void setLoadBalancerListenerID(String loadBalancerListenerID) {
+ this.loadBalancerListenerID = loadBalancerListenerID;
+ }
+
+ public String getLoadBalancerListenerTenantID() {
+ return loadBalancerListenerTenantID;
+ }
+
+ public void setLoadBalancerListenerTenantID(String loadBalancerListenerTenantID) {
+ this.loadBalancerListenerTenantID = loadBalancerListenerTenantID;
+ }
+
+ public String getLoadBalancerListenerName() {
+ return loadBalancerListenerName;
+ }
+
+ public void setLoadBalancerListenerName(String loadBalancerListenerName) {
+ this.loadBalancerListenerName = loadBalancerListenerName;
+ }
+
+ public String getLoadBalancerListenerDescription() {
+ return loadBalancerListenerDescription;
+ }
+
+ public void setLoadBalancerListenerDescription(String loadBalancerListenerDescription) {
+ this.loadBalancerListenerDescription = loadBalancerListenerDescription;
+ }
+
+ public Boolean getLoadBalancerListenerAdminStateIsUp() {
+ return loadBalancerListenerAdminStateIsUp;
+ }
+
+ public void setLoadBalancerListenerAdminStateIsUp(Boolean loadBalancerListenerAdminStateIsUp) {
+ this.loadBalancerListenerAdminStateIsUp = loadBalancerListenerAdminStateIsUp;
+ }
+
+ public String getLoadBalancerListenerStatus() {
+ return loadBalancerListenerStatus;
+ }
+
+ public void setLoadBalancerListenerStatus(String loadBalancerListenerStatus) {
+ this.loadBalancerListenerStatus = loadBalancerListenerStatus;
+ }
+
+ public Boolean getLoadBalancerListenerIsShared() {
+ return loadBalancerListenerIsShared;
+ }
+
+ public void setLoadBalancerListenerIsShared(Boolean loadBalancerListenerIsShared) {
+ this.loadBalancerListenerIsShared = loadBalancerListenerIsShared;
+ }
+
+ public String getNeutronLoadBalancerListenerProtocol() {
+ return neutronLoadBalancerListenerProtocol;
+ }
+
+ public void setNeutronLoadBalancerListenerProtocol(String neutronLoadBalancerListenerProtocol) {
+ this.neutronLoadBalancerListenerProtocol = neutronLoadBalancerListenerProtocol;
+ }
+
+ public String getNeutronLoadBalancerListenerProtocolPort() {
+ return neutronLoadBalancerListenerProtocolPort;
+ }
+
+ public void setNeutronLoadBalancerListenerProtocolPort(String neutronLoadBalancerListenerProtocolPort) {
+ this.neutronLoadBalancerListenerProtocolPort = neutronLoadBalancerListenerProtocolPort;
+ }
+
+ public String getNeutronLoadBalancerListenerDefaultPoolID() {
+ return neutronLoadBalancerListenerDefaultPoolID;
+ }
+
+ public void setNeutronLoadBalancerListenerDefaultPoolID(String neutronLoadBalancerListenerDefaultPoolID) {
+ this.neutronLoadBalancerListenerDefaultPoolID = neutronLoadBalancerListenerDefaultPoolID;
+ }
+
+ public String getNeutronLoadBalancerListenerLoadBalancerID() {
+ return neutronLoadBalancerListenerLoadBalancerID;
+ }
+
+ public void setNeutronLoadBalancerListenerLoadBalancerID(String neutronLoadBalancerListenerLoadBalancerID) {
+ this.neutronLoadBalancerListenerLoadBalancerID = neutronLoadBalancerListenerLoadBalancerID;
+ }
+
+ public NeutronLoadBalancerListener extractFields(List<String> fields) {
+ NeutronLoadBalancerListener ans = new NeutronLoadBalancerListener();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setLoadBalancerListenerID(this.getLoadBalancerListenerID());
+ }
+ if(s.equals("default_pool_id")) {
+ ans.setNeutronLoadBalancerListenerDefaultPoolID(this.getNeutronLoadBalancerListenerDefaultPoolID());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setLoadBalancerListenerTenantID(this.getLoadBalancerListenerTenantID());
+ }
+ if (s.equals("name")) {
+ ans.setLoadBalancerListenerName(this.getLoadBalancerListenerName());
+ }
+ if(s.equals("description")) {
+ ans.setLoadBalancerListenerDescription(this.getLoadBalancerListenerDescription());
+ }
+ if (s.equals("shared")) {
+ ans.setLoadBalancerListenerIsShared(loadBalancerListenerIsShared);
+ }
+ if (s.equals("protocol")) {
+ ans.setNeutronLoadBalancerListenerProtocol(this.getNeutronLoadBalancerListenerProtocol());
+ }
+ if (s.equals("protocol_port")) {
+ ans.setNeutronLoadBalancerListenerProtocolPort(this.getNeutronLoadBalancerListenerProtocolPort());
+ }
+ if (s.equals("load_balancer_id")) {
+ ans.setNeutronLoadBalancerListenerLoadBalancerID(this.getNeutronLoadBalancerListenerLoadBalancerID());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setLoadBalancerListenerAdminStateIsUp(loadBalancerListenerAdminStateIsUp);
+ }
+ if (s.equals("status")) {
+ ans.setLoadBalancerListenerStatus(this.getLoadBalancerListenerStatus());
+ }
+ }
+ return ans;
+ }
+
+ @Override public String toString() {
+ return "NeutronLoadBalancerListener{" +
+ "loadBalancerListenerID='" + loadBalancerListenerID + '\'' +
+ ", neutronLoadBalancerListenerDefaultPoolID='" + neutronLoadBalancerListenerDefaultPoolID + '\'' +
+ ", loadBalancerListenerTenantID='" + loadBalancerListenerTenantID + '\'' +
+ ", loadBalancerListenerName='" + loadBalancerListenerName + '\'' +
+ ", loadBalancerListenerDescription='" + loadBalancerListenerDescription + '\'' +
+ ", loadBalancerListenerAdminStateIsUp=" + loadBalancerListenerAdminStateIsUp +
+ ", loadBalancerListenerStatus='" + loadBalancerListenerStatus + '\'' +
+ ", loadBalancerListenerIsShared=" + loadBalancerListenerIsShared +
+ ", neutronLoadBalancerListenerProtocol='" + neutronLoadBalancerListenerProtocol + '\'' +
+ ", neutronLoadBalancerListenerProtocolPort='" + neutronLoadBalancerListenerProtocolPort + '\'' +
+ ", neutronLoadBalancerListenerLoadBalancerID='" + neutronLoadBalancerListenerLoadBalancerID + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.configuration.ConfigurationObject;
+
+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 java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * OpenStack Neutron v2.0 Load Balancer as a service
+ * (LBaaS) bindings. See OpenStack Network API
+ * v2.0 Reference for description of the fields:
+ * Implemented fields are as follows:
+ *
+ * id uuid-str
+ * tenant_id uuid-str
+ * name String
+ * description String
+ * protocol String
+ * lb_algorithm String
+ * healthmonitor_id String
+ * admin_state_up Bool
+ * status String
+ * members List <String>
+ * http://docs.openstack.org/api/openstack-network/2.0/openstack-network.pdf
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerPool extends ConfigurationObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlElement(name="id")
+ String loadBalancerPoolID;
+
+ @XmlElement (name="tenant_id")
+ String loadBalancerPoolTenantID;
+
+ @XmlElement (name="name")
+ String loadBalancerPoolName;
+
+ @XmlElement (name="description")
+ String loadBalancerPoolDescription;
+
+ @XmlElement (name="protocol")
+ String loadBalancerPoolProtocol;
+
+ @XmlElement (name="lb_algorithm")
+ String loadBalancerPoolLbAlgorithm;
+
+ @XmlElement (name="healthmonitor_id")
+ String neutronLoadBalancerPoolHealthMonitorID;
+
+ @XmlElement (defaultValue="true", name="admin_state_up")
+ Boolean loadBalancerPoolAdminStateIsUp;
+
+ @XmlElement (name="status")
+ String loadBalancerPoolStatus;
+
+ @XmlElement (name="members")
+ List loadBalancerPoolMembers;
+
+ HashMap<String, NeutronLoadBalancerPoolMember> member;
+
+ public NeutronLoadBalancerPool() {
+ member = new HashMap<String, NeutronLoadBalancerPoolMember>();
+ }
+
+ public String getLoadBalancerPoolID() {
+ return loadBalancerPoolID;
+ }
+
+ public void setLoadBalancerPoolID(String loadBalancerPoolID) {
+ this.loadBalancerPoolID = loadBalancerPoolID;
+ }
+
+ public String getLoadBalancerPoolTenantID() {
+ return loadBalancerPoolTenantID;
+ }
+
+ public void setLoadBalancerPoolTenantID(String loadBalancerPoolTenantID) {
+ this.loadBalancerPoolTenantID = loadBalancerPoolTenantID;
+ }
+
+ public String getLoadBalancerPoolName() {
+ return loadBalancerPoolName;
+ }
+
+ public void setLoadBalancerPoolName(String loadBalancerPoolName) {
+ this.loadBalancerPoolName = loadBalancerPoolName;
+ }
+
+ public String getLoadBalancerPoolDescription() {
+ return loadBalancerPoolDescription;
+ }
+
+ public void setLoadBalancerPoolDescription(String loadBalancerPoolDescription) {
+ this.loadBalancerPoolDescription = loadBalancerPoolDescription;
+ }
+
+ public String getLoadBalancerPoolProtocol() {
+ return loadBalancerPoolProtocol;
+ }
+
+ public void setLoadBalancerPoolProtocol(String loadBalancerPoolProtocol) {
+ this.loadBalancerPoolProtocol = loadBalancerPoolProtocol;
+ }
+
+ public String getLoadBalancerPoolLbAlgorithm() {
+ return loadBalancerPoolLbAlgorithm;
+ }
+
+ public void setLoadBalancerPoolLbAlgorithm(String loadBalancerPoolLbAlgorithm) {
+ this.loadBalancerPoolLbAlgorithm = loadBalancerPoolLbAlgorithm;
+ }
+
+ public String getNeutronLoadBalancerPoolHealthMonitorID() {
+ return neutronLoadBalancerPoolHealthMonitorID;
+ }
+
+ public void setNeutronLoadBalancerPoolHealthMonitorID(String neutronLoadBalancerPoolHealthMonitorID) {
+ this.neutronLoadBalancerPoolHealthMonitorID = neutronLoadBalancerPoolHealthMonitorID;
+ }
+
+ public Boolean getLoadBalancerPoolAdminIsStateIsUp() {
+ return loadBalancerPoolAdminStateIsUp;
+ }
+
+ public void setLoadBalancerPoolAdminStateIsUp(Boolean loadBalancerPoolAdminStateIsUp) {
+ this.loadBalancerPoolAdminStateIsUp = loadBalancerPoolAdminStateIsUp;
+ }
+
+ public String getLoadBalancerPoolStatus() {
+ return loadBalancerPoolStatus;
+ }
+
+ public void setLoadBalancerPoolStatus(String loadBalancerPoolStatus) {
+ this.loadBalancerPoolStatus = loadBalancerPoolStatus;
+ }
+
+ public List getLoadBalancerPoolMembers() {
+ return loadBalancerPoolMembers;
+ }
+
+ public void setLoadBalancerPoolMembers(List loadBalancerPoolMembers) {
+ this.loadBalancerPoolMembers = loadBalancerPoolMembers;
+ }
+
+ public NeutronLoadBalancerPool extractFields(List<String> fields) {
+ NeutronLoadBalancerPool ans = new NeutronLoadBalancerPool();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setLoadBalancerPoolID(this.getLoadBalancerPoolID());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setLoadBalancerPoolTenantID(this.getLoadBalancerPoolTenantID());
+ }
+ if (s.equals("name")) {
+ ans.setLoadBalancerPoolName(this.getLoadBalancerPoolName());
+ }
+ if(s.equals("description")) {
+ ans.setLoadBalancerPoolDescription(this.getLoadBalancerPoolDescription());
+ }
+ if(s.equals("protocol")) {
+ ans.setLoadBalancerPoolProtocol(this.getLoadBalancerPoolProtocol());
+ }
+ if(s.equals("lb_algorithm")) {
+ ans.setLoadBalancerPoolLbAlgorithm(this.getLoadBalancerPoolLbAlgorithm());
+ }
+ if(s.equals("healthmonitor_id")) {
+ ans.setNeutronLoadBalancerPoolHealthMonitorID(this.getNeutronLoadBalancerPoolHealthMonitorID());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setLoadBalancerPoolAdminStateIsUp(loadBalancerPoolAdminStateIsUp);
+ }
+ if (s.equals("status")) {
+ ans.setLoadBalancerPoolStatus(this.getLoadBalancerPoolStatus());
+ }
+ if (s.equals("members")) {
+ ans.setLoadBalancerPoolMembers(getLoadBalancerPoolMembers());
+ }
+ }
+ return ans;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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.configuration.ConfigurationObject;
+
+import javax.xml.bind.annotation.XmlElement;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+public class NeutronLoadBalancerPoolMember extends ConfigurationObject implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * TODO: Plumb into LBaaS Pool. Members are nested underneath Pool CRUD.
+ */
+ @XmlElement (name="id")
+ String poolMemberID;
+
+ @XmlElement (name="tenant_id")
+ String poolMemberTenantID;
+
+ @XmlElement (name="address")
+ String poolMemberAddress;
+
+ @XmlElement (name="protocol_port")
+ Integer poolMemberProtoPort;
+
+ @XmlElement (name="admin_state_up")
+ Boolean poolMemberAdminStateIsUp;
+
+ @XmlElement (name="weight")
+ Integer poolMemberWeight;
+
+ @XmlElement (name="subnet_id")
+ String poolMemberSubnetID;
+
+ @XmlElement (name="status")
+ String poolMemberStatus;
+
+ public NeutronLoadBalancerPoolMember() {
+ }
+
+ public String getPoolMemberID() {
+ return poolMemberID;
+ }
+
+ public void setPoolMemberID(String poolMemberID) {
+ this.poolMemberID = poolMemberID;
+ }
+
+ public String getPoolMemberTenantID() {
+ return poolMemberTenantID;
+ }
+
+ public void setPoolMemberTenantID(String poolMemberTenantID) {
+ this.poolMemberTenantID = poolMemberTenantID;
+ }
+
+ public String getPoolMemberAddress() {
+ return poolMemberAddress;
+ }
+
+ public void setPoolMemberAddress(String poolMemberAddress) {
+ this.poolMemberAddress = poolMemberAddress;
+ }
+
+ public Integer getPoolMemberProtoPort() {
+ return poolMemberProtoPort;
+ }
+
+ public void setPoolMemberProtoPort(Integer poolMemberProtoPort) {
+ this.poolMemberProtoPort = poolMemberProtoPort;
+ }
+
+ public Boolean getPoolMemberAdminStateIsUp() {
+ return poolMemberAdminStateIsUp;
+ }
+
+ public void setPoolMemberAdminStateIsUp(Boolean poolMemberAdminStateIsUp) {
+ this.poolMemberAdminStateIsUp = poolMemberAdminStateIsUp;
+ }
+
+ public Integer getPoolMemberWeight() {
+ return poolMemberWeight;
+ }
+
+ public void setPoolMemberWeight(Integer poolMemberWeight) {
+ this.poolMemberWeight = poolMemberWeight;
+ }
+
+ public String getPoolMemberSubnetID() {
+ return poolMemberSubnetID;
+ }
+
+ public void setPoolMemberSubnetID(String poolMemberSubnetID) {
+ this.poolMemberSubnetID = poolMemberSubnetID;
+ }
+
+ public String getPoolMemberStatus() {
+ return poolMemberStatus;
+ }
+
+ public void setPoolMemberStatus(String poolMemberStatus) {
+ this.poolMemberStatus = poolMemberStatus;
+ }
+
+ public NeutronLoadBalancerPoolMember extractFields(List<String> fields) {
+ NeutronLoadBalancerPoolMember ans = new NeutronLoadBalancerPoolMember();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ ans.setPoolMemberID(this.getPoolMemberID());
+ }
+ if (s.equals("tenant_id")) {
+ ans.setPoolMemberTenantID(this.getPoolMemberTenantID());
+ }
+ if (s.equals("address")) {
+ ans.setPoolMemberAddress(this.getPoolMemberAddress());
+ }
+ if(s.equals("protocol_port")) {
+ ans.setPoolMemberProtoPort(this.getPoolMemberProtoPort());
+ }
+ if (s.equals("admin_state_up")) {
+ ans.setPoolMemberAdminStateIsUp(poolMemberAdminStateIsUp);
+ }
+ if(s.equals("weight")) {
+ ans.setPoolMemberWeight(this.getPoolMemberWeight());
+ }
+ if(s.equals("subnet_id")) {
+ ans.setPoolMemberSubnetID(this.getPoolMemberSubnetID());
+ }
+ if (s.equals("status")) {
+ ans.setPoolMemberStatus(this.getPoolMemberStatus());
+ }
+ }
+ return ans;
+ }
+ @Override public String toString() {
+ return "NeutronLoadBalancerPoolMember{" +
+ "poolMemberID='" + poolMemberID + '\'' +
+ ", poolMemberTenantID='" + poolMemberTenantID + '\'' +
+ ", poolMemberAddress='" + poolMemberAddress + '\'' +
+ ", poolMemberProtoPort=" + poolMemberProtoPort +
+ ", poolMemberAdminStateIsUp=" + poolMemberAdminStateIsUp +
+ ", poolMemberWeight=" + poolMemberWeight +
+ ", poolMemberSubnetID='" + poolMemberSubnetID + '\'' +
+ ", poolMemberStatus='" + poolMemberStatus + '\'' +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
+
+import javax.xml.bind.annotation.XmlElement;
+import java.util.List;
+
+public class INeutronLoadBalancerPoolMemberRequest {
+
+ /**
+ * See OpenStack Network API v2.0 Reference for description of
+ * http://docs.openstack.org/api/openstack-network/2.0/content/
+ */
+
+ @XmlElement(name="member")
+ NeutronLoadBalancerPoolMember singletonLoadBalancerPoolMember;
+
+ @XmlElement(name="members")
+ List<NeutronLoadBalancerPoolMember> bulkRequest;
+
+ INeutronLoadBalancerPoolMemberRequest() {
+ }
+
+ INeutronLoadBalancerPoolMemberRequest(List<NeutronLoadBalancerPoolMember> bulk) {
+ bulkRequest = bulk;
+ singletonLoadBalancerPoolMember = null;
+ }
+
+ INeutronLoadBalancerPoolMemberRequest(NeutronLoadBalancerPoolMember group) {
+ singletonLoadBalancerPoolMember = group;
+ }
+
+ public List<NeutronLoadBalancerPoolMember> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronLoadBalancerPoolMember getSingleton() {
+ return singletonLoadBalancerPoolMember;
+ }
+
+ public boolean isSingleton() {
+ return (singletonLoadBalancerPoolMember != null);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerHealthMonitorAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerHealthMonitorCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerHealthMonitor;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for Load Balancer HealthMonitor.<br>
+ * This class provides REST APIs for managing neutron LoadBalancerHealthMonitor
+ *
+ * <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("/healthmonitors")
+public class NeutronLoadBalancerHealthMonitorNorthbound {
+ private static final Logger logger = LoggerFactory.getLogger(NeutronLoadBalancer.class);
+
+ private NeutronLoadBalancerHealthMonitor extractFields(NeutronLoadBalancerHealthMonitor o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all LoadBalancerHealthMonitor */
+ @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 listGroups(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // OpenStack LoadBalancerHealthMonitor attributes
+ @QueryParam("id") String queryLoadBalancerHealthMonitorID,
+ @QueryParam("tenant_id") String queryLoadBalancerHealthMonitorTenantID,
+ // TODO "type" is being a property by the JSON parser.
+ @QueryParam("type") String queryLoadBalancerHealthMonitorType,
+ @QueryParam("delay") Integer queryLoadBalancerHealthMonitorDelay,
+ @QueryParam("timeout") Integer queryLoadBalancerHealthMonitorTimeout,
+ @QueryParam("max_retries") Integer queryLoadBalancerHealthMonitorMaxRetries,
+ @QueryParam("http_method") String queryLoadBalancerHealthMonitorHttpMethod,
+ @QueryParam("url_path") String queryLoadBalancerHealthMonitorUrlPath,
+ @QueryParam("expected_codes") String queryLoadBalancerHealthMonitorExpectedCodes,
+ @QueryParam("admin_state_up") Boolean queryLoadBalancerHealthMonitorIsAdminStateUp,
+ @QueryParam("status") String queryLoadBalancerHealthMonitorStatus,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronLoadBalancerHealthMonitorCRUD loadBalancerHealthMonitorInterface = NeutronCRUDInterfaces
+ .getINeutronLoadBalancerHealthMonitorCRUD(this);
+ if (loadBalancerHealthMonitorInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerHealthMonitor CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronLoadBalancerHealthMonitor> allLoadBalancerHealthMonitors = loadBalancerHealthMonitorInterface.getAllNeutronLoadBalancerHealthMonitors();
+ List<NeutronLoadBalancerHealthMonitor> ans = new ArrayList<NeutronLoadBalancerHealthMonitor>();
+ Iterator<NeutronLoadBalancerHealthMonitor> i = allLoadBalancerHealthMonitors.iterator();
+ while (i.hasNext()) {
+ NeutronLoadBalancerHealthMonitor nsg = i.next();
+ if ((queryLoadBalancerHealthMonitorID == null ||
+ queryLoadBalancerHealthMonitorID.equals(nsg.getLoadBalancerHealthMonitorID())) &&
+ (queryLoadBalancerHealthMonitorTenantID == null ||
+ queryLoadBalancerHealthMonitorTenantID.equals
+ (nsg.getLoadBalancerHealthMonitorTenantID())) &&
+ (queryLoadBalancerHealthMonitorType == null ||
+ queryLoadBalancerHealthMonitorType.equals
+ (nsg.getLoadBalancerHealthMonitorType())) &&
+ (queryLoadBalancerHealthMonitorDelay == null ||
+ queryLoadBalancerHealthMonitorDelay.equals
+ (nsg.getLoadBalancerHealthMonitorDelay())) &&
+ (queryLoadBalancerHealthMonitorTimeout == null ||
+ queryLoadBalancerHealthMonitorTimeout.equals
+ (nsg.getLoadBalancerHealthMonitorTimeout())) &&
+ (queryLoadBalancerHealthMonitorMaxRetries == null ||
+ queryLoadBalancerHealthMonitorMaxRetries.equals
+ (nsg.getLoadBalancerHealthMonitorMaxRetries())) &&
+ (queryLoadBalancerHealthMonitorHttpMethod == null ||
+ queryLoadBalancerHealthMonitorHttpMethod.equals
+ (nsg.getLoadBalancerHealthMonitorHttpMethod())) &&
+ (queryLoadBalancerHealthMonitorUrlPath == null ||
+ queryLoadBalancerHealthMonitorUrlPath.equals
+ (nsg.getLoadBalancerHealthMonitorUrlPath())) &&
+ (queryLoadBalancerHealthMonitorExpectedCodes == null ||
+ queryLoadBalancerHealthMonitorExpectedCodes.equals
+ (nsg.getLoadBalancerHealthMonitorExpectedCodes())) &&
+ (queryLoadBalancerHealthMonitorIsAdminStateUp == null ||
+ queryLoadBalancerHealthMonitorIsAdminStateUp.equals
+ (nsg.getLoadBalancerHealthMonitorAdminStateIsUp())) &&
+ (queryLoadBalancerHealthMonitorStatus == null ||
+ queryLoadBalancerHealthMonitorStatus.equals
+ (nsg.getLoadBalancerHealthMonitorStatus()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsg,fields));
+ } else {
+ ans.add(nsg);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronLoadBalancerHealthMonitorRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific LoadBalancerHealthMonitor */
+
+ @Path("{loadBalancerHealthMonitorID}")
+ @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 showLoadBalancerHealthMonitor(@PathParam("loadBalancerHealthMonitorID") String loadBalancerHealthMonitorID,
+ // return fields
+ @QueryParam("fields") List<String> fields) {
+ INeutronLoadBalancerHealthMonitorCRUD loadBalancerHealthMonitorInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerHealthMonitorCRUD(this);
+ if (loadBalancerHealthMonitorInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerHealthMonitor CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!loadBalancerHealthMonitorInterface.neutronLoadBalancerHealthMonitorExists(loadBalancerHealthMonitorID)) {
+ throw new ResourceNotFoundException("LoadBalancerHealthMonitor UUID does not exist.");
+ }
+ if (fields.size() > 0) {
+ NeutronLoadBalancerHealthMonitor ans = loadBalancerHealthMonitorInterface.getNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID);
+ return Response.status(200).entity(
+ new NeutronLoadBalancerHealthMonitorRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(new NeutronLoadBalancerHealthMonitorRequest(loadBalancerHealthMonitorInterface.getNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID))).build();
+ }
+ }
+
+ /**
+ * Creates new LoadBalancerHealthMonitor */
+
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createLoadBalancerHealthMonitors(final NeutronLoadBalancerHealthMonitorRequest input) {
+ INeutronLoadBalancerHealthMonitorCRUD loadBalancerHealthMonitorInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerHealthMonitorCRUD(this);
+ if (loadBalancerHealthMonitorInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerHealthMonitor CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronLoadBalancerHealthMonitor singleton = input.getSingleton();
+
+ /*
+ * Verify that the LoadBalancerHealthMonitor doesn't already exist.
+ */
+ if (loadBalancerHealthMonitorInterface.neutronLoadBalancerHealthMonitorExists(singleton.getLoadBalancerHealthMonitorID())) {
+ throw new BadRequestException("LoadBalancerHealthMonitor UUID already exists");
+ }
+ loadBalancerHealthMonitorInterface.addNeutronLoadBalancerHealthMonitor(singleton);
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerHealthMonitorAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ int status = service.canCreateNeutronLoadBalancerHealthMonitor(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ loadBalancerHealthMonitorInterface.addNeutronLoadBalancerHealthMonitor(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ service.neutronLoadBalancerHealthMonitorCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronLoadBalancerHealthMonitor> bulk = input.getBulk();
+ Iterator<NeutronLoadBalancerHealthMonitor> i = bulk.iterator();
+ HashMap<String, NeutronLoadBalancerHealthMonitor> testMap = new HashMap<String, NeutronLoadBalancerHealthMonitor>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerHealthMonitorAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronLoadBalancerHealthMonitor test = i.next();
+
+ /*
+ * Verify that the firewall policy doesn't already exist
+ */
+
+ if (loadBalancerHealthMonitorInterface
+ .neutronLoadBalancerHealthMonitorExists(test.getLoadBalancerHealthMonitorID())) {
+ throw new BadRequestException("LoadBalancerHealthMonitor UUID already is already created");
+ }
+ if (testMap.containsKey(test.getLoadBalancerHealthMonitorID())) {
+ throw new BadRequestException("LoadBalancerHealthMonitor UUID already exists");
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ int status = service.canCreateNeutronLoadBalancerHealthMonitor(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()) {
+ NeutronLoadBalancerHealthMonitor test = i.next();
+ loadBalancerHealthMonitorInterface.addNeutronLoadBalancerHealthMonitor(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ service.neutronLoadBalancerHealthMonitorCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a LoadBalancerHealthMonitor Policy
+ */
+ @Path("{loadBalancerHealthMonitorID}")
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateLoadBalancerHealthMonitor(
+ @PathParam("loadBalancerHealthMonitorID") String loadBalancerHealthMonitorID,
+ final NeutronLoadBalancerHealthMonitorRequest input) {
+ INeutronLoadBalancerHealthMonitorCRUD loadBalancerHealthMonitorInterface = NeutronCRUDInterfaces
+ .getINeutronLoadBalancerHealthMonitorCRUD(this);
+ if (loadBalancerHealthMonitorInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerHealthMonitor CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the LoadBalancerHealthMonitor exists and there is only one delta provided
+ */
+ if (!loadBalancerHealthMonitorInterface.neutronLoadBalancerHealthMonitorExists(loadBalancerHealthMonitorID)) {
+ throw new ResourceNotFoundException("LoadBalancerHealthMonitor UUID does not exist.");
+ }
+ if (!input.isSingleton()) {
+ throw new BadRequestException("Only singleton edit supported");
+ }
+ NeutronLoadBalancerHealthMonitor delta = input.getSingleton();
+ NeutronLoadBalancerHealthMonitor original = loadBalancerHealthMonitorInterface
+ .getNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID);
+
+ /*
+ * updates restricted by Neutron
+ */
+ if (delta.getLoadBalancerHealthMonitorID() != null ||
+ delta.getLoadBalancerHealthMonitorTenantID() != null ||
+ delta.getLoadBalancerHealthMonitorType() != null ||
+ delta.getLoadBalancerHealthMonitorDelay() != null ||
+ delta.getLoadBalancerHealthMonitorTimeout() != null ||
+ delta.getLoadBalancerHealthMonitorMaxRetries() != null ||
+ delta.getLoadBalancerHealthMonitorHttpMethod() != null ||
+ delta.getLoadBalancerHealthMonitorUrlPath() != null ||
+ delta.getLoadBalancerHealthMonitorExpectedCodes() != null ||
+ delta.getLoadBalancerHealthMonitorAdminStateIsUp() != null ||
+ delta.getLoadBalancerHealthMonitorStatus() != null) {
+ throw new BadRequestException("Attribute edit blocked by Neutron");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerHealthMonitorAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ int status = service.canUpdateNeutronLoadBalancerHealthMonitor(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ loadBalancerHealthMonitorInterface.updateNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID, delta);
+ NeutronLoadBalancerHealthMonitor updatedLoadBalancerHealthMonitor = loadBalancerHealthMonitorInterface
+ .getNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ service.neutronLoadBalancerHealthMonitorUpdated(updatedLoadBalancerHealthMonitor);
+ }
+ }
+ return Response.status(200).entity(new NeutronLoadBalancerHealthMonitorRequest
+ (loadBalancerHealthMonitorInterface.getNeutronLoadBalancerHealthMonitor
+ (loadBalancerHealthMonitorID))).build();
+ }
+
+
+
+ /**
+ * Deletes a LoadBalancerHealthMonitor
+ * */
+ @Path("{loadBalancerHealthMonitorID}")
+ @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 deleteLoadBalancerHealthMonitor(
+ @PathParam("loadBalancerHealthMonitorID") String loadBalancerHealthMonitorID) {
+ INeutronLoadBalancerHealthMonitorCRUD loadBalancerHealthMonitorInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerHealthMonitorCRUD(this);
+ if (loadBalancerHealthMonitorInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerHealthMonitor CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ /*
+ * verify the LoadBalancerHealthMonitor exists and it isn't currently in use
+ */
+ if (!loadBalancerHealthMonitorInterface.neutronLoadBalancerHealthMonitorExists(loadBalancerHealthMonitorID)) {
+ throw new ResourceNotFoundException("LoadBalancerHealthMonitor UUID does not exist.");
+ }
+ if (loadBalancerHealthMonitorInterface.neutronLoadBalancerHealthMonitorInUse(loadBalancerHealthMonitorID)) {
+ return Response.status(409).build();
+ }
+ NeutronLoadBalancerHealthMonitor singleton = loadBalancerHealthMonitorInterface.getNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerHealthMonitorAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ int status = service.canDeleteNeutronLoadBalancerHealthMonitor(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ loadBalancerHealthMonitorInterface.removeNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance;
+ service.neutronLoadBalancerHealthMonitorDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerHealthMonitor;
+
+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 java.util.List;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerHealthMonitorRequest {
+ /**
+ * See OpenStack Network API v2.0 Reference for description of
+ * http://docs.openstack.org/api/openstack-network/2.0/content/
+ */
+
+ @XmlElement(name="healthmonitor")
+ NeutronLoadBalancerHealthMonitor singletonLoadBalancerHealthMonitor;
+
+ @XmlElement(name="healthmonitors")
+ List<NeutronLoadBalancerHealthMonitor> bulkRequest;
+
+ NeutronLoadBalancerHealthMonitorRequest() {
+ }
+
+ NeutronLoadBalancerHealthMonitorRequest(List<NeutronLoadBalancerHealthMonitor> bulk) {
+ bulkRequest = bulk;
+ singletonLoadBalancerHealthMonitor = null;
+ }
+
+ NeutronLoadBalancerHealthMonitorRequest(NeutronLoadBalancerHealthMonitor group) {
+ singletonLoadBalancerHealthMonitor = group;
+ }
+
+ public List<NeutronLoadBalancerHealthMonitor> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronLoadBalancerHealthMonitor getSingleton() {
+ return singletonLoadBalancerHealthMonitor;
+ }
+
+ public boolean isSingleton() {
+ return (singletonLoadBalancerHealthMonitor != null);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerListenerAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerListenerCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerListener;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for LoadBalancerListener Policies.<br>
+ * This class provides REST APIs for managing neutron LoadBalancerListener Policies
+ *
+ * <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("/listeners")
+public class NeutronLoadBalancerListenerNorthbound {
+
+ private NeutronLoadBalancerListener extractFields(NeutronLoadBalancerListener o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all LoadBalancerListener */
+ @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 listGroups(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // OpenStack LoadBalancerListener attributes
+ @QueryParam("id") String queryLoadBalancerListenerID,
+ @QueryParam("default_pool_id") String queryLoadBalancerListenerDefaultPoolID,
+ @QueryParam("tenant_id") String queryLoadBalancerListenerTenantID,
+ @QueryParam("name") String queryLoadBalancerListenerName,
+ @QueryParam("description") String queryLoadBalancerListenerDescription,
+ @QueryParam("shared") String queryLoadBalancerListenerIsShared,
+ @QueryParam("protocol") String queryLoadBalancerListenerProtocol,
+ @QueryParam("protocol_port") String queryLoadBalancerListenerProtocolPort,
+ @QueryParam("load_balancer_id") String queryLoadBalancerListenerLoadBalancerID,
+ @QueryParam("admin_state_up") String queryLoadBalancerListenerAdminIsUp,
+ @QueryParam("status") String queryLoadBalancerListenerStatus,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronLoadBalancerListenerCRUD loadBalancerListenerInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerListenerCRUD(this);
+ // INeutronLoadBalancerListenerRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerListenerRuleCRUD(this);
+
+ if (loadBalancerListenerInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerListener CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronLoadBalancerListener> allLoadBalancerListeners = loadBalancerListenerInterface.getAllNeutronLoadBalancerListeners();
+ // List<NeutronLoadBalancerListenerRule> allLoadBalancerListenerRules = firewallRuleInterface.getAllNeutronLoadBalancerListenerRules();
+ List<NeutronLoadBalancerListener> ans = new ArrayList<NeutronLoadBalancerListener>();
+ // List<NeutronLoadBalancerListenerRule> rules = new ArrayList<NeutronLoadBalancerListenerRule>();
+ Iterator<NeutronLoadBalancerListener> i = allLoadBalancerListeners.iterator();
+ while (i.hasNext()) {
+ NeutronLoadBalancerListener nsg = i.next();
+ if ((queryLoadBalancerListenerID == null ||
+ queryLoadBalancerListenerID.equals(nsg.getLoadBalancerListenerID())) &&
+ (queryLoadBalancerListenerDefaultPoolID == null ||
+ queryLoadBalancerListenerDefaultPoolID.equals(nsg.getNeutronLoadBalancerListenerDefaultPoolID())) &&
+ (queryLoadBalancerListenerTenantID == null ||
+ queryLoadBalancerListenerTenantID.equals(nsg.getLoadBalancerListenerTenantID())) &&
+ (queryLoadBalancerListenerName == null ||
+ queryLoadBalancerListenerName.equals(nsg.getLoadBalancerListenerName())) &&
+ (queryLoadBalancerListenerDescription == null ||
+ queryLoadBalancerListenerDescription.equals(nsg.getLoadBalancerListenerDescription())) &&
+ (queryLoadBalancerListenerIsShared == null ||
+ queryLoadBalancerListenerIsShared.equals(nsg.getLoadBalancerListenerIsShared())) &&
+ (queryLoadBalancerListenerProtocol == null ||
+ queryLoadBalancerListenerProtocol.equals(nsg.getNeutronLoadBalancerListenerProtocol())) &&
+ (queryLoadBalancerListenerProtocolPort == null ||
+ queryLoadBalancerListenerProtocolPort.equals(nsg.getNeutronLoadBalancerListenerProtocolPort())) &&
+ (queryLoadBalancerListenerLoadBalancerID == null ||
+ queryLoadBalancerListenerLoadBalancerID.equals(nsg.getNeutronLoadBalancerListenerLoadBalancerID())) &&
+ (queryLoadBalancerListenerAdminIsUp == null ||
+ queryLoadBalancerListenerAdminIsUp.equals(nsg.getLoadBalancerListenerAdminStateIsUp())) &&
+ (queryLoadBalancerListenerStatus == null ||
+ queryLoadBalancerListenerStatus.equals(nsg.getLoadBalancerListenerStatus()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsg,fields));
+ } else {
+ ans.add(nsg);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronLoadBalancerListenerRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific LoadBalancerListener */
+
+ @Path("{loadBalancerListenerID}")
+ @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 showLoadBalancerListener(@PathParam("loadBalancerListenerID") String loadBalancerListenerID,
+ // return fields
+ @QueryParam("fields") List<String> fields) {
+ INeutronLoadBalancerListenerCRUD loadBalancerListenerInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerListenerCRUD(this);
+ if (loadBalancerListenerInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerListener CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!loadBalancerListenerInterface.neutronLoadBalancerListenerExists(loadBalancerListenerID)) {
+ throw new ResourceNotFoundException("LoadBalancerListener UUID does not exist.");
+ }
+ if (fields.size() > 0) {
+ NeutronLoadBalancerListener ans = loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID);
+ return Response.status(200).entity(
+ new NeutronLoadBalancerListenerRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(new NeutronLoadBalancerListenerRequest(loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID))).build();
+ }
+ }
+
+ /**
+ * Creates new LoadBalancerListener */
+
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createLoadBalancerListeners(final NeutronLoadBalancerListenerRequest input) {
+ INeutronLoadBalancerListenerCRUD loadBalancerListenerInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerListenerCRUD(this);
+ if (loadBalancerListenerInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerListener CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronLoadBalancerListener singleton = input.getSingleton();
+
+ /*
+ * Verify that the LoadBalancerListener doesn't already exist.
+ */
+ if (loadBalancerListenerInterface.neutronLoadBalancerListenerExists(singleton.getLoadBalancerListenerID())) {
+ throw new BadRequestException("LoadBalancerListener UUID already exists");
+ }
+ loadBalancerListenerInterface.addNeutronLoadBalancerListener(singleton);
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerListenerAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ int status = service.canCreateNeutronLoadBalancerListener(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ loadBalancerListenerInterface.addNeutronLoadBalancerListener(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ service.neutronLoadBalancerListenerCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronLoadBalancerListener> bulk = input.getBulk();
+ Iterator<NeutronLoadBalancerListener> i = bulk.iterator();
+ HashMap<String, NeutronLoadBalancerListener> testMap = new HashMap<String, NeutronLoadBalancerListener>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerListenerAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronLoadBalancerListener test = i.next();
+
+ /*
+ * Verify that the firewall policy doesn't already exist
+ */
+
+ if (loadBalancerListenerInterface.neutronLoadBalancerListenerExists(test.getLoadBalancerListenerID())) {
+ throw new BadRequestException("LoadBalancerListener UUID already is already created");
+ }
+ if (testMap.containsKey(test.getLoadBalancerListenerID())) {
+ throw new BadRequestException("LoadBalancerListener UUID already exists");
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ int status = service.canCreateNeutronLoadBalancerListener(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()) {
+ NeutronLoadBalancerListener test = i.next();
+ loadBalancerListenerInterface.addNeutronLoadBalancerListener(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ service.neutronLoadBalancerListenerCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a LoadBalancerListener Policy
+ */
+ @Path("{loadBalancerListenerID}")
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateLoadBalancerListener(
+ @PathParam("loadBalancerListenerID") String loadBalancerListenerID, final NeutronLoadBalancerListenerRequest input) {
+ INeutronLoadBalancerListenerCRUD loadBalancerListenerInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerListenerCRUD(this);
+ if (loadBalancerListenerInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerListener CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the LoadBalancerListener exists and there is only one delta provided
+ */
+ if (!loadBalancerListenerInterface.neutronLoadBalancerListenerExists(loadBalancerListenerID)) {
+ throw new ResourceNotFoundException("LoadBalancerListener UUID does not exist.");
+ }
+ if (!input.isSingleton()) {
+ throw new BadRequestException("Only singleton edit supported");
+ }
+ NeutronLoadBalancerListener delta = input.getSingleton();
+ NeutronLoadBalancerListener original = loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID);
+
+ /*
+ * updates restricted by Neutron
+ */
+ if (delta.getLoadBalancerListenerID() != null ||
+ delta.getNeutronLoadBalancerListenerDefaultPoolID() != null ||
+ delta.getLoadBalancerListenerTenantID() != null ||
+ delta.getLoadBalancerListenerName() != null ||
+ delta.getLoadBalancerListenerDescription() != null ||
+ delta.getLoadBalancerListenerIsShared() != null ||
+ delta.getNeutronLoadBalancerListenerProtocol() != null ||
+ delta.getNeutronLoadBalancerListenerProtocolPort() != null ||
+ delta.getNeutronLoadBalancerListenerLoadBalancerID() != null ||
+ delta.getLoadBalancerListenerAdminStateIsUp() != null ||
+ delta.getLoadBalancerListenerStatus() != null) {
+ throw new BadRequestException("Attribute edit blocked by Neutron");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerListenerAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ int status = service.canUpdateNeutronLoadBalancerListener(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ loadBalancerListenerInterface.updateNeutronLoadBalancerListener(loadBalancerListenerID, delta);
+ NeutronLoadBalancerListener updatedLoadBalancerListener = loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ service.neutronLoadBalancerListenerUpdated(updatedLoadBalancerListener);
+ }
+ }
+ return Response.status(200).entity(new NeutronLoadBalancerListenerRequest(loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID))).build();
+ }
+
+ /**
+ * Deletes a LoadBalancerListener */
+
+ @Path("{loadBalancerListenerID}")
+ @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 deleteLoadBalancerListener(
+ @PathParam("loadBalancerListenerID") String loadBalancerListenerID) {
+ INeutronLoadBalancerListenerCRUD loadBalancerListenerInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerListenerCRUD(this);
+ if (loadBalancerListenerInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerListener CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the LoadBalancerListener exists and it isn't currently in use
+ */
+ if (!loadBalancerListenerInterface.neutronLoadBalancerListenerExists(loadBalancerListenerID)) {
+ throw new ResourceNotFoundException("LoadBalancerListener UUID does not exist.");
+ }
+ if (loadBalancerListenerInterface.neutronLoadBalancerListenerInUse(loadBalancerListenerID)) {
+ return Response.status(409).build();
+ }
+ NeutronLoadBalancerListener singleton = loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerListenerAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ int status = service.canDeleteNeutronLoadBalancerListener(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ loadBalancerListenerInterface.removeNeutronLoadBalancerListener(loadBalancerListenerID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance;
+ service.neutronLoadBalancerListenerDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerListener;
+
+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 java.util.List;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerListenerRequest {
+ /**
+ * See OpenStack Network API v2.0 Reference for description of
+ * http://docs.openstack.org/api/openstack-network/2.0/content/
+ */
+
+ @XmlElement(name="listener")
+ NeutronLoadBalancerListener singletonLoadBalancerListener;
+
+ @XmlElement(name="listeners")
+ List<NeutronLoadBalancerListener> bulkRequest;
+
+ NeutronLoadBalancerListenerRequest() {
+ }
+
+ NeutronLoadBalancerListenerRequest(List<NeutronLoadBalancerListener> bulk) {
+ bulkRequest = bulk;
+ singletonLoadBalancerListener = null;
+ }
+
+ NeutronLoadBalancerListenerRequest(NeutronLoadBalancerListener group) {
+ singletonLoadBalancerListener = group;
+ }
+
+ public List<NeutronLoadBalancerListener> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronLoadBalancerListener getSingleton() {
+ return singletonLoadBalancerListener;
+ }
+
+ public boolean isSingleton() {
+ return (singletonLoadBalancerListener != null);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for LoadBalancer Policies.<br>
+ * This class provides REST APIs for managing neutron LoadBalancer Policies
+ *
+ * <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("/loadbalancers")
+public class NeutronLoadBalancerNorthbound {
+
+ private NeutronLoadBalancer extractFields(NeutronLoadBalancer o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all LoadBalancer */
+ @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 listGroups(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // OpenStack LoadBalancer attributes
+ @QueryParam("id") String queryLoadBalancerID,
+ @QueryParam("tenant_id") String queryLoadBalancerTenantID,
+ @QueryParam("name") String queryLoadBalancerName,
+ @QueryParam("description") String queryLoadBalancerDescription,
+ @QueryParam("status") String queryLoadBalancerStatus,
+ @QueryParam("vip_address") String queryLoadBalancerVipAddress,
+ @QueryParam("vip_subnet") String queryLoadBalancerVipSubnet,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
+ this);
+ // INeutronLoadBalancerRuleCRUD firewallRuleInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerRuleCRUD(this);
+
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronLoadBalancer> allLoadBalancers = loadBalancerPoolInterface.getAllNeutronLoadBalancers();
+ // List<NeutronLoadBalancerRule> allLoadBalancerRules = firewallRuleInterface.getAllNeutronLoadBalancerRules();
+ List<NeutronLoadBalancer> ans = new ArrayList<NeutronLoadBalancer>();
+ // List<NeutronLoadBalancerRule> rules = new ArrayList<NeutronLoadBalancerRule>();
+ Iterator<NeutronLoadBalancer> i = allLoadBalancers.iterator();
+ while (i.hasNext()) {
+ NeutronLoadBalancer nsg = i.next();
+ if ((queryLoadBalancerID == null ||
+ queryLoadBalancerID.equals(nsg.getLoadBalancerID())) &&
+ (queryLoadBalancerTenantID == null ||
+ queryLoadBalancerTenantID.equals(nsg.getLoadBalancerTenantID())) &&
+ (queryLoadBalancerName == null ||
+ queryLoadBalancerName.equals(nsg.getLoadBalancerName())) &&
+ (queryLoadBalancerDescription == null ||
+ queryLoadBalancerDescription.equals(nsg.getLoadBalancerDescription())) &&
+ (queryLoadBalancerVipAddress == null ||
+ queryLoadBalancerVipAddress.equals(nsg.getLoadBalancerVipAddress())) &&
+ (queryLoadBalancerVipSubnet == null ||
+ queryLoadBalancerVipSubnet.equals(nsg.getLoadBalancerVipSubnetID()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsg,fields));
+ } else {
+ ans.add(nsg);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronLoadBalancerRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific LoadBalancer */
+
+ @Path("{loadBalancerPoolID}")
+ @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 showLoadBalancer(@PathParam("loadBalancerPoolID") String loadBalancerPoolID,
+ // return fields
+ @QueryParam("fields") List<String> fields) {
+ INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
+ this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!loadBalancerPoolInterface.neutronLoadBalancerExists(loadBalancerPoolID)) {
+ throw new ResourceNotFoundException("LoadBalancer UUID does not exist.");
+ }
+ if (fields.size() > 0) {
+ NeutronLoadBalancer ans = loadBalancerPoolInterface.getNeutronLoadBalancer(loadBalancerPoolID);
+ return Response.status(200).entity(
+ new NeutronLoadBalancerRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(new NeutronLoadBalancerRequest(loadBalancerPoolInterface.getNeutronLoadBalancer(
+ loadBalancerPoolID))).build();
+ }
+ }
+
+ /**
+ * Creates new LoadBalancer */
+
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createLoadBalancers(final NeutronLoadBalancerRequest input) {
+ INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
+ this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronLoadBalancer singleton = input.getSingleton();
+
+ /*
+ * Verify that the LoadBalancer doesn't already exist.
+ */
+ if (loadBalancerPoolInterface.neutronLoadBalancerExists(singleton.getLoadBalancerID())) {
+ throw new BadRequestException("LoadBalancer UUID already exists");
+ }
+ loadBalancerPoolInterface.addNeutronLoadBalancer(singleton);
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ int status = service.canCreateNeutronLoadBalancer(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ loadBalancerPoolInterface.addNeutronLoadBalancer(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ service.neutronLoadBalancerCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronLoadBalancer> bulk = input.getBulk();
+ Iterator<NeutronLoadBalancer> i = bulk.iterator();
+ HashMap<String, NeutronLoadBalancer> testMap = new HashMap<String, NeutronLoadBalancer>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronLoadBalancer test = i.next();
+
+ /*
+ * Verify that the firewall policy doesn't already exist
+ */
+
+ if (loadBalancerPoolInterface.neutronLoadBalancerExists(test.getLoadBalancerID())) {
+ throw new BadRequestException("Load Balancer Pool UUID already is already created");
+ }
+ if (testMap.containsKey(test.getLoadBalancerID())) {
+ throw new BadRequestException("Load Balancer Pool UUID already exists");
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ int status = service.canCreateNeutronLoadBalancer(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()) {
+ NeutronLoadBalancer test = i.next();
+ loadBalancerPoolInterface.addNeutronLoadBalancer(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ service.neutronLoadBalancerCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a LoadBalancer Policy
+ */
+ @Path("{loadBalancerPoolID}")
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateLoadBalancer(
+ @PathParam("loadBalancerPoolID") String loadBalancerPoolID, final NeutronLoadBalancerRequest input) {
+ INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
+ this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the LoadBalancer exists and there is only one delta provided
+ */
+ if (!loadBalancerPoolInterface.neutronLoadBalancerExists(loadBalancerPoolID)) {
+ throw new ResourceNotFoundException("LoadBalancer UUID does not exist.");
+ }
+ if (!input.isSingleton()) {
+ throw new BadRequestException("Only singleton edit supported");
+ }
+ NeutronLoadBalancer delta = input.getSingleton();
+ NeutronLoadBalancer original = loadBalancerPoolInterface.getNeutronLoadBalancer(loadBalancerPoolID);
+
+ /*
+ * updates restricted by Neutron
+ */
+ if (delta.getLoadBalancerID() != null ||
+ delta.getLoadBalancerTenantID() != null ||
+ delta.getLoadBalancerName() != null ||
+ delta.getLoadBalancerDescription() != null ||
+ delta.getLoadBalancerStatus() != null ||
+ delta.getLoadBalancerVipAddress() != null ||
+ delta.getLoadBalancerVipSubnetID() != null) {
+ throw new BadRequestException("Attribute edit blocked by Neutron");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ int status = service.canUpdateNeutronLoadBalancer(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ loadBalancerPoolInterface.updateNeutronLoadBalancer(loadBalancerPoolID, delta);
+ NeutronLoadBalancer updatedLoadBalancer = loadBalancerPoolInterface.getNeutronLoadBalancer(
+ loadBalancerPoolID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ service.neutronLoadBalancerUpdated(updatedLoadBalancer);
+ }
+ }
+ return Response.status(200).entity(new NeutronLoadBalancerRequest(loadBalancerPoolInterface.getNeutronLoadBalancer(
+ loadBalancerPoolID))).build();
+ }
+
+ /**
+ * Deletes a LoadBalancer */
+
+ @Path("{loadBalancerPoolID}")
+ @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 deleteLoadBalancer(
+ @PathParam("loadBalancerPoolID") String loadBalancerPoolID) {
+ INeutronLoadBalancerCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerCRUD(
+ this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancer CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the LoadBalancer exists and it isn't currently in use
+ */
+ if (!loadBalancerPoolInterface.neutronLoadBalancerExists(loadBalancerPoolID)) {
+ throw new ResourceNotFoundException("LoadBalancer UUID does not exist.");
+ }
+ if (loadBalancerPoolInterface.neutronLoadBalancerInUse(loadBalancerPoolID)) {
+ return Response.status(409).build();
+ }
+ NeutronLoadBalancer singleton = loadBalancerPoolInterface.getNeutronLoadBalancer(loadBalancerPoolID);
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ int status = service.canDeleteNeutronLoadBalancer(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ loadBalancerPoolInterface.removeNeutronLoadBalancer(loadBalancerPoolID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance;
+ service.neutronLoadBalancerDeleted(singleton);
+ }
+ }
+ return Response.status(204).build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolMemberCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPoolMember;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+
+@Path("/pools/{loadBalancerPoolID}/members")
+public class NeutronLoadBalancerPoolMembersNorthbound {
+
+ private NeutronLoadBalancerPoolMember extractFields(NeutronLoadBalancerPoolMember o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+/**
+ * Returns a list of all LoadBalancerPool
+ */
+@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 listMembers(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // OpenStack LoadBalancerPool attributes
+ @QueryParam("id") String queryLoadBalancerPoolMemberID,
+ @QueryParam("tenant_id") String queryLoadBalancerPoolMemberTenantID,
+ @QueryParam("address") String queryLoadBalancerPoolMemberAddress,
+ @QueryParam("protocol_port") String queryLoadBalancerPoolMemberProtoPort,
+ @QueryParam("admin_state_up") String queryLoadBalancerPoolMemberAdminStateUp,
+ @QueryParam("weight") String queryLoadBalancerPoolMemberWeight,
+ @QueryParam("subnet_id") String queryLoadBalancerPoolMemberSubnetID,
+ @QueryParam("status") String queryLoadBalancerPoolMemberStatus,
+
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+) {
+ INeutronLoadBalancerPoolMemberCRUD loadBalancerPoolMemberInterface = NeutronCRUDInterfaces
+ .getINeutronLoadBalancerPoolMemberCRUD(this);
+ if (loadBalancerPoolMemberInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerPool CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronLoadBalancerPoolMember> allLoadBalancerPoolMembers = loadBalancerPoolMemberInterface
+ .getAllNeutronLoadBalancerPoolMembers();
+ List<NeutronLoadBalancerPoolMember> ans = new ArrayList<NeutronLoadBalancerPoolMember>();
+ Iterator<NeutronLoadBalancerPoolMember> i = allLoadBalancerPoolMembers.iterator();
+ while (i.hasNext()) {
+ NeutronLoadBalancerPoolMember nsg = i.next();
+ if ((queryLoadBalancerPoolMemberID == null ||
+ queryLoadBalancerPoolMemberID.equals(nsg.getPoolMemberID())) &&
+ (queryLoadBalancerPoolMemberTenantID == null ||
+ queryLoadBalancerPoolMemberTenantID.equals(nsg.getPoolMemberTenantID())) &&
+ (queryLoadBalancerPoolMemberAddress == null ||
+ queryLoadBalancerPoolMemberAddress.equals(nsg.getPoolMemberAddress())) &&
+ (queryLoadBalancerPoolMemberAdminStateUp == null ||
+ queryLoadBalancerPoolMemberAdminStateUp.equals(nsg.getPoolMemberAdminStateIsUp())) &&
+ (queryLoadBalancerPoolMemberWeight == null ||
+ queryLoadBalancerPoolMemberWeight.equals(nsg.getPoolMemberWeight())) &&
+ (queryLoadBalancerPoolMemberSubnetID == null ||
+ queryLoadBalancerPoolMemberSubnetID.equals(nsg.getPoolMemberSubnetID())) &&
+ (queryLoadBalancerPoolMemberStatus == null ||
+ queryLoadBalancerPoolMemberStatus.equals(nsg.getPoolMemberStatus()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsg, fields));
+ } else {
+ ans.add(nsg);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new INeutronLoadBalancerPoolMemberRequest(ans)).build();
+}
+
+/**
+ * Adds a Member to an LBaaS Pool member
+ */
+@Path("/pools/{loadBalancerPoolID}/members")
+@PUT
+@Produces({MediaType.APPLICATION_JSON})
+@Consumes({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 createLoadBalancerPoolMember( INeutronLoadBalancerPoolMemberRequest input) {
+
+ INeutronLoadBalancerPoolMemberCRUD loadBalancerPoolMemberInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerPoolMemberCRUD(
+ this);
+ if (loadBalancerPoolMemberInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerPoolMember CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronLoadBalancerPoolMember singleton = input.getSingleton();
+
+ /*
+ * Verify that the LoadBalancerPoolMember doesn't already exist.
+ */
+ if (loadBalancerPoolMemberInterface.neutronLoadBalancerPoolMemberExists(
+ singleton.getPoolMemberID())) {
+ throw new BadRequestException("LoadBalancerPoolMember UUID already exists");
+ }
+ loadBalancerPoolMemberInterface.addNeutronLoadBalancerPoolMember(singleton);
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerPoolMemberAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
+ int status = service.canCreateNeutronLoadBalancerPoolMember(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ loadBalancerPoolMemberInterface.addNeutronLoadBalancerPoolMember(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
+ service.neutronLoadBalancerPoolMemberCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronLoadBalancerPoolMember> bulk = input.getBulk();
+ Iterator<NeutronLoadBalancerPoolMember> i = bulk.iterator();
+ HashMap<String, NeutronLoadBalancerPoolMember> testMap = new HashMap<String, NeutronLoadBalancerPoolMember>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerPoolMemberAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronLoadBalancerPoolMember test = i.next();
+
+ /*
+ * Verify that the firewall doesn't already exist
+ */
+
+ if (loadBalancerPoolMemberInterface.neutronLoadBalancerPoolMemberExists(
+ test.getPoolMemberID())) {
+ throw new BadRequestException("Load Balancer PoolMember UUID already is already created");
+ }
+ if (testMap.containsKey(test.getPoolMemberID())) {
+ throw new BadRequestException("Load Balancer PoolMember UUID already exists");
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
+ int status = service.canCreateNeutronLoadBalancerPoolMember(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()) {
+ NeutronLoadBalancerPoolMember test = i.next();
+ loadBalancerPoolMemberInterface.addNeutronLoadBalancerPoolMember(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance;
+ service.neutronLoadBalancerPoolMemberCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+}
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolAware;
+import org.opendaylight.controller.networkconfig.neutron.INeutronLoadBalancerPoolCRUD;
+import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
+import org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+
+import javax.ws.rs.Consumes;
+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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Neutron Northbound REST APIs for LoadBalancerPool Policies.<br>
+ * This class provides REST APIs for managing neutron LoadBalancerPool Policies
+ *
+ * <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("/pools")
+public class NeutronLoadBalancerPoolNorthbound {
+
+ private NeutronLoadBalancerPool extractFields(NeutronLoadBalancerPool o, List<String> fields) {
+ return o.extractFields(fields);
+ }
+
+ /**
+ * Returns a list of all LoadBalancerPool
+ * */
+ @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 listGroups(
+ // return fields
+ @QueryParam("fields") List<String> fields,
+ // OpenStack LoadBalancerPool attributes
+ @QueryParam("id") String queryLoadBalancerPoolID,
+ @QueryParam("tenant_id") String queryLoadBalancerPoolTenantID,
+ @QueryParam("name") String queryLoadBalancerPoolName,
+ @QueryParam("description") String queryLoadBalancerDescription,
+ @QueryParam("protocol") String queryLoadBalancerProtocol,
+ @QueryParam("lb_algorithm") String queryLoadBalancerPoolLbAlgorithm,
+ @QueryParam("healthmonitor_id") String queryLoadBalancerPoolHealthMonitorID,
+ @QueryParam("admin_state_up") String queryLoadBalancerIsAdminStateUp,
+ @QueryParam("status") String queryLoadBalancerPoolStatus,
+ @QueryParam("members") List queryLoadBalancerPoolMembers,
+ // pagination
+ @QueryParam("limit") String limit,
+ @QueryParam("marker") String marker,
+ @QueryParam("page_reverse") String pageReverse
+ // sorting not supported
+ ) {
+ INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerPoolCRUD(this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerPool CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ List<NeutronLoadBalancerPool> allLoadBalancerPools = loadBalancerPoolInterface.getAllNeutronLoadBalancerPools();
+ List<NeutronLoadBalancerPool> ans = new ArrayList<NeutronLoadBalancerPool>();
+ Iterator<NeutronLoadBalancerPool> i = allLoadBalancerPools.iterator();
+ while (i.hasNext()) {
+ NeutronLoadBalancerPool nsg = i.next();
+ if ((queryLoadBalancerPoolID == null ||
+ queryLoadBalancerPoolID.equals(nsg.getLoadBalancerPoolID())) &&
+ (queryLoadBalancerPoolTenantID == null ||
+ queryLoadBalancerPoolTenantID.equals(nsg.getLoadBalancerPoolTenantID())) &&
+ (queryLoadBalancerPoolName == null ||
+ queryLoadBalancerPoolName.equals(nsg.getLoadBalancerPoolName())) &&
+ (queryLoadBalancerDescription == null ||
+ queryLoadBalancerDescription.equals(nsg.getLoadBalancerPoolDescription())) &&
+ (queryLoadBalancerPoolLbAlgorithm == null ||
+ queryLoadBalancerPoolLbAlgorithm.equals(nsg.getLoadBalancerPoolLbAlgorithm())) &&
+ (queryLoadBalancerPoolHealthMonitorID == null ||
+ queryLoadBalancerPoolHealthMonitorID.equals(nsg.getNeutronLoadBalancerPoolHealthMonitorID())) &&
+ (queryLoadBalancerIsAdminStateUp == null ||
+ queryLoadBalancerIsAdminStateUp.equals(nsg.getLoadBalancerPoolAdminIsStateIsUp())) &&
+ (queryLoadBalancerPoolStatus == null ||
+ queryLoadBalancerPoolStatus.equals(nsg.getLoadBalancerPoolStatus())) &&
+ (queryLoadBalancerPoolMembers.size() == 0 ||
+ queryLoadBalancerPoolMembers.equals(nsg.getLoadBalancerPoolMembers()))) {
+ if (fields.size() > 0) {
+ ans.add(extractFields(nsg,fields));
+ } else {
+ ans.add(nsg);
+ }
+ }
+ }
+ return Response.status(200).entity(
+ new NeutronLoadBalancerPoolRequest(ans)).build();
+ }
+
+ /**
+ * Returns a specific LoadBalancerPool */
+
+ @Path("{loadBalancerPoolID}")
+ @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 showLoadBalancerPool(@PathParam("loadBalancerPoolID") String loadBalancerPoolID,
+ // return fields
+ @QueryParam("fields") List<String> fields) {
+ INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerPoolCRUD(this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerPool CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (!loadBalancerPoolInterface.neutronLoadBalancerPoolExists(loadBalancerPoolID)) {
+ throw new ResourceNotFoundException("LoadBalancerPool UUID does not exist.");
+ }
+ if (fields.size() > 0) {
+ NeutronLoadBalancerPool ans = loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolID);
+ return Response.status(200).entity(
+ new NeutronLoadBalancerPoolRequest(extractFields(ans, fields))).build();
+ } else {
+ return Response.status(200).entity(new NeutronLoadBalancerPoolRequest(loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolID))).build();
+ }
+ }
+
+ /**
+ * Creates new LoadBalancerPool */
+
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 409, condition = "Conflict"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response createLoadBalancerPools(final NeutronLoadBalancerPoolRequest input) {
+ INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerPoolCRUD(this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerPool CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ if (input.isSingleton()) {
+ NeutronLoadBalancerPool singleton = input.getSingleton();
+
+ /*
+ * Verify that the LoadBalancerPool doesn't already exist.
+ */
+ if (loadBalancerPoolInterface.neutronLoadBalancerPoolExists(singleton.getLoadBalancerPoolID())) {
+ throw new BadRequestException("LoadBalancerPool UUID already exists");
+ }
+ loadBalancerPoolInterface.addNeutronLoadBalancerPool(singleton);
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerPoolAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance;
+ int status = service.canCreateNeutronLoadBalancerPool(singleton);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+ loadBalancerPoolInterface.addNeutronLoadBalancerPool(singleton);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance;
+ service.neutronLoadBalancerPoolCreated(singleton);
+ }
+ }
+ } else {
+ List<NeutronLoadBalancerPool> bulk = input.getBulk();
+ Iterator<NeutronLoadBalancerPool> i = bulk.iterator();
+ HashMap<String, NeutronLoadBalancerPool> testMap = new HashMap<String, NeutronLoadBalancerPool>();
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerPoolAware.class, this, null);
+ while (i.hasNext()) {
+ NeutronLoadBalancerPool test = i.next();
+
+ /*
+ * Verify that the firewall doesn't already exist
+ */
+
+ if (loadBalancerPoolInterface.neutronLoadBalancerPoolExists(test.getLoadBalancerPoolID())) {
+ throw new BadRequestException("Load Balancer Pool UUID already is already created");
+ }
+ if (testMap.containsKey(test.getLoadBalancerPoolID())) {
+ throw new BadRequestException("Load Balancer Pool UUID already exists");
+ }
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance;
+ int status = service.canCreateNeutronLoadBalancerPool(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()) {
+ NeutronLoadBalancerPool test = i.next();
+ loadBalancerPoolInterface.addNeutronLoadBalancerPool(test);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance;
+ service.neutronLoadBalancerPoolCreated(test);
+ }
+ }
+ }
+ }
+ return Response.status(201).entity(input).build();
+ }
+
+ /**
+ * Updates a LoadBalancerPool Policy
+ */
+ @Path("{loadBalancerPoolID}")
+ @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 = 403, condition = "Forbidden"),
+ @ResponseCode(code = 404, condition = "Not Found"),
+ @ResponseCode(code = 501, condition = "Not Implemented") })
+ public Response updateLoadBalancerPool(
+ @PathParam("loadBalancerPoolID") String loadBalancerPoolID, final NeutronLoadBalancerPoolRequest input) {
+ INeutronLoadBalancerPoolCRUD loadBalancerPoolInterface = NeutronCRUDInterfaces.getINeutronLoadBalancerPoolCRUD(this);
+ if (loadBalancerPoolInterface == null) {
+ throw new ServiceUnavailableException("LoadBalancerPool CRUD Interface "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /*
+ * verify the LoadBalancerPool exists and there is only one delta provided
+ */
+ if (!loadBalancerPoolInterface.neutronLoadBalancerPoolExists(loadBalancerPoolID)) {
+ throw new ResourceNotFoundException("LoadBalancerPool UUID does not exist.");
+ }
+ if (!input.isSingleton()) {
+ throw new BadRequestException("Only singleton edit supported");
+ }
+ NeutronLoadBalancerPool delta = input.getSingleton();
+ NeutronLoadBalancerPool original = loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolID);
+
+ /*
+ * updates restricted by Neutron
+ */
+ if (delta.getLoadBalancerPoolID() != null ||
+ delta.getLoadBalancerPoolTenantID() != null ||
+ delta.getLoadBalancerPoolName() != null ||
+ delta.getLoadBalancerPoolDescription() != null ||
+ delta.getLoadBalancerPoolProtocol() != null ||
+ delta.getLoadBalancerPoolLbAlgorithm() != null ||
+ delta.getNeutronLoadBalancerPoolHealthMonitorID() != null ||
+ delta.getLoadBalancerPoolAdminIsStateIsUp() != null ||
+ delta.getLoadBalancerPoolStatus() != null ||
+ delta.getLoadBalancerPoolMembers() != null) {
+ throw new BadRequestException("Attribute edit blocked by Neutron");
+ }
+
+ Object[] instances = ServiceHelper.getGlobalInstances(INeutronLoadBalancerPoolAware.class, this, null);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance;
+ int status = service.canUpdateNeutronLoadBalancerPool(delta, original);
+ if (status < 200 || status > 299) {
+ return Response.status(status).build();
+ }
+ }
+ }
+
+ /*
+ * update the object and return it
+ */
+ loadBalancerPoolInterface.updateNeutronLoadBalancerPool(loadBalancerPoolID, delta);
+ NeutronLoadBalancerPool updatedLoadBalancerPool = loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolID);
+ if (instances != null) {
+ for (Object instance : instances) {
+ INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance;
+ service.neutronLoadBalancerPoolUpdated(updatedLoadBalancerPool);
+ }
+ }
+ return Response.status(200).entity(new NeutronLoadBalancerPoolRequest(loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolID))).build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancerPool;
+
+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 java.util.List;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerPoolRequest {
+ /**
+ * See OpenStack Network API v2.0 Reference for description of
+ * http://docs.openstack.org/api/openstack-network/2.0/content/
+ */
+
+ @XmlElement(name="pool")
+ NeutronLoadBalancerPool singletonLoadBalancerPool;
+
+ @XmlElement(name="pools")
+ List<NeutronLoadBalancerPool> bulkRequest;
+
+ NeutronLoadBalancerPoolRequest() {
+ }
+
+ NeutronLoadBalancerPoolRequest(List<NeutronLoadBalancerPool> bulk) {
+ bulkRequest = bulk;
+ singletonLoadBalancerPool = null;
+ }
+
+ NeutronLoadBalancerPoolRequest(NeutronLoadBalancerPool group) {
+ singletonLoadBalancerPool = group;
+ }
+
+ public List<NeutronLoadBalancerPool> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronLoadBalancerPool getSingleton() {
+ return singletonLoadBalancerPool;
+ }
+
+ public boolean isSingleton() {
+ return (singletonLoadBalancerPool != null);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * 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 org.opendaylight.controller.networkconfig.neutron.NeutronLoadBalancer;
+
+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 java.util.List;
+
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+
+public class NeutronLoadBalancerRequest {
+ /**
+ * See OpenStack Network API v2.0 Reference for description of
+ * http://docs.openstack.org/api/openstack-network/2.0/content/
+ */
+
+ @XmlElement(name="loadbalancer")
+ NeutronLoadBalancer singletonLoadBalancer;
+
+ @XmlElement(name="loadbalancers")
+ List<NeutronLoadBalancer> bulkRequest;
+
+ NeutronLoadBalancerRequest() {
+ }
+
+ NeutronLoadBalancerRequest(List<NeutronLoadBalancer> bulk) {
+ bulkRequest = bulk;
+ singletonLoadBalancer = null;
+ }
+
+ NeutronLoadBalancerRequest(NeutronLoadBalancer group) {
+ singletonLoadBalancer = group;
+ }
+
+ public List<NeutronLoadBalancer> getBulk() {
+ return bulkRequest;
+ }
+
+ public NeutronLoadBalancer getSingleton() {
+ return singletonLoadBalancer;
+ }
+
+ public boolean isSingleton() {
+ return (singletonLoadBalancer != null);
+ }
+}
\ No newline at end of file
classes.add(NeutronFirewallNorthbound.class);
classes.add(NeutronFirewallPolicyNorthbound.class);
classes.add(NeutronFirewallRulesNorthbound.class);
+ classes.add(NeutronLoadBalancerNorthbound.class);
+ classes.add(NeutronLoadBalancerListenerNorthbound.class);
+ classes.add(NeutronLoadBalancerPoolNorthbound.class);
+ classes.add(NeutronLoadBalancerHealthMonitorNorthbound.class);
+ classes.add(NeutronLoadBalancerPoolMembersNorthbound.class);
return classes;
}