</properties>
<dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa</artifactId>
+ <version>${aaa.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.neutron</artifactId>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<features name="odl-neutron-${networkconfig.neutron.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.aaa/features-aaa/${aaa.version}/xml/features</repository>
<feature name='odl-neutron-all' version='${networkconfig.neutron.version}' description="OpenDaylight :: Neutron :: API">
<feature version='${networkconfig.neutron.version}'>odl-neutron-api</feature>
<feature version='${networkconfig.neutron.version}'>odl-neutron-northbound</feature>
<feature version='${networkconfig.neutron.version}'>odl-neutron-implementation</feature>
</feature>
<feature name='odl-neutron-northbound' version='${networkconfig.neutron.version}' description="OpenDaylight :: Neutron :: Northbound">
+ <feature version='${aaa.version}'>odl-aaa-authn</feature>
+ <feature>war</feature>
<feature version='${networkconfig.neutron.version}'>odl-neutron-api</feature>
<bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.moxy/${eclipse.persistence.version}</bundle>
<bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.core/${eclipse.persistence.version}</bundle>
+ <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.antlr/${eclipse.persistence.version}</bundle>
<bundle>mvn:org.opendaylight.controller/networkconfig.neutron.northbound/${networkconfig.neutron.northbound.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-core/${jersey.version}</bundle>
<bundle>mvn:com.sun.jersey/jersey-server/${jersey.version}</bundle>
</feature>
<feature name='odl-neutron-implementation' version='${networkconfig.neutron.version}' description="OpenDaylight :: Neutron :: Implementation">
<feature version='${networkconfig.neutron.version}'>odl-neutron-api</feature>
+ <feature>war</feature>
<bundle>mvn:org.opendaylight.controller/networkconfig.neutron.implementation/${networkconfig.neutron.implementation.version}</bundle>
<bundle>mvn:org.osgi/org.osgi.core/${osgi.core.version}</bundle>
</feature>
-</features>
\ No newline at end of file
+</features>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<Service name="Catalina">
- <Connector port="8080" protocol="HTTP/1.1"
+ <Connector port="8282" protocol="HTTP/1.1"
connectionTimeout="20000"
- redirectPort="8443" />
+ redirectPort="8663" />
<!--
Please remove the comments around the following Connector tag to enable HTTPS Authentication support.
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//
+DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<Configure class="org.eclipse.jetty.server.Server">
+
+ <!-- =========================================================== -->
+ <!-- Set connectors -->
+ <!-- =========================================================== -->
+ <!-- One of each type! -->
+ <!-- =========================================================== -->
+
+ <!-- Use this connector for many frequently idle connections and for
+ threadless continuations. -->
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
+ <Set name="host">
+ <Property name="jetty.host" />
+ </Set>
+ <Set name="port">
+ <Property name="jetty.port" default="8181" />
+ </Set>
+ <Set name="maxIdleTime">300000</Set>
+ <Set name="Acceptors">2</Set>
+ <Set name="statsOn">false</Set>
+ <Set name="confidentialPort">8543</Set>
+ <Set name="lowResourcesConnections">20000</Set>
+ <Set name="lowResourcesMaxIdleTime">5000</Set>
+ </New>
+ </Arg>
+ </Call>
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
+ <Set name="host">
+ <Property name="jetty.host" />
+ </Set>
+ <Set name="port">
+ <Property name="jetty.port" default="8080" />
+ </Set>
+ <Set name="maxIdleTime">300000</Set>
+ <Set name="Acceptors">2</Set>
+ <Set name="statsOn">false</Set>
+ <Set name="confidentialPort">8443</Set>
+ <Set name="lowResourcesConnections">20000</Set>
+ <Set name="lowResourcesMaxIdleTime">5000</Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <!-- =========================================================== -->
+ <!-- Configure Authentication Realms -->
+ <!-- Realms may be configured for the entire server here, or -->
+ <!-- they can be configured for a specific web app in a context -->
+ <!-- configuration (see $(jetty.home)/contexts/test.xml for an -->
+ <!-- example). -->
+ <!-- =========================================================== -->
+ <Call name="addBean">
+ <Arg>
+ <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
+ <Set name="name">karaf</Set>
+ <Set name="loginModuleName">karaf</Set>
+ <Set name="roleClassNames">
+ <Array type="java.lang.String">
+ <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Arg>
+ </Call>
+ <Call name="addBean">
+ <Arg>
+ <New class="org.eclipse.jetty.plus.jaas.JAASLoginService">
+ <Set name="name">default</Set>
+ <Set name="loginModuleName">karaf</Set>
+ <Set name="roleClassNames">
+ <Array type="java.lang.String">
+ <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal
+ </Item>
+ </Array>
+ </Set>
+ </New>
+ </Arg>
+ </Call>
+
+</Configure>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-neutron</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+
</dependencies>
<build>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-neutron</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ <version>${networkconfig.neutron.version}</version>
+ </dependency>
+
<!-- JMH Benchmark dependencies -->
<dependency>
<groupId>org.openjdk.jmh</groupId>
itemTypes[i++] = innerCompositeType;
}
- String[] descriptions = Arrays.copyOf(itemNames, itemNames.length);
+ String[] descriptions = itemNames.clone();
descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
try {
<!-- sal-distributed-datastore -->
<module>sal-distributed-datastore</module>
+ <module>sal-dummy-distributed-datastore</module>
<!-- XSQL -->
<module>sal-dom-xsql</module>
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
public class ValueSerializer {
+ private static final String NULL_VALUE = "";
+
public static void serialize(NormalizedNodeMessages.Node.Builder builder,
QNameSerializationContext context, Object value) {
builder.setIntValueType(ValueType.getSerializableType(value).ordinal());
}
}
}
- } else if(value instanceof byte[]){
+ } else if(value instanceof byte[]) {
builder.setBytesValue(ByteString.copyFrom((byte[]) value));
+ } else if(value == null){
+ builder.setValue(NULL_VALUE);
} else {
builder.setValue(value.toString());
}
}
} else if(value instanceof byte[]){
builder.setBytesValue(ByteString.copyFrom((byte[]) value));
+ } else if(value == null){
+ builder.setValue(NULL_VALUE);
} else {
builder.setValue(value.toString());
}
package org.opendaylight.controller.cluster.datastore.node.utils.serialization;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.math.BigDecimal;
Object deserialize(final String str) {
throw new UnsupportedOperationException("Should have been caught by caller");
}
+ },
+ NULL_TYPE {
+ @Override
+ Object deserialize(final String str) {
+ return null;
+ }
};
private static final Map<Class<?>, ValueType> TYPES;
abstract Object deserialize(String str);
public static final ValueType getSerializableType(Object node) {
- Preconditions.checkNotNull(node, "node should not be null");
+ if(node == null){
+ return NULL_TYPE;
+ }
final ValueType type = TYPES.get(node.getClass());
if (type != null) {
return bytes;
case ValueTypes.YANG_IDENTIFIER_TYPE :
- return readYangInstanceIdentifier();
+ return readYangInstanceIdentifier();
default :
return null;
case ValueTypes.YANG_IDENTIFIER_TYPE:
writeYangInstanceIdentifier((YangInstanceIdentifier) value);
break;
+ case ValueTypes.NULL_TYPE :
+ break;
default:
output.writeUTF(value.toString());
break;
package org.opendaylight.controller.cluster.datastore.node.utils.stream;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import java.math.BigDecimal;
public static final byte BIG_INTEGER_TYPE = 10;
public static final byte BIG_DECIMAL_TYPE = 11;
public static final byte BINARY_TYPE = 12;
+ public static final byte NULL_TYPE = 13;
private static final Map<Class<?>, Byte> TYPES;
}
public static final byte getSerializableType(Object node) {
- Preconditions.checkNotNull(node, "node should not be null");
+ if(node == null){
+ return NULL_TYPE;
+ }
final Byte type = TYPES.get(node.getClass());
if (type != null) {
}
+ @Test
+ public void testSerializeNull(){
+ NormalizedNodeMessages.Node.Builder builder = NormalizedNodeMessages.Node.newBuilder();
+ Object none = null;
+ ValueSerializer.serialize(builder, mock(QNameSerializationContext.class),none);
+
+ assertEquals(ValueType.NULL_TYPE.ordinal(), builder.getIntValueType());
+ assertEquals("", builder.getValue());
+
+ NormalizedNodeMessages.PathArgumentAttribute.Builder builder1 = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+ ValueSerializer.serialize(builder1, mock(QNameSerializationContext.class),none);
+
+ assertEquals(ValueType.NULL_TYPE.ordinal(), builder1.getType());
+ assertEquals("", builder.getValue());
+
+ }
+
@Test
public void testDeSerializeShort(){
}
+ @Test
+ public void testDeSerializeNullType(){
+ NormalizedNodeMessages.Node.Builder nodeBuilder = NormalizedNodeMessages.Node.newBuilder();
+ nodeBuilder.setIntValueType(ValueType.NULL_TYPE.ordinal());
+ nodeBuilder.setValue("");
+
+ Object o = ValueSerializer
+ .deSerialize(mock(QNameDeSerializationContext.class),
+ nodeBuilder.build());
+
+ assertEquals(null, o);
+
+ NormalizedNodeMessages.PathArgumentAttribute.Builder argumentBuilder
+ = NormalizedNodeMessages.PathArgumentAttribute.newBuilder();
+
+ argumentBuilder.setType(ValueType.NULL_TYPE.ordinal());
+ argumentBuilder.setValue("");
+
+ o = ValueSerializer
+ .deSerialize(mock(QNameDeSerializationContext.class),
+ argumentBuilder.build());
+
+ assertEquals(null, o);
+
+ }
+
}
package org.opendaylight.controller.cluster.datastore.node.utils.serialization;
-import org.junit.Test;
-
import static org.junit.Assert.assertEquals;
+import org.junit.Test;
public class ValueTypeTest {
ValueType serializableType = ValueType.getSerializableType(b);
assertEquals(ValueType.BINARY_TYPE, serializableType);
}
+
+ @Test
+ public void testNullType(){
+ ValueType serializableType = ValueType.getSerializableType(null);
+ assertEquals(ValueType.NULL_TYPE, serializableType);
+
+ assertEquals(null, ValueType.NULL_TYPE.deserialize(""));
+ }
}
\ No newline at end of file
new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, bytes2)).
withValue(bytes2).build();
+ LeafSetEntryNode<Object> entry3 = ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+ new YangInstanceIdentifier.NodeWithValue(TestModel.BINARY_LEAF_LIST_QNAME, null)).
+ withValue(null).build();
+
+
return TestModel.createBaseTestContainerBuilder().
withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(
new YangInstanceIdentifier.NodeIdentifier(TestModel.BINARY_LEAF_LIST_QNAME)).
- withChild(entry1).withChild(entry2).build()).
+ withChild(entry1).withChild(entry2).withChild(entry3).build()).
withChild(ImmutableNodes.leafNode(TestModel.SOME_BINARY_DATA_QNAME, new byte[]{1,2,3,4})).
withChild(Builders.orderedMapBuilder().
withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.ORDERED_LIST_QNAME)).
if (impl != null) {
LOG.trace("Transaction {} cancelled before submit", getIdentifier());
FUTURE_UPDATER.lazySet(this, CANCELLED_FUTURE);
+ closeSubtransactions();
return true;
}
--- /dev/null
+To use this run a real instance of the controller on your laptop.
+Modify the module-shards.conf to replicate modules to member-2 or
+member-2 and member-3 as neccessary.
+
+Then run the dummy datastore.
+
+For example,
+
+ java -jar ./target/sal-dummy-distributed-datastore-1.2.0-SNAPSHOT-allinone.jar -member-name member-2 -cause-trouble -drop-replies -max-delay-millis 500
+
+Runs the dummy datastore as member-2. Will cause failures including dropped replies and when it does reply may cause a random delay of upto
+500 millis
+
+This will start of the dummy datastore which will then spawn dummy shard actors which will listen to the RequestVote
+and AppendEntries messages. For RequestVote messages it will always respond with a positive vote and for AppendEntries
+it will put a sleep for a randomized interval upto the max delay.
\ No newline at end of file
--- /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>sal-parent</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-dummy-distributed-datastore</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-actor_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-cluster_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-persistence-experimental_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-remote_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-testkit_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-slf4j_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-osgi_${scala.version}</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-clustering-commons</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-akka-raft</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </dependency>
+
+
+ <!-- Test Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>args4j</groupId>
+ <artifactId>args4j</artifactId>
+ <version>2.0.29</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.7.7</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-package></Export-package>
+ <Private-Package></Private-Package>
+ <Import-Package>!*snappy;!org.jboss.*;!com.jcraft.*;!*jetty*;!sun.security.*;*</Import-Package>
+ <!--
+ <Embed-Dependency>
+ sal-clustering-commons;
+ sal-akka-raft;
+ *metrics*;
+ !sal*;
+ !*config-api*;
+ !*testkit*;
+ akka*;
+ *leveldb*;
+ *config*;
+ *hawt*;
+ *protobuf*;
+ *netty*;
+ *uncommons*;
+ *scala*;
+ </Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ -->
+ </instructions>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>org.opendaylight.controller.*</include>
+
+ </includes>
+ <excludes>
+ <exclude>org.opendaylight.controller.config.yang.config.*</exclude>
+ </excludes>
+ <check>false</check>
+ </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.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ <shadedClassifierName>allinone</shadedClassifierName>
+ <artifactSet>
+ <includes>
+ <include>*:*</include>
+ </includes>
+ </artifactSet>
+ <transformers>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+ <resource>reference.conf</resource>
+ </transformer>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <manifestEntries>
+ <Main-Class>org.opendaylight.controller.dummy.datastore.Main</Main-Class>
+ </manifestEntries>
+ </transformer>
+ </transformers>
+ </configuration>
+ </execution>
+ </executions>
+ </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:Architecture:Clustering</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.dummy.datastore;
+
+public class Configuration {
+ private final int maxDelayInMillis;
+ private final boolean dropReplies;
+ private final boolean causeTrouble;
+
+ public Configuration(int maxDelayInMillis, boolean dropReplies, boolean causeTrouble) {
+ this.maxDelayInMillis = maxDelayInMillis;
+ this.dropReplies = dropReplies;
+ this.causeTrouble = causeTrouble;
+ }
+
+ public int getMaxDelayInMillis() {
+ return maxDelayInMillis;
+ }
+
+ public boolean shouldDropReplies() {
+ return dropReplies;
+ }
+
+ public boolean shouldCauseTrouble() {
+ return causeTrouble;
+ }
+}
--- /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.dummy.datastore;
+
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
+import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
+import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
+import org.opendaylight.controller.cluster.raft.messages.RequestVote;
+import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DummyShard extends UntypedActor{
+ private final Configuration configuration;
+ private final String followerId;
+ private final Logger LOG = LoggerFactory.getLogger(DummyShard.class);
+
+ public DummyShard(Configuration configuration, String followerId) {
+ this.configuration = configuration;
+ this.followerId = followerId;
+ LOG.info("Creating : {}", followerId);
+ }
+
+ @Override
+ public void onReceive(Object o) throws Exception {
+ if(o instanceof RequestVote){
+ RequestVote req = (RequestVote) o;
+ sender().tell(new RequestVoteReply(req.getTerm(), true), self());
+ } else if(AppendEntries.LEGACY_SERIALIZABLE_CLASS.equals(o.getClass()) || o instanceof AppendEntries) {
+ AppendEntries req = AppendEntries.fromSerializable(o);
+ handleAppendEntries(req);
+ } else if(InstallSnapshot.SERIALIZABLE_CLASS.equals(o.getClass())) {
+ InstallSnapshot req = InstallSnapshot.fromSerializable(o);
+ handleInstallSnapshot(req);
+ } else if(o instanceof InstallSnapshot){
+ handleInstallSnapshot((InstallSnapshot) o);
+ } else {
+ LOG.error("Unknown message : {}", o.getClass());
+ }
+ }
+
+ private void handleInstallSnapshot(InstallSnapshot req) {
+ sender().tell(new InstallSnapshotReply(req.getTerm(), followerId, req.getChunkIndex(), true), self());
+ }
+
+ protected void handleAppendEntries(AppendEntries req) throws InterruptedException {
+ LOG.info("{} - Received AppendEntries message : leader term, index, size = {}, {}, {}", followerId, req.getTerm(),req.getLeaderCommit(), req.getEntries().size());
+ long lastIndex = req.getLeaderCommit();
+ if (req.getEntries().size() > 0)
+ lastIndex = req.getEntries().get(0).getIndex();
+
+ if (configuration.shouldCauseTrouble()) {
+ boolean ignore = false;
+
+ if (configuration.shouldDropReplies()) {
+ ignore = Math.random() > 0.5;
+ }
+
+ long delay = (long) (Math.random() * configuration.getMaxDelayInMillis());
+
+ if (!ignore) {
+ LOG.info("{} - Randomizing delay : {}", followerId, delay);
+ Thread.sleep(delay);
+ sender().tell(new AppendEntriesReply(followerId, req.getTerm(), true, lastIndex, req.getTerm()), self());
+ }
+ } else {
+ sender().tell(new AppendEntriesReply(followerId, req.getTerm(), true, lastIndex, req.getTerm()), self());
+ }
+ }
+
+ public static Props props(Configuration configuration, final String followerId) {
+
+ return Props.create(new DummyShardCreator(configuration, followerId));
+ }
+
+ private static class DummyShardCreator implements Creator<DummyShard> {
+
+ private static final long serialVersionUID = 1L;
+ private final Configuration configuration;
+ private final String followerId;
+
+ DummyShardCreator(Configuration configuration, String followerId) {
+ this.configuration = configuration;
+ this.followerId = followerId;
+ }
+
+ @Override
+ public DummyShard create() throws Exception {
+ return new DummyShard(configuration, followerId);
+ }
+ }
+
+}
--- /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.dummy.datastore;
+
+import akka.actor.ActorContext;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+
+public class DummyShardManager extends UntypedActor {
+ public DummyShardManager(Configuration configuration, String memberName, String[] shardNames, String type) throws Exception {
+ new DummyShardsCreator(configuration, context(), memberName, shardNames, type).create();
+ }
+
+ @Override
+ public void onReceive(Object o) throws Exception {
+
+ }
+
+ public static Props props(Configuration configuration, String memberName, String[] shardNames, String type){
+ return Props.create(new DummyShardManagerCreator(configuration, memberName, shardNames, type));
+ }
+
+ private static class DummyShardManagerCreator implements Creator<DummyShardManager> {
+
+ private final Configuration configuration;
+ private final String memberName;
+ private final String[] shardNames;
+ private final String type;
+
+ public DummyShardManagerCreator(Configuration configuration, String memberName, String[] shardNames, String type) {
+ this.configuration = configuration;
+ this.memberName = memberName;
+ this.shardNames = shardNames;
+ this.type = type;
+ }
+
+ @Override
+ public DummyShardManager create() throws Exception {
+ return new DummyShardManager(configuration, memberName, shardNames, type );
+ }
+ }
+
+ private static class DummyShardsCreator {
+ private final Configuration configuration;
+ private final ActorContext actorSystem;
+ private final String memberName;
+ private final String[] shardNames;
+ private final String type;
+
+ DummyShardsCreator(Configuration configuration, ActorContext actorSystem, String memberName, String[] shardNames, String type){
+ this.configuration = configuration;
+ this.actorSystem = actorSystem;
+ this.memberName = memberName;
+ this.shardNames = shardNames;
+ this.type = type;
+ }
+
+ void create(){
+ for(String shardName : shardNames){
+ String shardId = memberName + "-shard-" + shardName + "-" + type;
+ actorSystem.actorOf(DummyShard.props(configuration, shardId), shardId);
+ }
+ }
+ }
+}
--- /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.dummy.datastore;
+
+import akka.actor.ActorSystem;
+import com.typesafe.config.ConfigFactory;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+
+public class Main {
+ @Option(name="-member-name", usage="Sets the member name", required = true)
+ public String memberName;
+
+ @Option(name="-max-delay-millis", usage = "Sets the maximum delay that should be applied for any append entry. Only applies when cause-trouble is present.")
+ public int maxDelayInMillis = 500;
+
+ @Option(name="-cause-trouble", usage="If present turns on artificial failures")
+ public boolean causeTrouble = false;
+
+ @Option(name="-drop-replies", usage = "If present drops replies. Only applies when cause-trouble is present.")
+ public boolean dropReplies = false;
+
+ public void run(){
+ ActorSystem actorSystem = ActorSystem.create("opendaylight-cluster-data", ConfigFactory.load(memberName).getConfig("odl-cluster-data"));
+
+ Configuration configuration = new Configuration(maxDelayInMillis, dropReplies, causeTrouble);
+
+ actorSystem.actorOf(DummyShardManager.props(configuration, memberName, new String[] {"inventory", "default", "toaster", "topology"}, "operational"), "shardmanager-operational");
+ actorSystem.actorOf(DummyShardManager.props(configuration, memberName, new String[] {"inventory", "default", "toaster", "topology"}, "config"), "shardmanager-config");
+ }
+
+ @Override
+ public String toString() {
+ return "Main{" +
+ "memberName='" + memberName + '\'' +
+ ", maxDelayInMillis=" + maxDelayInMillis +
+ ", causeTrouble=" + causeTrouble +
+ ", dropReplies=" + dropReplies +
+ '}';
+ }
+
+ public static void main(String[] args){
+ Main bean = new Main();
+ CmdLineParser parser = new CmdLineParser(bean);
+
+ try {
+ parser.parseArgument(args);
+ System.out.println(bean.toString());
+ bean.run();
+ } catch(Exception e){
+ System.err.println(e.getMessage());
+ parser.printUsage(System.err);
+ }
+ }
+
+}
--- /dev/null
+odl-cluster-data {
+ bounded-mailbox {
+ mailbox-type = "org.opendaylight.controller.cluster.common.actor.MeteredBoundedMailbox"
+ mailbox-capacity = 1000
+ mailbox-push-timeout-time = 100ms
+ }
+
+ metric-capture-enabled = true
+
+ akka {
+ loglevel = "INFO"
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+
+ 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 = 2553
+ maximum-frame-size = 419430400
+ send-buffer-size = 52428800
+ receive-buffer-size = 52428800
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.1:2553"]
+
+ auto-down-unreachable-after = 10s
+
+ roles = [
+ "member-2"
+ ]
+
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+odl-cluster-data {
+ bounded-mailbox {
+ mailbox-type = "org.opendaylight.controller.cluster.common.actor.MeteredBoundedMailbox"
+ mailbox-capacity = 1000
+ mailbox-push-timeout-time = 100ms
+ }
+
+ metric-capture-enabled = true
+
+ akka {
+ loglevel = "INFO"
+ loggers = ["akka.event.slf4j.Slf4jLogger"]
+
+ 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 = 2554
+ maximum-frame-size = 419430400
+ send-buffer-size = 52428800
+ receive-buffer-size = 52428800
+ }
+ }
+
+ cluster {
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.1:2554"]
+
+ auto-down-unreachable-after = 10s
+
+ roles = [
+ "member-3"
+ ]
+
+ }
+ }
+}
\ No newline at end of file
<param-name>javax.ws.rs.Application</param-name>\r
<param-value>org.opendaylight.controller.networkconfig.neutron.northbound.NeutronNorthboundRSApplication</param-value>\r
</init-param>\r
+ <!-- AAA Auth Filter -->\r
+ <init-param>\r
+ <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>\r
+ <param-value> org.opendaylight.aaa.sts.TokenAuthFilter</param-value>\r
+ </init-param>\r
<load-on-startup>1</load-on-startup>\r
</servlet>\r
\r
<servlet-name>JAXRSNeutron</servlet-name>\r
<url-pattern>/*</url-pattern>\r
</servlet-mapping>\r
- <security-constraint>\r
- <web-resource-collection>\r
- <web-resource-name>NB api</web-resource-name>\r
- <url-pattern>/*</url-pattern>\r
- </web-resource-collection>\r
- <auth-constraint>\r
- <role-name>System-Admin</role-name>\r
- <role-name>Network-Admin</role-name>\r
- <role-name>Network-Operator</role-name>\r
- <role-name>Container-User</role-name>\r
- </auth-constraint>\r
- </security-constraint>\r
-\r
- <security-role>\r
- <role-name>System-Admin</role-name>\r
- </security-role>\r
- <security-role>\r
- <role-name>Network-Admin</role-name>\r
- </security-role>\r
- <security-role>\r
- <role-name>Network-Operator</role-name>\r
- </security-role>\r
- <security-role>\r
- <role-name>Container-User</role-name>\r
- </security-role>\r
\r
- <login-config>\r
- <auth-method>BASIC</auth-method>\r
- <realm-name>opendaylight</realm-name>\r
- </login-config>\r
+ <filter>\r
+ <filter-name>cross-origin-restconf</filter-name>\r
+ <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>\r
+ <init-param>\r
+ <param-name>allowedOrigins</param-name>\r
+ <param-value>*</param-value>\r
+ </init-param>\r
+ <init-param>\r
+ <param-name>allowedMethods</param-name>\r
+ <param-value>GET,POST,OPTIONS,DELETE,PUT,HEAD</param-value>\r
+ </init-param>\r
+ <init-param>\r
+ <param-name>allowedHeaders</param-name>\r
+ <param-value>origin, content-type, accept, authorization</param-value>\r
+ </init-param>\r
+ </filter>\r
+ <filter-mapping>\r
+ <filter-name>cross-origin-restconf</filter-name>\r
+ <url-pattern>/*</url-pattern>\r
+ </filter-mapping>\r
+ <security-constraint>\r
+ <web-resource-collection>\r
+ <web-resource-name>NB api</web-resource-name>\r
+ <url-pattern>/*</url-pattern>\r
+ <http-method>POST</http-method>\r
+ <http-method>GET</http-method>\r
+ <http-method>PUT</http-method>\r
+ <http-method>PATCH</http-method>\r
+ <http-method>DELETE</http-method>\r
+ <http-method>HEAD</http-method>\r
+ </web-resource-collection>\r
+ </security-constraint>\r
</web-app>\r