From: Tony Tkacik Date: Fri, 13 Feb 2015 09:29:35 +0000 (+0000) Subject: Merge "BUG-2626: activate enunciate only on jdk-1.7" X-Git-Tag: release/lithium~549^2~2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=fddfe9fc95e2d0807ea943d5c1c6af6a970ef34c;hp=c7237c68818c70efb2fe5719bbd9e48a91bf2c4d;p=controller.git Merge "BUG-2626: activate enunciate only on jdk-1.7" --- diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 6a9b4bef2a..6cc363b96f 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -1259,16 +1259,6 @@ nagasena-rta ${exi.nagasena.version} - - org.osgi - org.osgi.compendium - ${osgi.compendium.version} - - - org.osgi - org.osgi.core - ${osgi.core.version} - org.reflections reflections diff --git a/opendaylight/config/config-parent/pom.xml b/opendaylight/config/config-parent/pom.xml index af39b63447..e6e2bb8478 100644 --- a/opendaylight/config/config-parent/pom.xml +++ b/opendaylight/config/config-parent/pom.xml @@ -123,6 +123,25 @@ and is available at http://www.eclipse.org/legal/epl-v10.html + + org.codehaus.mojo + build-helper-maven-plugin + + + add-yang-sources + generate-sources + + add-source + + + + ${jmxGeneratorPath} + ${salGeneratorPath} + + + + + diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java index fcfaee3603..7a94c0c158 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Leader.java @@ -12,7 +12,6 @@ import akka.actor.Cancellable; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import org.opendaylight.controller.cluster.raft.RaftActorContext; -import org.opendaylight.controller.cluster.raft.base.messages.InitiateInstallSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.IsolatedLeaderCheck; import scala.concurrent.duration.FiniteDuration; @@ -45,8 +44,6 @@ public class Leader extends AbstractLeader { public Leader(RaftActorContext context) { super(context); - scheduleInstallSnapshotCheck(context.getConfigParams().getIsolatedCheckInterval()); - scheduleIsolatedLeaderCheck( new FiniteDuration(context.getConfigParams().getHeartBeatInterval().length() * 10, context.getConfigParams().getHeartBeatInterval().unit())); @@ -66,30 +63,6 @@ public class Leader extends AbstractLeader { return super.handleMessage(sender, originalMessage); } - protected void stopInstallSnapshotSchedule() { - if (installSnapshotSchedule != null && !installSnapshotSchedule.isCancelled()) { - installSnapshotSchedule.cancel(); - } - } - - protected void scheduleInstallSnapshotCheck(FiniteDuration interval) { - if (getFollowerIds().isEmpty()) { - // Optimization - do not bother scheduling a heartbeat as there are - // no followers - return; - } - - stopInstallSnapshotSchedule(); - - // Schedule a message to send append entries to followers that can - // accept an append entries with some data in it - installSnapshotSchedule = - context.getActorSystem().scheduler().scheduleOnce( - interval, - context.getActor(), new InitiateInstallSnapshot(), - context.getActorSystem().dispatcher(), context.getActor()); - } - protected void stopIsolatedLeaderCheckSchedule() { if (isolatedLeaderCheckSchedule != null && !isolatedLeaderCheckSchedule.isCancelled()) { isolatedLeaderCheckSchedule.cancel(); @@ -104,7 +77,6 @@ public class Leader extends AbstractLeader { @Override public void close() throws Exception { - stopInstallSnapshotSchedule(); stopIsolatedLeaderCheckSchedule(); super.close(); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java index 9e0e06c70b..56bf6200dc 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java @@ -50,6 +50,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.cluster.DataPersistenceProvider; import org.opendaylight.controller.cluster.datastore.DataPersistenceProviderMonitor; @@ -77,9 +78,16 @@ import scala.concurrent.duration.FiniteDuration; public class RaftActorTest extends AbstractActorTest { + private TestActorFactory factory; + + @Before + public void setUp(){ + factory = new TestActorFactory(getSystem()); + } @After - public void tearDown() { + public void tearDown() throws Exception { + factory.close(); MockAkkaJournal.clearJournal(); MockSnapshotStore.setMockSnapshot(null); } @@ -337,7 +345,7 @@ public class RaftActorTest extends AbstractActorTest { @Test public void testRaftActorRecovery() throws Exception { new JavaTestKit(getSystem()) {{ - String persistenceId = "follower10"; + String persistenceId = factory.generateActorId("follower-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); // Set the heartbeat interval high to essentially disable election otherwise the test @@ -345,8 +353,8 @@ public class RaftActorTest extends AbstractActorTest { // log entry. config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS)); - ActorRef followerActor = getSystem().actorOf(MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config)), persistenceId); + ActorRef followerActor = factory.createActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config)), persistenceId); watch(followerActor); @@ -358,15 +366,15 @@ public class RaftActorTest extends AbstractActorTest { int lastAppliedDuringSnapshotCapture = 3; int lastIndexDuringSnapshotCapture = 4; - // 4 messages as part of snapshot, which are applied to state - ByteString snapshotBytes = fromObject(Arrays.asList( + // 4 messages as part of snapshot, which are applied to state + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("A"), new MockRaftActorContext.MockPayload("B"), new MockRaftActorContext.MockPayload("C"), new MockRaftActorContext.MockPayload("D"))); Snapshot snapshot = Snapshot.create(snapshotBytes.toByteArray(), - snapshotUnappliedEntries, lastIndexDuringSnapshotCapture, 1 , + snapshotUnappliedEntries, lastIndexDuringSnapshotCapture, 1, lastAppliedDuringSnapshotCapture, 1); MockSnapshotStore.setMockSnapshot(snapshot); MockSnapshotStore.setPersistenceId(persistenceId); @@ -399,8 +407,8 @@ public class RaftActorTest extends AbstractActorTest { unwatch(followerActor); //reinstate the actor - TestActorRef ref = TestActorRef.create(getSystem(), - MockRaftActor.props(persistenceId, Collections.emptyMap(), + TestActorRef ref = factory.createTestActor( + MockRaftActor.props(persistenceId, Collections.emptyMap(), Optional.of(config))); ref.underlyingActor().waitForRecoveryComplete(); @@ -426,28 +434,28 @@ public class RaftActorTest extends AbstractActorTest { public void testHandleRecoveryWhenDataPersistenceRecoveryApplicable() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testHandleRecoveryWhenDataPersistenceRecoveryApplicable"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS)); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config)), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config)), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); // Wait for akka's recovery to complete so it doesn't interfere. mockRaftActor.waitForRecoveryComplete(); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("A"), new MockRaftActorContext.MockPayload("B"), new MockRaftActorContext.MockPayload("C"), new MockRaftActorContext.MockPayload("D"))); Snapshot snapshot = Snapshot.create(snapshotBytes.toByteArray(), - Lists.newArrayList(), 3, 1 ,3, 1); + Lists.newArrayList(), 3, 1, 3, 1); mockRaftActor.onReceiveRecover(new SnapshotOffer(new SnapshotMetadata(persistenceId, 100, 100), snapshot)); @@ -480,8 +488,6 @@ public class RaftActorTest extends AbstractActorTest { mockRaftActor.onReceiveRecover(mock(RecoveryCompleted.class)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - }}; } @@ -495,28 +501,28 @@ public class RaftActorTest extends AbstractActorTest { public void testHandleRecoveryWhenDataPersistenceRecoveryNotApplicable() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testHandleRecoveryWhenDataPersistenceRecoveryNotApplicable"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS)); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), new DataPersistenceProviderMonitor()), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), new DataPersistenceProviderMonitor()), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); // Wait for akka's recovery to complete so it doesn't interfere. mockRaftActor.waitForRecoveryComplete(); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("A"), new MockRaftActorContext.MockPayload("B"), new MockRaftActorContext.MockPayload("C"), new MockRaftActorContext.MockPayload("D"))); Snapshot snapshot = Snapshot.create(snapshotBytes.toByteArray(), - Lists.newArrayList(), 3, 1 ,3, 1); + Lists.newArrayList(), 3, 1, 3, 1); mockRaftActor.onReceiveRecover(new SnapshotOffer(new SnapshotMetadata(persistenceId, 100, 100), snapshot)); @@ -547,7 +553,6 @@ public class RaftActorTest extends AbstractActorTest { mockRaftActor.onReceiveRecover(mock(RecoveryCompleted.class)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); }}; } @@ -556,7 +561,7 @@ public class RaftActorTest extends AbstractActorTest { public void testUpdatingElectionTermCallsDataPersistence() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testUpdatingElectionTermCallsDataPersistence"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -566,8 +571,8 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProviderMonitor dataPersistenceProviderMonitor = new DataPersistenceProviderMonitor(); dataPersistenceProviderMonitor.setPersistLatch(persistLatch); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProviderMonitor), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProviderMonitor), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); @@ -575,9 +580,8 @@ public class RaftActorTest extends AbstractActorTest { assertEquals("Persist called", true, persistLatch.await(5, TimeUnit.SECONDS)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } + }; } @@ -585,7 +589,7 @@ public class RaftActorTest extends AbstractActorTest { public void testAddingReplicatedLogEntryCallsDataPersistence() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testAddingReplicatedLogEntryCallsDataPersistence"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -593,8 +597,8 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); @@ -604,9 +608,8 @@ public class RaftActorTest extends AbstractActorTest { verify(dataPersistenceProvider).persist(eq(logEntry), any(Procedure.class)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } + }; } @@ -614,7 +617,7 @@ public class RaftActorTest extends AbstractActorTest { public void testRemovingReplicatedLogEntryCallsDataPersistence() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testRemovingReplicatedLogEntryCallsDataPersistence"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -622,8 +625,8 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); @@ -633,9 +636,8 @@ public class RaftActorTest extends AbstractActorTest { verify(dataPersistenceProvider, times(2)).persist(anyObject(), any(Procedure.class)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } + }; } @@ -643,7 +645,7 @@ public class RaftActorTest extends AbstractActorTest { public void testApplyLogEntriesCallsDataPersistence() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testApplyLogEntriesCallsDataPersistence"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -651,8 +653,8 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); @@ -660,9 +662,8 @@ public class RaftActorTest extends AbstractActorTest { verify(dataPersistenceProvider, times(1)).persist(anyObject(), any(Procedure.class)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } + }; } @@ -670,7 +671,7 @@ public class RaftActorTest extends AbstractActorTest { public void testCaptureSnapshotReplyCallsDataPersistence() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testCaptureSnapshotReplyCallsDataPersistence"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -678,19 +679,19 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), - MockRaftActor.props(persistenceId,Collections.emptyMap(), - Optional.of(config), dataPersistenceProvider), persistenceId); + TestActorRef mockActorRef = factory.createTestActor( + MockRaftActor.props(persistenceId, Collections.emptyMap(), + Optional.of(config), dataPersistenceProvider), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("A"), new MockRaftActorContext.MockPayload("B"), new MockRaftActorContext.MockPayload("C"), new MockRaftActorContext.MockPayload("D"))); - mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1,1,-1,1)); + mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, -1, 1)); RaftActorContext raftActorContext = mockRaftActor.getRaftActorContext(); @@ -700,8 +701,6 @@ public class RaftActorTest extends AbstractActorTest { verify(dataPersistenceProvider).saveSnapshot(anyObject()); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -710,7 +709,7 @@ public class RaftActorTest extends AbstractActorTest { public void testSaveSnapshotSuccessCallsDataPersistence() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testSaveSnapshotSuccessCallsDataPersistence"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -718,16 +717,16 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); - mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1,0, mock(Payload.class))); - mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1,1, mock(Payload.class))); - mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1,2, mock(Payload.class))); - mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1,3, mock(Payload.class))); - mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1,4, mock(Payload.class))); + mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 0, mock(Payload.class))); + mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 1, mock(Payload.class))); + mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 2, mock(Payload.class))); + mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 3, mock(Payload.class))); + mockRaftActor.getReplicatedLog().append(new MockRaftActorContext.MockReplicatedLogEntry(1, 4, mock(Payload.class))); ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("A"), @@ -758,8 +757,6 @@ public class RaftActorTest extends AbstractActorTest { // Index 2 will not be in the log because it was removed due to snapshotting assertNull(mockRaftActor.getReplicatedLog().get(2)); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -769,7 +766,7 @@ public class RaftActorTest extends AbstractActorTest { new JavaTestKit(getSystem()) { { - String persistenceId = "testApplyState"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -777,8 +774,8 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProvider), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); @@ -789,8 +786,6 @@ public class RaftActorTest extends AbstractActorTest { verify(mockRaftActor.delegate).applyState(eq(mockActorRef), eq("apply-state"), anyObject()); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -799,7 +794,7 @@ public class RaftActorTest extends AbstractActorTest { public void testApplySnapshot() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testApplySnapshot"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -807,24 +802,24 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProviderMonitor dataPersistenceProviderMonitor = new DataPersistenceProviderMonitor(); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProviderMonitor), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProviderMonitor), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); ReplicatedLog oldReplicatedLog = mockRaftActor.getReplicatedLog(); - oldReplicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1,0,mock(Payload.class))); - oldReplicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1,1,mock(Payload.class))); + oldReplicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1, 0, mock(Payload.class))); + oldReplicatedLog.append(new MockRaftActorContext.MockReplicatedLogEntry(1, 1, mock(Payload.class))); oldReplicatedLog.append( - new MockRaftActorContext.MockReplicatedLogEntry(1, 2, - mock(Payload.class))); + new MockRaftActorContext.MockReplicatedLogEntry(1, 2, + mock(Payload.class))); ByteString snapshotBytes = fromObject(Arrays.asList( - new MockRaftActorContext.MockPayload("A"), - new MockRaftActorContext.MockPayload("B"), - new MockRaftActorContext.MockPayload("C"), - new MockRaftActorContext.MockPayload("D"))); + new MockRaftActorContext.MockPayload("A"), + new MockRaftActorContext.MockPayload("B"), + new MockRaftActorContext.MockPayload("C"), + new MockRaftActorContext.MockPayload("D"))); Snapshot snapshot = mock(Snapshot.class); @@ -837,15 +832,13 @@ public class RaftActorTest extends AbstractActorTest { verify(mockRaftActor.delegate).applySnapshot(eq(snapshot.getState())); assertTrue("The replicatedLog should have changed", - oldReplicatedLog != mockRaftActor.getReplicatedLog()); + oldReplicatedLog != mockRaftActor.getReplicatedLog()); assertEquals("lastApplied should be same as in the snapshot", - (Long) 3L, mockRaftActor.getLastApplied()); + (Long) 3L, mockRaftActor.getLastApplied()); assertEquals(0, mockRaftActor.getReplicatedLog().size()); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -854,7 +847,7 @@ public class RaftActorTest extends AbstractActorTest { public void testSaveSnapshotFailure() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "testSaveSnapshotFailure"; + String persistenceId = factory.generateActorId("leader-"); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); @@ -862,12 +855,12 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProviderMonitor dataPersistenceProviderMonitor = new DataPersistenceProviderMonitor(); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, - Collections.emptyMap(), Optional.of(config), dataPersistenceProviderMonitor), persistenceId); + TestActorRef mockActorRef = factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), dataPersistenceProviderMonitor), persistenceId); MockRaftActor mockRaftActor = mockActorRef.underlyingActor(); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("A"), new MockRaftActorContext.MockPayload("B"), new MockRaftActorContext.MockPayload("C"), @@ -877,7 +870,7 @@ public class RaftActorTest extends AbstractActorTest { mockRaftActor.setCurrentBehavior(new Leader(raftActorContext)); - mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1,1,-1,1)); + mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, -1, 1)); mockRaftActor.onReceiveCommand(new CaptureSnapshotReply(snapshotBytes.toByteArray())); @@ -887,8 +880,6 @@ public class RaftActorTest extends AbstractActorTest { assertEquals("Snapshot index should not have advanced because save snapshot failed", -1, mockRaftActor.getReplicatedLog().getSnapshotIndex()); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -896,35 +887,35 @@ public class RaftActorTest extends AbstractActorTest { @Test public void testRaftRoleChangeNotifier() throws Exception { new JavaTestKit(getSystem()) {{ - ActorRef notifierActor = getSystem().actorOf(Props.create(MessageCollectorActor.class)); + ActorRef notifierActor = factory.createActor(Props.create(MessageCollectorActor.class)); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); - String id = "testRaftRoleChangeNotifier"; + String persistenceId = factory.generateActorId("notifier-"); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(id, - Collections.emptyMap(), Optional.of(config), notifierActor), id); + factory.createTestActor(MockRaftActor.props(persistenceId, + Collections.emptyMap(), Optional.of(config), notifierActor), persistenceId); // sleeping for a minimum of 2 seconds, if it spans more its fine. Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS); - List matches = MessageCollectorActor.getAllMatching(notifierActor, RoleChanged.class); + List matches = MessageCollectorActor.getAllMatching(notifierActor, RoleChanged.class); assertNotNull(matches); assertEquals(3, matches.size()); // check if the notifier got a role change from null to Follower RoleChanged raftRoleChanged = (RoleChanged) matches.get(0); - assertEquals(id, raftRoleChanged.getMemberId()); + assertEquals(persistenceId, raftRoleChanged.getMemberId()); assertNull(raftRoleChanged.getOldRole()); assertEquals(RaftState.Follower.name(), raftRoleChanged.getNewRole()); // check if the notifier got a role change from Follower to Candidate raftRoleChanged = (RoleChanged) matches.get(1); - assertEquals(id, raftRoleChanged.getMemberId()); + assertEquals(persistenceId, raftRoleChanged.getMemberId()); assertEquals(RaftState.Follower.name(), raftRoleChanged.getOldRole()); assertEquals(RaftState.Candidate.name(), raftRoleChanged.getNewRole()); // check if the notifier got a role change from Candidate to Leader raftRoleChanged = (RoleChanged) matches.get(2); - assertEquals(id, raftRoleChanged.getMemberId()); + assertEquals(persistenceId, raftRoleChanged.getMemberId()); assertEquals(RaftState.Candidate.name(), raftRoleChanged.getOldRole()); assertEquals(RaftState.Leader.name(), raftRoleChanged.getNewRole()); }}; @@ -934,10 +925,11 @@ public class RaftActorTest extends AbstractActorTest { public void testFakeSnapshotsForLeaderWithInRealSnapshots() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "leader1"; + String persistenceId = factory.generateActorId("leader-"); + String follower1Id = factory.generateActorId("follower-"); ActorRef followerActor1 = - getSystem().actorOf(Props.create(MessageCollectorActor.class)); + factory.createActor(Props.create(MessageCollectorActor.class)); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS)); @@ -946,7 +938,7 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); Map peerAddresses = new HashMap<>(); - peerAddresses.put("follower-1", followerActor1.path().toString()); + peerAddresses.put(follower1Id, followerActor1.path().toString()); TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, peerAddresses, @@ -970,7 +962,7 @@ public class RaftActorTest extends AbstractActorTest { assertEquals(8, leaderActor.getReplicatedLog().size()); - leaderActor.onReceiveCommand(new CaptureSnapshot(6,1,4,1)); + leaderActor.onReceiveCommand(new CaptureSnapshot(6, 1, 4, 1)); leaderActor.getRaftActorContext().setSnapshotCaptureInitiated(true); verify(leaderActor.delegate).createSnapshot(); @@ -978,20 +970,20 @@ public class RaftActorTest extends AbstractActorTest { assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state()); //fake snapshot on index 5 - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-1", 1, true, 5, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower1Id, 1, true, 5, 1)); assertEquals(8, leaderActor.getReplicatedLog().size()); //fake snapshot on index 6 assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state()); - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-1", 1, true, 6, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower1Id, 1, true, 6, 1)); assertEquals(8, leaderActor.getReplicatedLog().size()); assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state()); assertEquals(8, leaderActor.getReplicatedLog().size()); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("foo-0"), new MockRaftActorContext.MockPayload("foo-1"), new MockRaftActorContext.MockPayload("foo-2"), @@ -1009,12 +1001,10 @@ public class RaftActorTest extends AbstractActorTest { new ReplicatedLogImplEntry(8, 1, new MockRaftActorContext.MockPayload("foo-8"))); //fake snapshot on index 7, since lastApplied = 7 , we would keep the last applied - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-1", 1, true, 7, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower1Id, 1, true, 7, 1)); assertEquals(2, leaderActor.getReplicatedLog().size()); assertEquals(8, leaderActor.getReplicatedLog().lastIndex()); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -1023,10 +1013,12 @@ public class RaftActorTest extends AbstractActorTest { public void testFakeSnapshotsForFollowerWithInRealSnapshots() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "follower1"; + String persistenceId = factory.generateActorId("follower-"); + String leaderId = factory.generateActorId("leader-"); + ActorRef leaderActor1 = - getSystem().actorOf(Props.create(MessageCollectorActor.class)); + factory.createActor(Props.create(MessageCollectorActor.class)); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS)); @@ -1035,7 +1027,7 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); Map peerAddresses = new HashMap<>(); - peerAddresses.put("leader", leaderActor1.path().toString()); + peerAddresses.put(leaderId, leaderActor1.path().toString()); TestActorRef mockActorRef = TestActorRef.create(getSystem(), MockRaftActor.props(persistenceId, peerAddresses, @@ -1060,7 +1052,7 @@ public class RaftActorTest extends AbstractActorTest { assertEquals(6, followerActor.getReplicatedLog().size()); //snapshot on 4 - followerActor.onReceiveCommand(new CaptureSnapshot(5,1,4,1)); + followerActor.onReceiveCommand(new CaptureSnapshot(5, 1, 4, 1)); followerActor.getRaftActorContext().setSnapshotCaptureInitiated(true); verify(followerActor.delegate).createSnapshot(); @@ -1072,7 +1064,7 @@ public class RaftActorTest extends AbstractActorTest { (ReplicatedLogEntry) new MockRaftActorContext.MockReplicatedLogEntry(1, 6, new MockRaftActorContext.MockPayload("foo-6")) ); - followerActor.onReceiveCommand(new AppendEntries(1, "leader", 5, 1, entries , 5, 5)); + followerActor.onReceiveCommand(new AppendEntries(1, leaderId, 5, 1, entries, 5, 5)); assertEquals(7, followerActor.getReplicatedLog().size()); //fake snapshot on index 7 @@ -1083,13 +1075,13 @@ public class RaftActorTest extends AbstractActorTest { (ReplicatedLogEntry) new MockRaftActorContext.MockReplicatedLogEntry(1, 7, new MockRaftActorContext.MockPayload("foo-7")) ); - followerActor.onReceiveCommand(new AppendEntries(1, "leader", 6, 1, entries, 6, 6)); + followerActor.onReceiveCommand(new AppendEntries(1, leaderId, 6, 1, entries, 6, 6)); assertEquals(8, followerActor.getReplicatedLog().size()); assertEquals(RaftState.Follower, followerActor.getCurrentBehavior().state()); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("foo-0"), new MockRaftActorContext.MockPayload("foo-1"), new MockRaftActorContext.MockPayload("foo-2"), @@ -1108,13 +1100,11 @@ public class RaftActorTest extends AbstractActorTest { new MockRaftActorContext.MockPayload("foo-7")) ); // send an additional entry 8 with leaderCommit = 7 - followerActor.onReceiveCommand(new AppendEntries(1, "leader", 7, 1, entries , 7, 7)); + followerActor.onReceiveCommand(new AppendEntries(1, leaderId, 7, 1, entries, 7, 7)); // 7 and 8, as lastapplied is 7 assertEquals(2, followerActor.getReplicatedLog().size()); - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } @@ -1123,12 +1113,14 @@ public class RaftActorTest extends AbstractActorTest { public void testFakeSnapshotsForLeaderWithInInitiateSnapshots() throws Exception { new JavaTestKit(getSystem()) { { - String persistenceId = "leader1"; + String persistenceId = factory.generateActorId("leader-"); + String follower1Id = factory.generateActorId("follower-"); + String follower2Id = factory.generateActorId("follower-"); ActorRef followerActor1 = - getSystem().actorOf(Props.create(MessageCollectorActor.class)); + factory.createActor(Props.create(MessageCollectorActor.class), follower1Id); ActorRef followerActor2 = - getSystem().actorOf(Props.create(MessageCollectorActor.class)); + factory.createActor(Props.create(MessageCollectorActor.class), follower2Id); DefaultConfigParamsImpl config = new DefaultConfigParamsImpl(); config.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS)); @@ -1137,10 +1129,10 @@ public class RaftActorTest extends AbstractActorTest { DataPersistenceProvider dataPersistenceProvider = mock(DataPersistenceProvider.class); Map peerAddresses = new HashMap<>(); - peerAddresses.put("follower-1", followerActor1.path().toString()); - peerAddresses.put("follower-2", followerActor2.path().toString()); + peerAddresses.put(follower1Id, followerActor1.path().toString()); + peerAddresses.put(follower2Id, followerActor2.path().toString()); - TestActorRef mockActorRef = TestActorRef.create(getSystem(), + TestActorRef mockActorRef = factory.createTestActor( MockRaftActor.props(persistenceId, peerAddresses, Optional.of(config), dataPersistenceProvider), persistenceId); @@ -1162,26 +1154,26 @@ public class RaftActorTest extends AbstractActorTest { leaderActor.getRaftActorContext().getReplicatedLog().setSnapshotIndex(4); assertEquals(5, leaderActor.getReplicatedLog().size()); - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-1", 1, true, 9, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower1Id, 1, true, 9, 1)); assertEquals(5, leaderActor.getReplicatedLog().size()); // set the 2nd follower nextIndex to 1 which has been snapshotted - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-2", 1, true, 0, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower2Id, 1, true, 0, 1)); assertEquals(5, leaderActor.getReplicatedLog().size()); // simulate a real snapshot leaderActor.onReceiveCommand(new InitiateInstallSnapshot()); assertEquals(5, leaderActor.getReplicatedLog().size()); assertEquals(String.format("expected to be Leader but was %s. Current Leader = %s ", - leaderActor.getCurrentBehavior().state(),leaderActor.getLeaderId()) + leaderActor.getCurrentBehavior().state(), leaderActor.getLeaderId()) , RaftState.Leader, leaderActor.getCurrentBehavior().state()); //reply from a slow follower does not initiate a fake snapshot - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-2", 1, true, 9, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower2Id, 1, true, 9, 1)); assertEquals("Fake snapshot should not happen when Initiate is in progress", 5, leaderActor.getReplicatedLog().size()); - ByteString snapshotBytes = fromObject(Arrays.asList( + ByteString snapshotBytes = fromObject(Arrays.asList( new MockRaftActorContext.MockPayload("foo-0"), new MockRaftActorContext.MockPayload("foo-1"), new MockRaftActorContext.MockPayload("foo-2"), @@ -1193,17 +1185,12 @@ public class RaftActorTest extends AbstractActorTest { assertEquals("Real snapshot didn't clear the log till lastApplied", 0, leaderActor.getReplicatedLog().size()); //reply from a slow follower after should not raise errors - leaderActor.onReceiveCommand(new AppendEntriesReply("follower-2", 1, true, 5, 1)); + leaderActor.onReceiveCommand(new AppendEntriesReply(follower2Id, 1, true, 5, 1)); assertEquals(0, leaderActor.getReplicatedLog().size()); - - mockActorRef.tell(PoisonPill.getInstance(), getRef()); - } }; } - - private ByteString fromObject(Object snapshot) throws Exception { ByteArrayOutputStream b = null; ObjectOutputStream o = null; @@ -1223,4 +1210,5 @@ public class RaftActorTest extends AbstractActorTest { } } } + } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java new file mode 100644 index 0000000000..6872c8fa45 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/TestActorFactory.java @@ -0,0 +1,117 @@ +/* + * 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.raft; + +/* + * 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 + */ + +import akka.actor.Actor; +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.PoisonPill; +import akka.actor.Props; +import akka.testkit.TestActorRef; +import java.util.LinkedList; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * TestActorFactory provides methods to create both normal and test actors and to kill them when the factory is closed + * The ideal usage for TestActorFactory is with try with resources,
+ * For example
+ *
+ *     try (TestActorFactory factory = new TestActorFactory(getSystem())){
+ *         factory.createActor(props);
+ *         factory.createTestActor(props);
+ *         factory.generateActorId("leader-");
+ *     }
+ * 
+ */ +public class TestActorFactory implements AutoCloseable { + private final ActorSystem system; + List createdActors = new LinkedList<>(); + Logger LOG = LoggerFactory.getLogger(getClass()); + private static int actorCount = 1; + + public TestActorFactory(ActorSystem system){ + this.system = system; + } + + /** + * Create a normal actor with an auto-generated name + * + * @param props + * @return + */ + public ActorRef createActor(Props props){ + ActorRef actorRef = system.actorOf(props); + createdActors.add(actorRef); + return actorRef; + } + + /** + * Create a normal actor with the passed in name + * @param props + * @param actorId name of actor + * @return + */ + public ActorRef createActor(Props props, String actorId){ + ActorRef actorRef = system.actorOf(props, actorId); + createdActors.add(actorRef); + return actorRef; + } + + /** + * Create a test actor with the passed in name + * @param props + * @param actorId + * @param + * @return + */ + public TestActorRef createTestActor(Props props, String actorId){ + TestActorRef actorRef = TestActorRef.create(system, props, actorId); + createdActors.add(actorRef); + return actorRef; + } + + /** + * Create a test actor with an auto-generated name + * @param props + * @param + * @return + */ + public TestActorRef createTestActor(Props props){ + TestActorRef actorRef = TestActorRef.create(system, props); + createdActors.add(actorRef); + return actorRef; + } + + /** + * Generate a friendly but unique actor id/name + * @param prefix + * @return + */ + public String generateActorId(String prefix){ + return prefix + actorCount++; + } + + @Override + public void close() throws Exception { + for(ActorRef actor : createdActors){ + LOG.info("Killing actor {}", actor); + actor.tell(PoisonPill.getInstance(), null); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderElectionScenariosTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderElectionScenariosTest.java new file mode 100644 index 0000000000..3aac005179 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderElectionScenariosTest.java @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2015 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.cluster.raft.behaviors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.actor.Props; +import akka.dispatch.Dispatchers; +import akka.testkit.JavaTestKit; +import akka.testkit.TestActorRef; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Uninterruptibles; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import org.junit.After; +import org.junit.Test; +import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl; +import org.opendaylight.controller.cluster.raft.MockRaftActorContext; +import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload; +import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry; +import org.opendaylight.controller.cluster.raft.MockRaftActorContext.SimpleReplicatedLog; +import org.opendaylight.controller.cluster.raft.RaftActorContext; +import org.opendaylight.controller.cluster.raft.RaftState; +import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout; +import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; +import org.opendaylight.controller.cluster.raft.messages.AppendEntries; +import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; +import org.opendaylight.controller.cluster.raft.messages.RequestVote; +import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply; +import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.impl.SimpleLogger; +import scala.concurrent.duration.FiniteDuration; + +/** + * Tests various leader election scenarios. + * + * @author Thomas Pantelis + */ +public class LeaderElectionScenariosTest { + + private static final int HEARTBEAT_INTERVAL = 50; + + public static class MemberActor extends MessageCollectorActor { + + volatile RaftActorBehavior behavior; + Map, CountDownLatch> messagesReceivedLatches = new ConcurrentHashMap<>(); + Map, Boolean> dropMessagesToBehavior = new ConcurrentHashMap<>(); + CountDownLatch behaviorStateChangeLatch; + + public static Props props() { + return Props.create(MemberActor.class).withDispatcher(Dispatchers.DefaultDispatcherId()); + } + + @Override + public void onReceive(Object message) throws Exception { + // Ignore scheduled SendHeartBeat messages. + if(message instanceof SendHeartBeat) { + return; + } + + try { + if(behavior != null && !dropMessagesToBehavior.containsKey(message.getClass())) { + RaftActorBehavior oldBehavior = behavior; + behavior = behavior.handleMessage(getSender(), message); + if(behavior != oldBehavior && behaviorStateChangeLatch != null) { + behaviorStateChangeLatch.countDown(); + } + } + } finally { + super.onReceive(message); + + CountDownLatch latch = messagesReceivedLatches.get(message.getClass()); + if(latch != null) { + latch.countDown(); + } + } + } + + void expectBehaviorStateChange() { + behaviorStateChangeLatch = new CountDownLatch(1); + } + + void waitForBehaviorStateChange() { + assertTrue("Expected behavior state change", + Uninterruptibles.awaitUninterruptibly(behaviorStateChangeLatch, 5, TimeUnit.SECONDS)); + } + + void expectMessageClass(Class expClass, int expCount) { + messagesReceivedLatches.put(expClass, new CountDownLatch(expCount)); + } + + void waitForExpectedMessages(Class expClass) { + CountDownLatch latch = messagesReceivedLatches.get(expClass); + assertNotNull("No messages received for " + expClass, latch); + assertTrue("Missing messages of type " + expClass, + Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS)); + } + + void dropMessagesToBehavior(Class msgClass) { + dropMessagesToBehavior(msgClass, 1); + } + + void dropMessagesToBehavior(Class msgClass, int expCount) { + expectMessageClass(msgClass, expCount); + dropMessagesToBehavior.put(msgClass, Boolean.TRUE); + } + + void clearDropMessagesToBehavior() { + dropMessagesToBehavior.clear(); + } + + @Override + public void clear() { + behaviorStateChangeLatch = null; + clearDropMessagesToBehavior(); + messagesReceivedLatches.clear(); + super.clear(); + } + + void forwardCapturedMessageToBehavior(Class msgClass, ActorRef sender) throws Exception { + Object message = getFirstMatching(getSelf(), msgClass); + assertNotNull("Message of type " + msgClass + " not received", message); + getSelf().tell(message, sender); + } + + void forwardCapturedMessagesToBehavior(Class msgClass, ActorRef sender) throws Exception { + for(Object m: getAllMatching(getSelf(), msgClass)) { + getSelf().tell(m, sender); + } + } + + T getCapturedMessage(Class msgClass) throws Exception { + Object message = getFirstMatching(getSelf(), msgClass); + assertNotNull("Message of type " + msgClass + " not received", message); + return (T) message; + } + } + + static { + System.setProperty(SimpleLogger.LOG_KEY_PREFIX + MockRaftActorContext.class.getName(), "trace"); + } + + private final Logger testLog = LoggerFactory.getLogger(MockRaftActorContext.class); + private final ActorSystem system = ActorSystem.create("test"); + + @After + public void tearDown() { + JavaTestKit.shutdownActorSystem(system); + } + + private DefaultConfigParamsImpl newConfigParams() { + DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl(); + configParams.setHeartBeatInterval(new FiniteDuration(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS)); + configParams.setElectionTimeoutFactor(100000); + configParams.setIsolatedLeaderCheckInterval(new FiniteDuration(1, TimeUnit.DAYS)); + return configParams; + } + + private MockRaftActorContext newRaftActorContext(String id, ActorRef actor, + Map peerAddresses) { + MockRaftActorContext context = new MockRaftActorContext(id, system, actor); + context.setPeerAddresses(peerAddresses); + context.getTermInformation().updateAndPersist(1, ""); + return context; + } + + private void verifyBehaviorState(String name, TestActorRef actor, RaftState expState) { + assertEquals(name + " behavior state", expState, actor.underlyingActor().behavior.state()); + } + + private void initializeLeaderBehavior(TestActorRef actor, RaftActorContext context, + int numActiveFollowers) throws Exception { + // Leader sends immediate heartbeats - we don't care about it so ignore it. + + actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, numActiveFollowers); + Leader leader = new Leader(context); + actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class); + actor.underlyingActor().behavior = leader; + + actor.underlyingActor().forwardCapturedMessagesToBehavior(AppendEntriesReply.class, ActorRef.noSender()); + actor.underlyingActor().clear(); + } + + private TestActorRef newMemberActor(String name) throws Exception { + TestActorRef actor = TestActorRef.create(system, MemberActor.props(), name); + MessageCollectorActor.waitUntilReady(actor); + return actor; + } + + private void sendHeartbeat(TestActorRef leaderActor) { + Uninterruptibles.sleepUninterruptibly(HEARTBEAT_INTERVAL, TimeUnit.MILLISECONDS); + leaderActor.underlyingActor().behavior.handleMessage(leaderActor, new SendHeartBeat()); + } + + @Test + public void testDelayedMessagesScenario() throws Exception { + testLog.info("Starting testDelayedMessagesScenario"); + + TestActorRef member1Actor = newMemberActor("member1"); + TestActorRef member2Actor = newMemberActor("member2"); + TestActorRef member3Actor = newMemberActor("member3"); + + // Create member 2's behavior initially as Follower + + MockRaftActorContext member2Context = newRaftActorContext("member2", member2Actor, + ImmutableMap.builder(). + put("member1", member1Actor.path().toString()). + put("member3", member3Actor.path().toString()).build()); + + DefaultConfigParamsImpl member2ConfigParams = newConfigParams(); + member2Context.setConfigParams(member2ConfigParams); + + Follower member2Behavior = new Follower(member2Context); + member2Actor.underlyingActor().behavior = member2Behavior; + + // Create member 3's behavior initially as Follower + + MockRaftActorContext member3Context = newRaftActorContext("member3", member3Actor, + ImmutableMap.builder(). + put("member1", member1Actor.path().toString()). + put("member2", member2Actor.path().toString()).build()); + + DefaultConfigParamsImpl member3ConfigParams = newConfigParams(); + member3Context.setConfigParams(member3ConfigParams); + + Follower member3Behavior = new Follower(member3Context); + member3Actor.underlyingActor().behavior = member3Behavior; + + // Create member 1's behavior initially as Leader + + MockRaftActorContext member1Context = newRaftActorContext("member1", member1Actor, + ImmutableMap.builder(). + put("member2", member2Actor.path().toString()). + put("member3", member3Actor.path().toString()).build()); + + DefaultConfigParamsImpl member1ConfigParams = newConfigParams(); + member1Context.setConfigParams(member1ConfigParams); + + initializeLeaderBehavior(member1Actor, member1Context, 2); + + member2Actor.underlyingActor().clear(); + member3Actor.underlyingActor().clear(); + + // Send ElectionTimeout to member 2 to simulate missing heartbeat from the Leader. member 2 + // should switch to Candidate and send out RequestVote messages. Set member 1 and 3 actors + // to capture RequestVote but not to forward to the behavior just yet as we want to + // control the order of RequestVote messages to member 1 and 3. + + member1Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class); + + member2Actor.underlyingActor().expectBehaviorStateChange(); + + member3Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class); + + member2Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + member2Actor.underlyingActor().waitForBehaviorStateChange(); + verifyBehaviorState("member 2", member2Actor, RaftState.Candidate); + + assertEquals("member 1 election term", 1, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 1, member3Context.getTermInformation().getCurrentTerm()); + + // At this point member 1 and 3 actors have captured the RequestVote messages. First + // forward the RequestVote message to member 1's behavior. Since the RequestVote term + // is greater than member 1's term, member 1 should switch to Follower without replying + // to RequestVote and update its term to 2. + + member1Actor.underlyingActor().clearDropMessagesToBehavior(); + member1Actor.underlyingActor().expectBehaviorStateChange(); + member1Actor.underlyingActor().forwardCapturedMessageToBehavior(RequestVote.class, member2Actor); + member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + member1Actor.underlyingActor().waitForBehaviorStateChange(); + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + + // Now forward member 3's captured RequestVote message to its behavior. Since member 3 is + // already a Follower, it should update its term to 2 and send a RequestVoteReply back to + // member 2 granting the vote b/c the RequestVote's term, lastLogTerm, and lastLogIndex + // should satisfy the criteria for granting the vote. However, we'll delay sending the + // RequestVoteReply to member 2's behavior to simulate network latency. + + member2Actor.underlyingActor().dropMessagesToBehavior(RequestVoteReply.class); + + member3Actor.underlyingActor().clearDropMessagesToBehavior(); + member3Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + member3Actor.underlyingActor().forwardCapturedMessageToBehavior(RequestVote.class, member2Actor); + member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + verifyBehaviorState("member 3", member3Actor, RaftState.Follower); + + assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm()); + + // Send ElectionTimeout to member 3 to simulate missing heartbeat from a Leader. member 3 + // should switch to Candidate and send out RequestVote messages. member 1 should grant the + // vote and send a reply. After receiving the RequestVoteReply, member 3 should switch to leader. + + member2Actor.underlyingActor().expectBehaviorStateChange(); + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1); + member3Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 2); + + member3Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member3Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class); + + RequestVoteReply requestVoteReply = member3Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class); + assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm()); + assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted()); + + verifyBehaviorState("member 3", member3Actor, RaftState.Leader); + + // member 2 should've switched to Follower as member 3's RequestVote term (3) was greater + // than member 2's term (2). + + member2Actor.underlyingActor().waitForBehaviorStateChange(); + verifyBehaviorState("member 2", member2Actor, RaftState.Follower); + + // The switch to leader should cause an immediate AppendEntries heartbeat from member 3. + + member3Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class); + + assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm()); + + // Now forward the original delayed RequestVoteReply from member 3 to member 2 that granted + // the vote. Since member 2 is now a Follower, the RequestVoteReply should be ignored. + + member2Actor.underlyingActor().clearDropMessagesToBehavior(); + member2Actor.underlyingActor().forwardCapturedMessageToBehavior(RequestVoteReply.class, member3Actor); + + member2Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class); + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + verifyBehaviorState("member 2", member2Actor, RaftState.Follower); + verifyBehaviorState("member 3", member3Actor, RaftState.Leader); + + assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm()); + + testLog.info("testDelayedMessagesScenario done"); + } + + @Test + public void testPartitionedLeadersScenario() throws Exception { + testLog.info("Starting testPartitionedLeadersScenario"); + + TestActorRef member1Actor = newMemberActor("member1"); + TestActorRef member2Actor = newMemberActor("member2"); + TestActorRef member3Actor = newMemberActor("member3"); + + // Create member 2's behavior initially as Follower + + MockRaftActorContext member2Context = newRaftActorContext("member2", member2Actor, + ImmutableMap.builder(). + put("member1", member1Actor.path().toString()). + put("member3", member3Actor.path().toString()).build()); + + DefaultConfigParamsImpl member2ConfigParams = newConfigParams(); + member2Context.setConfigParams(member2ConfigParams); + + Follower member2Behavior = new Follower(member2Context); + member2Actor.underlyingActor().behavior = member2Behavior; + + // Create member 3's behavior initially as Follower + + MockRaftActorContext member3Context = newRaftActorContext("member3", member3Actor, + ImmutableMap.builder(). + put("member1", member1Actor.path().toString()). + put("member2", member2Actor.path().toString()).build()); + + DefaultConfigParamsImpl member3ConfigParams = newConfigParams(); + member3Context.setConfigParams(member3ConfigParams); + + Follower member3Behavior = new Follower(member3Context); + member3Actor.underlyingActor().behavior = member3Behavior; + + // Create member 1's behavior initially as Leader + + MockRaftActorContext member1Context = newRaftActorContext("member1", member1Actor, + ImmutableMap.builder(). + put("member2", member2Actor.path().toString()). + put("member3", member3Actor.path().toString()).build()); + + DefaultConfigParamsImpl member1ConfigParams = newConfigParams(); + member1Context.setConfigParams(member1ConfigParams); + + initializeLeaderBehavior(member1Actor, member1Context, 2); + + member2Actor.underlyingActor().clear(); + member3Actor.underlyingActor().clear(); + + // Send ElectionTimeout to member 2 to simulate no heartbeat from the Leader (member 1). + // member 2 should switch to Candidate, start new term 2 and send out RequestVote messages. + // member 1 will switch to Follower b/c its term is less than the RequestVote term, also it + // won't send back a reply. member 3 will drop the message (ie won't forward it to its behavior) to + // simulate loss of network connectivity between member 2 and 3. + + member1Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + + member2Actor.underlyingActor().expectBehaviorStateChange(); + + member3Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class); + + member2Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + // member 1 should switch to Follower as the RequestVote term is greater than its term. It + // won't send back a RequestVoteReply in this case. + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + + // member 2 should switch to Candidate since member 1 didn't reply. + + member2Actor.underlyingActor().waitForBehaviorStateChange(); + verifyBehaviorState("member 2", member2Actor, RaftState.Candidate); + + assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 1, member3Context.getTermInformation().getCurrentTerm()); + + // Send ElectionTimeout to member 3 to simulate no heartbeat from the Leader (member 1). + // member 2 should switch to Candidate and send out RequestVote messages. member 1 will reply and + // grant the vote but member 2 will drop the message to simulate loss of network connectivity. + + member1Actor.underlyingActor().clear(); + member1Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1); + + member2Actor.underlyingActor().clear(); + member2Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class); + member2Actor.underlyingActor().dropMessagesToBehavior(AppendEntries.class); + + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1); + member3Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1); + + member3Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member3Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class); + + RequestVoteReply requestVoteReply = member3Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class); + assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm()); + assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted()); + + // when member 3 switches to Leader it will immediately send out heartbeat AppendEntries to + // the followers. Wait for AppendEntries to member 1 and its AppendEntriesReply. The + // AppendEntries message to member 2 is dropped. + + member1Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class); + member2Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class); + member3Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class); + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + verifyBehaviorState("member 2", member2Actor, RaftState.Candidate); + verifyBehaviorState("member 3", member3Actor, RaftState.Leader); + + assertEquals("member 1 election term", 2, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 2, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm()); + + // member 2 is partitioned from the Leader (member 3) and hasn't received any messages. It + // would get another ElectionTimeout so simulate that. member 1 should send back a reply + // granting the vote. Messages (RequestVote and AppendEntries) from member 2 to member 3 + // are dropped to simulate loss of network connectivity. Note member 2 will increment its + // election term to 3. + + member1Actor.underlyingActor().clear(); + member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1); + + member2Actor.underlyingActor().clear(); + member2Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1); + member2Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1); + + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().dropMessagesToBehavior(AppendEntries.class); + member3Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class); + + member2Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member2Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class); + + requestVoteReply = member2Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class); + assertEquals("getTerm", member2Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm()); + assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted()); + + member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + member1Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class); + member3Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class); + member2Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class); + + // We end up with 2 partitioned leaders both leading member 1. The term for member 1 and 3 + // is 3 and member 3's term is 2. + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + verifyBehaviorState("member 2", member2Actor, RaftState.Leader); + verifyBehaviorState("member 3", member3Actor, RaftState.Leader); + + assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 2, member3Context.getTermInformation().getCurrentTerm()); + + // Re-establish connectivity between member 2 and 3, ie stop dropping messages between + // the 2. Send heartbeats (AppendEntries) from member 3. Both member 1 and 2 should send back + // an unsuccessful AppendEntriesReply b/c their term (3) is greater than member 3's term (2). + // This should cause member 3 to switch to Follower. + + RaftActorBehavior savedMember1Behavior = member1Actor.underlyingActor().behavior; + RaftActorBehavior savedMember2Behavior = member2Actor.underlyingActor().behavior; + RaftActorBehavior savedMember3Behavior = member3Actor.underlyingActor().behavior; + long savedMember3Term = member3Context.getTermInformation().getCurrentTerm(); + String savedMember3VoterFor = member3Context.getTermInformation().getVotedFor(); + + member1Actor.underlyingActor().clear(); + member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1); + + member2Actor.underlyingActor().clear(); + member2Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1); + + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1); + + sendHeartbeat(member3Actor); + + member3Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class); + + AppendEntriesReply appendEntriesReply = member3Actor.underlyingActor(). + getCapturedMessage(AppendEntriesReply.class); + assertEquals("isSuccess", false, appendEntriesReply.isSuccess()); + assertEquals("getTerm", 3, appendEntriesReply.getTerm()); + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + verifyBehaviorState("member 2", member2Actor, RaftState.Leader); + verifyBehaviorState("member 3", member3Actor, RaftState.Follower); + + assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm()); + + // Revert back to the partitioned leaders state to test the other sequence where member 2 + // sends heartbeats first before member 3. member 1 should return a successful + // AppendEntriesReply b/c his term matches member 2's. member 3 should switch to Follower + // as his term is less than member 2's. + + member1Actor.underlyingActor().behavior = savedMember1Behavior; + member2Actor.underlyingActor().behavior = savedMember2Behavior; + member3Actor.underlyingActor().behavior = savedMember3Behavior; + + member3Context.getTermInformation().update(savedMember3Term, savedMember3VoterFor); + + member1Actor.underlyingActor().clear(); + member1Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1); + + member2Actor.underlyingActor().clear(); + member2Actor.underlyingActor().expectMessageClass(AppendEntriesReply.class, 1); + + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().expectMessageClass(AppendEntries.class, 1); + + sendHeartbeat(member2Actor); + + member1Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class); + member3Actor.underlyingActor().waitForExpectedMessages(AppendEntries.class); + + member2Actor.underlyingActor().waitForExpectedMessages(AppendEntriesReply.class); + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + verifyBehaviorState("member 2", member2Actor, RaftState.Leader); + verifyBehaviorState("member 3", member3Actor, RaftState.Follower); + + assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", 3, member3Context.getTermInformation().getCurrentTerm()); + + testLog.info("testPartitionedLeadersScenario done"); + } + + @Test + public void testPartitionedCandidateOnStartupScenario() throws Exception { + testLog.info("Starting testPartitionedCandidateOnStartupScenario"); + + TestActorRef member1Actor = newMemberActor("member1") ; + TestActorRef member2Actor = newMemberActor("member2"); + TestActorRef member3Actor = newMemberActor("member3"); + + // Create member 2's behavior as Follower. + + MockRaftActorContext member2Context = newRaftActorContext("member2", member2Actor, + ImmutableMap.builder(). + put("member1", member1Actor.path().toString()). + put("member3", member3Actor.path().toString()).build()); + + DefaultConfigParamsImpl member2ConfigParams = newConfigParams(); + member2Context.setConfigParams(member2ConfigParams); + + Follower member2Behavior = new Follower(member2Context); + member2Actor.underlyingActor().behavior = member2Behavior; + + // Create member 1's behavior as Leader. + + MockRaftActorContext member1Context = newRaftActorContext("member1", member1Actor, + ImmutableMap.builder(). + put("member2", member2Actor.path().toString()). + put("member3", member3Actor.path().toString()).build()); + + DefaultConfigParamsImpl member1ConfigParams = newConfigParams(); + member1Context.setConfigParams(member1ConfigParams); + + initializeLeaderBehavior(member1Actor, member1Context, 1); + + member2Actor.underlyingActor().clear(); + member3Actor.underlyingActor().clear(); + + // Initialize the ReplicatedLog and election term info for member 1 and 2. The current term + // will be 3 and the last term will be 2. + + SimpleReplicatedLog replicatedLog = new SimpleReplicatedLog(); + replicatedLog.append(new MockReplicatedLogEntry(2, 1, new MockPayload(""))); + replicatedLog.append(new MockReplicatedLogEntry(3, 1, new MockPayload(""))); + + member1Context.setReplicatedLog(replicatedLog); + member1Context.getTermInformation().update(3, ""); + + member2Context.setReplicatedLog(replicatedLog); + member2Context.getTermInformation().update(3, member1Context.getId()); + + // Create member 3's behavior initially as a Candidate. + + MockRaftActorContext member3Context = newRaftActorContext("member3", member3Actor, + ImmutableMap.builder(). + put("member1", member1Actor.path().toString()). + put("member2", member2Actor.path().toString()).build()); + + DefaultConfigParamsImpl member3ConfigParams = newConfigParams(); + member3Context.setConfigParams(member3ConfigParams); + + // Initialize the ReplicatedLog and election term info for Candidate member 3. The current term + // will be 2 and the last term will be 1 so it is behind the leader's log. + + SimpleReplicatedLog candidateReplicatedLog = new SimpleReplicatedLog(); + candidateReplicatedLog.append(new MockReplicatedLogEntry(1, 1, new MockPayload(""))); + candidateReplicatedLog.append(new MockReplicatedLogEntry(2, 1, new MockPayload(""))); + + member3Context.setReplicatedLog(candidateReplicatedLog); + member3Context.getTermInformation().update(2, member1Context.getId()); + + // The member 3 Candidate will start a new term and send RequestVotes. However it will be + // partitioned from the cluster by having member 1 and 2 drop its RequestVote messages. + + int numCandidateElections = 5; + long candidateElectionTerm = member3Context.getTermInformation().getCurrentTerm() + numCandidateElections; + + member1Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class, numCandidateElections); + + member2Actor.underlyingActor().dropMessagesToBehavior(RequestVote.class, numCandidateElections); + + Candidate member3Behavior = new Candidate(member3Context); + member3Actor.underlyingActor().behavior = member3Behavior; + + // Send several additional ElectionTimeouts to Candidate member 3. Each ElectionTimeout will + // start a new term so Candidate member 3's current term will be greater than the leader's + // current term. + + for(int i = 0; i < numCandidateElections - 1; i++) { + member3Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + } + + member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + verifyBehaviorState("member 1", member1Actor, RaftState.Leader); + verifyBehaviorState("member 2", member2Actor, RaftState.Follower); + verifyBehaviorState("member 3", member3Actor, RaftState.Candidate); + + assertEquals("member 1 election term", 3, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", 3, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", candidateElectionTerm, + member3Context.getTermInformation().getCurrentTerm()); + + // Now send a couple more ElectionTimeouts to Candidate member 3 with the partition resolved. + // + // On the first RequestVote, Leader member 1 should switch to Follower as its term (s) is less than + // the RequestVote's term (8) from member 3. No RequestVoteReply should be sent by member 1. + // Follower member 2 should update its term since it less than the RequestVote's term and + // should return a RequestVoteReply but should not grant the vote as its last term and index + // is greater than the RequestVote's lastLogTerm and lastLogIndex, ie member 2's log is later + // or more up to date than member 3's. + // + // On the second RequestVote, both member 1 and 2 are followers so they should update their + // term and return a RequestVoteReply but should not grant the vote. + + candidateElectionTerm += 2; + for(int i = 0; i < 2; i++) { + member1Actor.underlyingActor().clear(); + member1Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + member2Actor.underlyingActor().clear(); + member2Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1); + + member3Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member1Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + member3Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class); + + RequestVoteReply requestVoteReply = member3Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class); + assertEquals("getTerm", member3Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm()); + assertEquals("isVoteGranted", false, requestVoteReply.isVoteGranted()); + } + + verifyBehaviorState("member 1", member1Actor, RaftState.Follower); + verifyBehaviorState("member 2", member2Actor, RaftState.Follower); + verifyBehaviorState("member 3", member3Actor, RaftState.Candidate); + + // Even though member 3 didn't get voted for, member 1 and 2 should have updated their term + // to member 3's. + + assertEquals("member 1 election term", candidateElectionTerm, + member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", candidateElectionTerm, + member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", candidateElectionTerm, + member3Context.getTermInformation().getCurrentTerm()); + + // At this point we have no leader. Candidate member 3 would continue to start new elections + // but wouldn't be granted a vote. One of the 2 followers would eventually time out from + // not having received a heartbeat from a leader and switch to candidate and start a new + // election. We'll simulate that here by sending an ElectionTimeout to member 1. + + member1Actor.underlyingActor().clear(); + member1Actor.underlyingActor().expectMessageClass(RequestVoteReply.class, 1); + member2Actor.underlyingActor().clear(); + member2Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + member3Actor.underlyingActor().clear(); + member3Actor.underlyingActor().expectMessageClass(RequestVote.class, 1); + member3Actor.underlyingActor().expectBehaviorStateChange(); + + member1Actor.tell(new ElectionTimeout(), ActorRef.noSender()); + + member2Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + member3Actor.underlyingActor().waitForExpectedMessages(RequestVote.class); + + // The RequestVoteReply should come from Follower member 2 and the vote should be granted + // since member 2's last term and index matches member 1's. + + member1Actor.underlyingActor().waitForExpectedMessages(RequestVoteReply.class); + + RequestVoteReply requestVoteReply = member1Actor.underlyingActor().getCapturedMessage(RequestVoteReply.class); + assertEquals("getTerm", member1Context.getTermInformation().getCurrentTerm(), requestVoteReply.getTerm()); + assertEquals("isVoteGranted", true, requestVoteReply.isVoteGranted()); + + // Candidate member 3 should change to follower as its term should be less than the + // RequestVote term (member 1 started a new term higher than the other member's terms). + + member3Actor.underlyingActor().waitForBehaviorStateChange(); + + verifyBehaviorState("member 1", member1Actor, RaftState.Leader); + verifyBehaviorState("member 2", member2Actor, RaftState.Follower); + verifyBehaviorState("member 3", member3Actor, RaftState.Follower); + + // newTerm should be 10. + + long newTerm = candidateElectionTerm + 1; + assertEquals("member 1 election term", newTerm, member1Context.getTermInformation().getCurrentTerm()); + assertEquals("member 2 election term", newTerm, member2Context.getTermInformation().getCurrentTerm()); + assertEquals("member 3 election term", newTerm, member3Context.getTermInformation().getCurrentTerm()); + + testLog.info("testPartitionedCandidateOnStartupScenario done"); + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java index 3f551b3a30..8251c6b265 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java @@ -44,16 +44,10 @@ import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply; import org.opendaylight.controller.cluster.raft.utils.DoNothingActor; import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor; import org.opendaylight.controller.protobuff.messages.cluster.raft.InstallSnapshotMessages; -import org.slf4j.impl.SimpleLogger; import scala.concurrent.duration.FiniteDuration; public class LeaderTest extends AbstractRaftActorBehaviorTest { - static { - // This enables trace logging for the tests. - System.setProperty(SimpleLogger.LOG_KEY_PREFIX + MockRaftActorContext.class.getName(), "trace"); - } - private final ActorRef leaderActor = getSystem().actorOf(Props.create(DoNothingActor.class)); private final ActorRef senderActor = diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java index c5acb1f2a4..79c90cf051 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/utils/MessageCollectorActor.java @@ -17,6 +17,7 @@ import com.google.common.util.concurrent.Uninterruptibles; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; @@ -24,14 +25,21 @@ import scala.concurrent.duration.FiniteDuration; public class MessageCollectorActor extends UntypedActor { + private static final String ARE_YOU_READY = "ARE_YOU_READY"; + private final List messages = new ArrayList<>(); @Override public void onReceive(Object message) throws Exception { + if(message.equals(ARE_YOU_READY)) { + getSender().tell("yes", getSelf()); + return; + } + if(message instanceof String){ if("get-all-messages".equals(message)){ - getSender().tell(new ArrayList(messages), getSelf()); + getSender().tell(new ArrayList<>(messages), getSelf()); } - } else { + } else if(message != null) { messages.add(message); } } @@ -45,11 +53,7 @@ public class MessageCollectorActor extends UntypedActor { Timeout operationTimeout = new Timeout(operationDuration); Future future = Patterns.ask(actor, "get-all-messages", operationTimeout); - try { - return (List) Await.result(future, operationDuration); - } catch (Exception e) { - throw e; - } + return (List) Await.result(future, operationDuration); } /** @@ -88,4 +92,17 @@ public class MessageCollectorActor extends UntypedActor { return output; } + public static void waitUntilReady(ActorRef actor) throws Exception { + long timeout = 500; + FiniteDuration duration = Duration.create(timeout, TimeUnit.MILLISECONDS); + for(int i = 0; i < 10; i++) { + try { + Await.ready(Patterns.ask(actor, ARE_YOU_READY, timeout), duration); + return; + } catch (TimeoutException e) { + } + } + + throw new TimeoutException("Actor not ready in time."); + } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/resources/simplelogger.properties b/opendaylight/md-sal/sal-akka-raft/src/test/resources/simplelogger.properties new file mode 100644 index 0000000000..4e798073f6 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/test/resources/simplelogger.properties @@ -0,0 +1,6 @@ +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=hh:mm:ss,S a +org.slf4j.simpleLogger.logFile=System.out +org.slf4j.simpleLogger.showShortLogName=true +org.slf4j.simpleLogger.levelInBrackets=true +org.slf4j.simpleLogger.org.opendaylight.controller.cluster.raft=trace \ No newline at end of file diff --git a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf index f196ad1644..9da6a3b5a4 100644 --- a/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf +++ b/opendaylight/md-sal/sal-clustering-config/src/main/resources/initial/akka.conf @@ -39,7 +39,7 @@ odl-cluster-data { cluster { seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"] - auto-down-unreachable-after = 10s + auto-down-unreachable-after = 300s roles = [ "member-1" @@ -71,13 +71,16 @@ odl-cluster-rpc { netty.tcp { hostname = "127.0.0.1" port = 2551 + maximum-frame-size = 419430400 + send-buffer-size = 52428800 + receive-buffer-size = 52428800 } } cluster { seed-nodes = ["akka.tcp://odl-cluster-rpc@127.0.0.1:2551"] - auto-down-unreachable-after = 10s + auto-down-unreachable-after = 300s } } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java index 8a37dfee4d..1e2386ae1b 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java @@ -124,29 +124,20 @@ public abstract class ShardTransaction extends AbstractUntypedActorWithMetering protected void readData(DOMStoreReadTransaction transaction, ReadData message, final boolean returnSerialized) { - final ActorRef sender = getSender(); - final ActorRef self = getSelf(); - final YangInstanceIdentifier path = message.getPath(); - final CheckedFuture>, ReadFailedException> future = - transaction.read(path); - - future.addListener(new Runnable() { - @Override - public void run() { - try { - Optional> optional = future.checkedGet(); - ReadDataReply readDataReply = new ReadDataReply(optional.orNull()); - sender.tell((returnSerialized ? readDataReply.toSerializable(clientTxVersion): - readDataReply), self); + final YangInstanceIdentifier path = message.getPath(); + try { + final CheckedFuture>, ReadFailedException> future = transaction.read(path); + Optional> optional = future.checkedGet(); + ReadDataReply readDataReply = new ReadDataReply(optional.orNull()); - } catch (Exception e) { - shardStats.incrementFailedReadTransactionsCount(); - sender.tell(new akka.actor.Status.Failure(e), self); - } + sender().tell((returnSerialized ? readDataReply.toSerializable(clientTxVersion): readDataReply), self()); - } - }, getContext().dispatcher()); + } catch (Exception e) { + LOG.error(String.format("Unexpected error reading path %s", path), e); + shardStats.incrementFailedReadTransactionsCount(); + sender().tell(new akka.actor.Status.Failure(e), self()); + } } protected void dataExists(DOMStoreReadTransaction transaction, DataExists message, diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/simplelogger.properties b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/simplelogger.properties new file mode 100644 index 0000000000..9ed3d276a3 --- /dev/null +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/simplelogger.properties @@ -0,0 +1,6 @@ +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=hh:mm:ss,S a +org.slf4j.simpleLogger.logFile=System.out +org.slf4j.simpleLogger.showShortLogName=true +org.slf4j.simpleLogger.levelInBrackets=true +org.slf4j.simpleLogger.log.org.opendaylight.controller.cluster.datastore=trace \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcAvailabilityListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcAvailabilityListener.java new file mode 100644 index 0000000000..77d42a43c9 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcAvailabilityListener.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import java.util.Collection; +import java.util.EventListener; +import javax.annotation.Nonnull; + +/** + * An {@link EventListener} used to track RPC implementations becoming (un)available + * to a {@link DOMRpcService}. + */ +public interface DOMRpcAvailabilityListener extends EventListener { + /** + * Method invoked whenever an RPC type becomes available. + * + * @param rpcs RPC types newly available + */ + void onRpcAvailable(@Nonnull Collection rpcs); + + /** + * Method invoked whenever an RPC type becomes unavailable. + * + * @param rpcs RPC types which became unavailable + */ + void onRpcUnavailable(@Nonnull Collection rpcs); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcException.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcException.java new file mode 100644 index 0000000000..7ea4f4cf56 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcException.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +/** + * Base class for failures that can occur during RPC invocation. This covers + * transport and protocol-level failures. + */ +public abstract class DOMRpcException extends Exception { + private static final long serialVersionUID = 1L; + + /** + * Construct an new instance with a message and an empty cause. + * + * @param message Exception message + */ + protected DOMRpcException(final String message) { + super(message); + } + + /** + * Construct an new instance with a message and a cause. + * + * @param message Exception message + * @param cause Chained cause + */ + protected DOMRpcException(final String message, final Throwable cause) { + super(message, cause); + } +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java new file mode 100644 index 0000000000..1976913a17 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import com.google.common.base.Preconditions; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +/** + * Identifier of a RPC context. This is an extension of the YANG RPC, which + * always has global context. It allows an RPC to have a instance identifier + * attached, so that there can be multiple implementations bound to different + * contexts concurrently. + */ +public abstract class DOMRpcIdentifier { + private static final class Global extends DOMRpcIdentifier { + private Global(final @Nonnull SchemaPath type) { + super(type); + } + + @Override + public YangInstanceIdentifier getContextReference() { + return null; + } + } + + private static final class Local extends DOMRpcIdentifier { + private final YangInstanceIdentifier contextReference; + + private Local(final @Nonnull SchemaPath type, final @Nonnull YangInstanceIdentifier contextReference) { + super(type); + this.contextReference = Preconditions.checkNotNull(contextReference); + } + + @Override + public YangInstanceIdentifier getContextReference() { + return contextReference; + } + } + + private final SchemaPath type; + + private DOMRpcIdentifier(final SchemaPath type) { + this.type = Preconditions.checkNotNull(type); + } + + /** + * Create a global RPC identifier. + * + * @param type RPC type, SchemaPath of its definition, may not be null + * @return A global RPC identifier, guaranteed to be non-null. + */ + public static @Nonnull DOMRpcIdentifier create(final @Nonnull SchemaPath type) { + return new Global(type); + } + + /** + * Create an RPC identifier with a particular context reference. + * + * @param type RPC type, SchemaPath of its definition, may not be null + * @param contextReference Context reference, null means a global RPC identifier. + * @return A global RPC identifier, guaranteed to be non-null. + */ + public static @Nonnull DOMRpcIdentifier create(final @Nonnull SchemaPath type, final @Nullable YangInstanceIdentifier contextReference) { + if (contextReference == null) { + return new Global(type); + } else { + return new Local(type, contextReference); + } + } + + /** + * Return the RPC type. + * + * @return RPC type. + */ + public final @Nonnull SchemaPath getType() { + return type; + } + + /** + * Return the RPC context reference. Null value indicates global context. + * + * @return RPC context reference. + */ + public abstract @Nullable YangInstanceIdentifier getContextReference(); + + @Override + public final int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + type.hashCode(); + result = prime * result + (getContextReference() == null ? 0 : getContextReference().hashCode()); + return result; + } + + @Override + public final boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof DOMRpcIdentifier)) { + return false; + } + DOMRpcIdentifier other = (DOMRpcIdentifier) obj; + if (!type.equals(other.type)) { + return false; + } + return Objects.equals(getContextReference(), other.getContextReference()); + } + + @Override + public final String toString() { + return com.google.common.base.Objects.toStringHelper(this).omitNullValues().add("type", type).add("contextReference", getContextReference()).toString(); + } +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementation.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementation.java new file mode 100644 index 0000000000..c246c76270 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementation.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import com.google.common.util.concurrent.CheckedFuture; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Interface implemented by an individual RPC implementation. This API allows for dispatch + * implementations, e.g. an individual object handling a multitude of RPCs. + */ +public interface DOMRpcImplementation { + /** + * Initiate invocation of the RPC. Implementations of this method are + * expected to not block on external resources. + * + * @param rpc RPC identifier which was invoked + * @param input Input arguments, null if the RPC does not take any. + * @return A {@link CheckedFuture} which will return either a result structure, + * or report a subclass of {@link DOMRpcException} reporting a transport + * error. + */ + @Nonnull CheckedFuture invokeRpc(@Nonnull DOMRpcIdentifier rpc, @Nullable NormalizedNode input); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementationNotAvailableException.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementationNotAvailableException.java new file mode 100644 index 0000000000..cca9a452b8 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementationNotAvailableException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import com.google.common.base.Preconditions; +import javax.annotation.Nonnull; + +/** + * Exception indicating that no implementation of the requested RPC service is available. + */ +public class DOMRpcImplementationNotAvailableException extends DOMRpcException { + private static final long serialVersionUID = 1L; + + public DOMRpcImplementationNotAvailableException(@Nonnull final String format, final Object... args) { + super(String.format(format, args)); + } + + public DOMRpcImplementationNotAvailableException(@Nonnull final Throwable cause, @Nonnull final String format, final Object... args) { + super(String.format(format, args), Preconditions.checkNotNull(cause)); + } +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementationRegistration.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementationRegistration.java new file mode 100644 index 0000000000..0b8dff50bb --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcImplementationRegistration.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import org.opendaylight.yangtools.concepts.ObjectRegistration; + +/** + * A registration of a {@link DOMRpcImplementation}. Used to track and revoke a registration + * with a {@link DOMRpcProviderService}. + * + * @param RPC implementation type + */ +public interface DOMRpcImplementationRegistration extends ObjectRegistration { + @Override + void close(); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcProviderService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcProviderService.java new file mode 100644 index 0000000000..4a4f9656ba --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcProviderService.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import java.util.Set; +import javax.annotation.Nonnull; + +/** + * A {@link DOMService} which allows registration of RPC implementations with a conceptual + * router. The client counterpart of this service is {@link DOMRpcService}. + */ +public interface DOMRpcProviderService extends DOMService { + /** + * Register an {@link DOMRpcImplementation} object with this service. + * + * @param implementation RPC implementation, must not be null + * @param rpcs Array of supported RPC identifiers. Must not be null, empty, or contain a null element. + * Each identifier is added exactly once, no matter how many times it occurs. + * @return A {@link DOMRpcImplementationRegistration} object, guaranteed to be non-null. + * @throws NullPointerException if implementation or types is null + * @throws IllegalArgumentException if types is empty or contains a null element. + */ + @Nonnull DOMRpcImplementationRegistration registerRpcImplementation(@Nonnull T implementation, @Nonnull DOMRpcIdentifier... rpcs); + + /** + * Register an {@link DOMRpcImplementation} object with this service. + * + * @param implementation RPC implementation, must not be null + * @param rpcs Set of supported RPC identifiers. Must not be null, empty, or contain a null element. + * @return A {@link DOMRpcImplementationRegistration} object, guaranteed to be non-null. + * @throws NullPointerException if implementation or types is null + * @throws IllegalArgumentException if types is empty or contains a null element. + */ + @Nonnull DOMRpcImplementationRegistration registerRpcImplementation(@Nonnull T implementation, @Nonnull Set rpcs); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcResult.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcResult.java new file mode 100644 index 0000000000..5893688870 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcResult.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import java.util.Collection; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Interface defining a result of an RPC call. + */ +public interface DOMRpcResult { + /** + * Returns a set of errors and warnings which occurred during processing + * the call. + * + * @return a Collection of {@link RpcError}, guaranteed to be non-null. In case + * no errors are reported, an empty collection is returned. + */ + @Nonnull Collection getErrors(); + + /** + * Returns the value result of the call or null if no result is available. + * + * @return Invocation result, null if the operation has not produced a result. This might + * be the case if the operation does not produce a result, or if it failed. + */ + @Nullable NormalizedNode getResult(); +} diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcService.java new file mode 100644 index 0000000000..48f6ab6500 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcService.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 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.sal.dom.api; + +import com.google.common.util.concurrent.CheckedFuture; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +/** + * A {@link DOMService} which allows clients to invoke RPCs. The conceptual model of this + * service is that of a dynamic router, where the set of available RPC services can change + * dynamically. The service allows users to add a listener to track the process of + * RPCs becoming available. + */ +public interface DOMRpcService extends DOMService { + /** + * Initiate invocation of an RPC. This method is guaranteed to not block on any external + * resources. + * + * @param type SchemaPath of the RPC to be invoked + * @param input Input arguments, null if the RPC does not take any. + * @return A {@link CheckedFuture} which will return either a result structure, + * or report a subclass of {@link DOMRpcException} reporting a transport + * error. + */ + @Nonnull CheckedFuture invokeRpc(@Nonnull SchemaPath type, @Nullable NormalizedNode input); + + /** + * Register a {@link DOMRpcAvailabilityListener} with this service to receive notifications + * about RPC implementations becoming (un)available. The listener will be invoked with the + * current implementations reported and will be kept uptodate as implementations come and go. + * + * Users should note that using a listener does not necessarily mean that {@link #invokeRpc(SchemaPath, NormalizedNode)} + * will not report a failure due to {@link DOMRpcImplementationNotAvailableException} and + * need to be ready to handle it. Implementations are encouraged to take reasonable precautions + * to prevent this scenario from occurring. + * + * @param listener {@link DOMRpcAvailabilityListener} instance to register + * @return A {@link DOMRpcAvailabilityListenerRegistration} representing this registration. Performing + * a {@link DOMRpcAvailabilityListenerRegistration#close()} will cancel it. Returned object + * is guaranteed to be non-null. + */ + @Nonnull ListenerRegistration registerRpcListener(@Nonnull T listener); +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMRpcImplementationRegistration.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMRpcImplementationRegistration.java new file mode 100644 index 0000000000..f0ce2b69c7 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMRpcImplementationRegistration.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; + +/** + * Abstract base class for {@link DOMRpcImplementationRegistration} implementations. + */ +public abstract class AbstractDOMRpcImplementationRegistration extends AbstractObjectRegistration implements DOMRpcImplementationRegistration { + protected AbstractDOMRpcImplementationRegistration(final T instance) { + super(instance); + } +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMRpcProviderService.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMRpcProviderService.java new file mode 100644 index 0000000000..c1374264cc --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMRpcProviderService.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import com.google.common.collect.ImmutableSet; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService; + +/** + * Convenience abstract base class for {@link DOMRpcProviderService} implementations. + */ +public abstract class AbstractDOMRpcProviderService implements DOMRpcProviderService { + @Override + public final DOMRpcImplementationRegistration registerRpcImplementation(final T implementation, final DOMRpcIdentifier... types) { + return registerRpcImplementation(implementation, ImmutableSet.copyOf(types)); + } +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DefaultDOMRpcResult.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DefaultDOMRpcResult.java new file mode 100644 index 0000000000..269fd3537c --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/DefaultDOMRpcResult.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; +import org.opendaylight.yangtools.concepts.Immutable; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Utility class implementing {@link DefaultDOMRpcResult}. + */ +@Beta +public final class DefaultDOMRpcResult implements DOMRpcResult, Immutable, Serializable { + private static final long serialVersionUID = 1L; + private final Collection errors; + private final NormalizedNode result; + + private static Collection asCollection(final RpcError... errors) { + if (errors.length == 0) { + return Collections.emptyList(); + } else { + return Arrays.asList(errors); + } + } + + public DefaultDOMRpcResult(final NormalizedNode result, final RpcError... errors) { + this(result, asCollection(errors)); + } + + public DefaultDOMRpcResult(final RpcError... errors) { + this(null, asCollection(errors)); + } + + public DefaultDOMRpcResult(final NormalizedNode result) { + this(result, Collections.emptyList()); + } + + public DefaultDOMRpcResult(final NormalizedNode result, final @Nonnull Collection errors) { + this.result = result; + this.errors = Preconditions.checkNotNull(errors); + } + + public DefaultDOMRpcResult(final @Nonnull Collection errors) { + this(null, errors); + } + + @Override + public @Nonnull Collection getErrors() { + return errors; + } + + @Override + public NormalizedNode getResult() { + return result; + } + + @Override + public int hashCode() { + int ret = errors.hashCode(); + if (result != null) { + ret = 31 * ret + result.hashCode(); + } + return ret; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof DefaultDOMRpcResult)) { + return false; + } + + final DefaultDOMRpcResult other = (DefaultDOMRpcResult) obj; + if (!errors.equals(other.errors)) { + return false; + } + return Objects.equals(result, other.result); + } +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcImplementation.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcImplementation.java new file mode 100644 index 0000000000..e93f9417d4 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcImplementation.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import com.google.common.collect.ForwardingObject; +import com.google.common.util.concurrent.CheckedFuture; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcException; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Utility implementation which implements {@link DOMRpcImplementation} by forwarding it to + * a backing delegate. + */ +public abstract class ForwardingDOMRpcImplementation extends ForwardingObject implements DOMRpcImplementation { + @Override + protected abstract @Nonnull DOMRpcImplementation delegate(); + + @Override + public CheckedFuture invokeRpc(final DOMRpcIdentifier type, final NormalizedNode input) { + return delegate().invokeRpc(type, input); + } +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcProviderService.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcProviderService.java new file mode 100644 index 0000000000..99c4cad8a9 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcProviderService.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import com.google.common.collect.ForwardingObject; +import java.util.Set; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcIdentifier; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationRegistration; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService; + +/** + * Utility class which implements {@link DOMRpcProviderService} by forwarding + * requests to a backing instance. + */ +public abstract class ForwardingDOMRpcProviderService extends ForwardingObject implements DOMRpcProviderService { + @Override + protected abstract @Nonnull DOMRpcProviderService delegate(); + + @Override + public DOMRpcImplementationRegistration registerRpcImplementation(final T implementation, final DOMRpcIdentifier... types) { + return delegate().registerRpcImplementation(implementation, types); + } + + @Override + public DOMRpcImplementationRegistration registerRpcImplementation(final T implementation, final Set types) { + return delegate().registerRpcImplementation(implementation, types); + } +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcResult.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcResult.java new file mode 100644 index 0000000000..ba46d3facf --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcResult.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import com.google.common.collect.ForwardingObject; +import java.util.Collection; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * Utility class which implements {@link DOMRpcResult} by forwarding all methods + * to a backing instance. + */ +public abstract class ForwardingDOMRpcResult extends ForwardingObject implements DOMRpcResult { + @Override + protected abstract @Nonnull DOMRpcResult delegate(); + + @Override + public Collection getErrors() { + return delegate().getErrors(); + } + + @Override + public NormalizedNode getResult() { + return delegate().getResult(); + } +} diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcService.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcService.java new file mode 100644 index 0000000000..976d08623b --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMRpcService.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 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.sal.dom.spi; + +import com.google.common.collect.ForwardingObject; +import com.google.common.util.concurrent.CheckedFuture; +import javax.annotation.Nonnull; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcException; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; +import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; + +/** + * Utility {@link DOMRpcService} which forwards all requests to a backing delegate instance. + */ +public abstract class ForwardingDOMRpcService extends ForwardingObject implements DOMRpcService { + @Override + protected abstract @Nonnull DOMRpcService delegate(); + + @Override + public CheckedFuture invokeRpc(final SchemaPath type, final NormalizedNode input) { + return delegate().invokeRpc(type, input); + } + + @Override + public ListenerRegistration registerRpcListener(final T listener) { + return delegate().registerRpcListener(listener); + } +} diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java index e52fce7ae0..e4cc80fa74 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java @@ -78,6 +78,9 @@ public final class Main { @Arg(dest = "debug") public boolean debug; + @Arg(dest = "notification-file") + public File notificationFile; + static ArgumentParser getParser() { final ArgumentParser parser = ArgumentParsers.newArgumentParser("netconf testool"); @@ -95,6 +98,11 @@ public final class Main { .help("Directory containing yang schemas to describe simulated devices. Some schemas e.g. netconf monitoring and inet types are included by default") .dest("schemas-dir"); + parser.addArgument("--notification-file") + .type(File.class) + .help("Xml file containing notifications that should be sent to clients after create subscription is called") + .dest("notification-file"); + parser.addArgument("--starting-port") .type(Integer.class) .setDefault(17830) diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java index a5f4947474..0d7ee3b945 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java @@ -26,6 +26,7 @@ import io.netty.channel.local.LocalAddress; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; import java.io.Closeable; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -71,6 +72,14 @@ import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOper import org.opendaylight.controller.netconf.ssh.SshProxyServer; import org.opendaylight.controller.netconf.ssh.SshProxyServerConfiguration; import org.opendaylight.controller.netconf.ssh.SshProxyServerConfigurationBuilder; +import org.opendaylight.controller.netconf.test.tool.rpc.DataList; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedCommit; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedCreateSubscription; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedEditConfig; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedGet; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedGetConfig; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedLock; +import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedUnLock; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation; @@ -116,7 +125,7 @@ public class NetconfDeviceSimulator implements Closeable { this.nioExecutor = nioExecutor; } - private NetconfServerDispatcher createDispatcher(final Map moduleBuilders, final boolean exi, final int generateConfigsTimeout) { + private NetconfServerDispatcher createDispatcher(final Map moduleBuilders, final boolean exi, final int generateConfigsTimeout, final Optional notificationsFile) { final Set capabilities = Sets.newHashSet(Collections2.transform(moduleBuilders.keySet(), new Function() { @Override @@ -132,7 +141,7 @@ public class NetconfDeviceSimulator implements Closeable { final SessionIdProvider idProvider = new SessionIdProvider(); - final SimulatedOperationProvider simulatedOperationProvider = new SimulatedOperationProvider(idProvider, capabilities); + final SimulatedOperationProvider simulatedOperationProvider = new SimulatedOperationProvider(idProvider, capabilities, notificationsFile); final NetconfMonitoringOperationService monitoringService = new NetconfMonitoringOperationService(new NetconfMonitoringServiceImpl(simulatedOperationProvider)); simulatedOperationProvider.addService(monitoringService); @@ -183,7 +192,7 @@ public class NetconfDeviceSimulator implements Closeable { final Map moduleBuilders = parseSchemasToModuleBuilders(params); - final NetconfServerDispatcher dispatcher = createDispatcher(moduleBuilders, params.exi, params.generateConfigsTimeout); + final NetconfServerDispatcher dispatcher = createDispatcher(moduleBuilders, params.exi, params.generateConfigsTimeout, Optional.fromNullable(params.notificationFile)); int currentPort = params.startingPort; @@ -392,9 +401,9 @@ public class NetconfDeviceSimulator implements Closeable { private final Set netconfOperationServices; - public SimulatedOperationProvider(final SessionIdProvider idProvider, final Set caps) { + public SimulatedOperationProvider(final SessionIdProvider idProvider, final Set caps, final Optional notificationsFile) { this.idProvider = idProvider; - final SimulatedOperationService simulatedOperationService = new SimulatedOperationService(caps, idProvider.getCurrentSessionId()); + final SimulatedOperationService simulatedOperationService = new SimulatedOperationService(caps, idProvider.getCurrentSessionId(), notificationsFile); this.netconfOperationServices = Sets.newHashSet(simulatedOperationService); } @@ -433,10 +442,12 @@ public class NetconfDeviceSimulator implements Closeable { static class SimulatedOperationService implements NetconfOperationService { private final Set capabilities; private final long currentSessionId; + private final Optional notificationsFile; - public SimulatedOperationService(final Set capabilities, final long currentSessionId) { + public SimulatedOperationService(final Set capabilities, final long currentSessionId, final Optional notificationsFile) { this.capabilities = capabilities; this.currentSessionId = currentSessionId; + this.notificationsFile = notificationsFile; } @Override @@ -453,7 +464,8 @@ public class NetconfDeviceSimulator implements Closeable { final SimulatedCommit sCommit = new SimulatedCommit(String.valueOf(currentSessionId)); final SimulatedLock sLock = new SimulatedLock(String.valueOf(currentSessionId)); final SimulatedUnLock sUnlock = new SimulatedUnLock(String.valueOf(currentSessionId)); - return Sets.newHashSet(sGet, sGetConfig, sEditConfig, sCommit, sLock, sUnlock); + final SimulatedCreateSubscription sCreateSubs = new SimulatedCreateSubscription(String.valueOf(currentSessionId), notificationsFile); + return Sets.newHashSet(sGet, sGetConfig, sEditConfig, sCommit, sLock, sUnlock, sCreateSubs); } @Override diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/DataList.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/DataList.java similarity index 93% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/DataList.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/DataList.java index d6dd55cb4e..abc954e807 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/DataList.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/DataList.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import java.util.Collections; import java.util.List; diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedCommit.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedCommit.java similarity index 85% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedCommit.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedCommit.java index db3717fab4..cb91319699 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedCommit.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedCommit.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import com.google.common.base.Optional; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -17,9 +17,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -class SimulatedCommit extends AbstractConfigNetconfOperation { +public class SimulatedCommit extends AbstractConfigNetconfOperation { - SimulatedCommit(final String netconfSessionIdForReporting) { + public SimulatedCommit(final String netconfSessionIdForReporting) { super(null, netconfSessionIdForReporting); } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedCreateSubscription.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedCreateSubscription.java new file mode 100644 index 0000000000..abf51c4764 --- /dev/null +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedCreateSubscription.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.test.tool.rpc; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlRootElement; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.impl.NetconfServerSession; +import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultNetconfOperation; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +public class SimulatedCreateSubscription extends AbstractLastNetconfOperation implements DefaultNetconfOperation { + + private NetconfServerSession session; + private final Optional notifications; + private ScheduledExecutorService scheduledExecutorService; + + public SimulatedCreateSubscription(final String id, final Optional notificationsFile) { + super(id); + if(notificationsFile.isPresent()) { + notifications = Optional.of(loadNotifications(notificationsFile.get())); + scheduledExecutorService = Executors.newScheduledThreadPool(1); + } else { + notifications = Optional.absent(); + } + } + + private Notifications loadNotifications(final File file) { + try { + final JAXBContext jaxbContext = JAXBContext.newInstance(Notifications.class); + final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); + return (Notifications) jaxbUnmarshaller.unmarshal(file); + } catch (final JAXBException e) { + throw new IllegalArgumentException("Canot parse file " + file + " as a notifications file", e); + } + } + + @Override + protected String getOperationName() { + return "create-subscription"; + } + + @Override + protected String getOperationNamespace() { + return "urn:ietf:params:xml:ns:netconf:notification:1.0"; + } + + @Override + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { + + + if(notifications.isPresent()) { + long delayAggregator = 0; + System.console().writer().println("Scheduling notifications " + notifications.get()); + + for (final Notification notification : notifications.get().getNotificationList()) { + for (int i = 0; i <= notification.getTimes(); i++) { + + delayAggregator += notification.getDelayInSeconds(); + + System.console().writer().println("Times " + notification.getTimes()); + scheduledExecutorService.schedule(new Runnable() { + @Override + public void run() { + try { + System.console().writer().println("Sending actual notification " + notification); + Preconditions.checkState(session != null, "Session is not set, cannot process notifications"); + session.sendMessage(parseNetconfNotification(notification.getContent())); + } catch (IOException | SAXException e) { + throw new IllegalStateException("Unable to process notification " + notification, e); + } + } + }, delayAggregator, TimeUnit.SECONDS); + } + } + } + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); + } + + private static NetconfMessage parseNetconfNotification(String content) throws IOException, SAXException { + final int startEventTime = content.indexOf("") + "".length(); + final int endEventTime = content.indexOf(""); + final String eventTime = content.substring(startEventTime, endEventTime); + if(eventTime.equals("XXXX")) { + content = content.replace(eventTime, new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date())); + } + + return new NetconfMessage(XmlUtil.readXmlToDocument(content)); + } + + @Override + public void setNetconfSession(final NetconfServerSession s) { + this.session = s; + } + + @XmlRootElement(name = "notifications") + public static final class Notifications { + + @javax.xml.bind.annotation.XmlElement(nillable = false, name = "notification", required = true) + private List notificationList; + + public List getNotificationList() { + return notificationList; + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Notifications{"); + sb.append("notificationList=").append(notificationList); + sb.append('}'); + return sb.toString(); + } + } + + public static final class Notification { + + @javax.xml.bind.annotation.XmlElement(nillable = false, name = "delay") + private long delayInSeconds; + + @javax.xml.bind.annotation.XmlElement(nillable = false, name = "times") + private long times; + + @javax.xml.bind.annotation.XmlElement(nillable = false, name = "content", required = true) + private String content; + + public long getDelayInSeconds() { + return delayInSeconds; + } + + public long getTimes() { + return times; + } + + public String getContent() { + return content; + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("Notification{"); + sb.append("delayInSeconds=").append(delayInSeconds); + sb.append(", times=").append(times); + sb.append(", content='").append(content).append('\''); + sb.append('}'); + return sb.toString(); + } + } +} diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedEditConfig.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedEditConfig.java similarity index 91% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedEditConfig.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedEditConfig.java index fd4cd136fd..9ba73f4e3a 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedEditConfig.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedEditConfig.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import com.google.common.base.Optional; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -19,13 +19,13 @@ import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; -class SimulatedEditConfig extends AbstractConfigNetconfOperation { +public class SimulatedEditConfig extends AbstractConfigNetconfOperation { private static final String DELETE_EDIT_CONFIG = "delete"; private static final String OPERATION = "operation"; private static final String REMOVE_EDIT_CONFIG = "remove"; private final DataList storage; - SimulatedEditConfig(final String netconfSessionIdForReporting, final DataList storage) { + public SimulatedEditConfig(final String netconfSessionIdForReporting, final DataList storage) { super(null, netconfSessionIdForReporting); this.storage = storage; } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGet.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedGet.java similarity index 87% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGet.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedGet.java index 1c24213ca7..24d2fcc35e 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGet.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedGet.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import com.google.common.base.Optional; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -17,11 +17,11 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -class SimulatedGet extends AbstractConfigNetconfOperation { +public class SimulatedGet extends AbstractConfigNetconfOperation { private final DataList storage; - SimulatedGet(final String netconfSessionIdForReporting, final DataList storage) { + public SimulatedGet(final String netconfSessionIdForReporting, final DataList storage) { super(null, netconfSessionIdForReporting); this.storage = storage; } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGetConfig.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedGetConfig.java similarity index 87% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGetConfig.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedGetConfig.java index cc1258eee4..985cb4015e 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedGetConfig.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedGetConfig.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import com.google.common.base.Optional; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -17,11 +17,11 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -class SimulatedGetConfig extends AbstractConfigNetconfOperation { +public class SimulatedGetConfig extends AbstractConfigNetconfOperation { private final DataList storage; - SimulatedGetConfig(final String netconfSessionIdForReporting, final DataList storage) { + public SimulatedGetConfig(final String netconfSessionIdForReporting, final DataList storage) { super(null, netconfSessionIdForReporting); this.storage = storage; } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedLock.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedLock.java similarity index 85% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedLock.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedLock.java index 4717e5464f..71b77a0825 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedLock.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedLock.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import com.google.common.base.Optional; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -17,9 +17,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -class SimulatedLock extends AbstractConfigNetconfOperation { +public class SimulatedLock extends AbstractConfigNetconfOperation { - SimulatedLock(final String netconfSessionIdForReporting) { + public SimulatedLock(final String netconfSessionIdForReporting) { super(null, netconfSessionIdForReporting); } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedUnLock.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedUnLock.java similarity index 85% rename from opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedUnLock.java rename to opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedUnLock.java index 31f9fc13ab..9d970b7bb5 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedUnLock.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/rpc/SimulatedUnLock.java @@ -6,7 +6,7 @@ * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.controller.netconf.test.tool; +package org.opendaylight.controller.netconf.test.tool.rpc; import com.google.common.base.Optional; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; @@ -17,9 +17,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; -class SimulatedUnLock extends AbstractConfigNetconfOperation { +public class SimulatedUnLock extends AbstractConfigNetconfOperation { - SimulatedUnLock(final String netconfSessionIdForReporting) { + public SimulatedUnLock(final String netconfSessionIdForReporting) { super(null, netconfSessionIdForReporting); } diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java index 33043d4389..b97a554f60 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallNorthbound.java @@ -187,13 +187,19 @@ public class NeutronFirewallNorthbound { firewallInterface.addNeutronFirewall(singleton); Object[] instances = NeutronUtil.getInstances(INeutronFirewallAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallAware service = (INeutronFirewallAware) instance; - int status = service.canCreateNeutronFirewall(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallAware service = (INeutronFirewallAware) instance; + int status = service.canCreateNeutronFirewall(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } firewallInterface.addNeutronFirewall(singleton); if (instances != null) { @@ -220,13 +226,19 @@ public class NeutronFirewallNorthbound { throw new BadRequestException("Firewall UUID already exists"); } if (instances != null) { - for (Object instance : instances) { - INeutronFirewallAware service = (INeutronFirewallAware) instance; - int status = service.canCreateNeutronFirewall(test); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallAware service = (INeutronFirewallAware) instance; + int status = service.canCreateNeutronFirewall(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } @@ -298,13 +310,19 @@ public class NeutronFirewallNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronFirewallAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallAware service = (INeutronFirewallAware) instance; - int status = service.canUpdateNeutronFirewall(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallAware service = (INeutronFirewallAware) instance; + int status = service.canUpdateNeutronFirewall(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -352,13 +370,19 @@ public class NeutronFirewallNorthbound { NeutronFirewall singleton = firewallInterface.getNeutronFirewall(firewallUUID); Object[] instances = NeutronUtil.getInstances(INeutronFirewallAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallAware service = (INeutronFirewallAware) instance; - int status = service.canDeleteNeutronFirewall(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallAware service = (INeutronFirewallAware) instance; + int status = service.canDeleteNeutronFirewall(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java index 08e563138c..e9b813d731 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallPolicyNorthbound.java @@ -184,13 +184,19 @@ public class NeutronFirewallPolicyNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronFirewallPolicyAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; - int status = service.canCreateNeutronFirewallPolicy(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; + int status = service.canCreateNeutronFirewallPolicy(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } firewallPolicyInterface.addNeutronFirewallPolicy(singleton); if (instances != null) { @@ -218,13 +224,19 @@ public class NeutronFirewallPolicyNorthbound { throw new BadRequestException("Firewall Policy UUID already exists"); } if (instances != null) { - for (Object instance : instances) { - INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; - int status = service.canCreateNeutronFirewallPolicy(test); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; + int status = service.canCreateNeutronFirewallPolicy(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -295,13 +307,19 @@ public class NeutronFirewallPolicyNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronFirewallPolicyAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; - int status = service.canUpdateNeutronFirewallPolicy(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; + int status = service.canUpdateNeutronFirewallPolicy(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -349,13 +367,19 @@ public class NeutronFirewallPolicyNorthbound { NeutronFirewallPolicy singleton = firewallPolicyInterface.getNeutronFirewallPolicy(firewallPolicyUUID); Object[] instances = NeutronUtil.getInstances(INeutronFirewallPolicyAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; - int status = service.canDeleteNeutronFirewallPolicy(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallPolicyAware service = (INeutronFirewallPolicyAware) instance; + int status = service.canDeleteNeutronFirewallPolicy(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } firewallPolicyInterface.removeNeutronFirewallPolicy(firewallPolicyUUID); diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java index 5e51711e5b..40b830da55 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFirewallRulesNorthbound.java @@ -220,13 +220,19 @@ public class NeutronFirewallRulesNorthbound { firewallRuleInterface.addNeutronFirewallRule(singleton); Object[] instances = NeutronUtil.getInstances(INeutronFirewallRuleAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; - int status = service.canCreateNeutronFirewallRule(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; + int status = service.canCreateNeutronFirewallRule(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // add rule to cache singleton.initDefaults(); @@ -256,13 +262,19 @@ public class NeutronFirewallRulesNorthbound { throw new BadRequestException("Firewall Rule UUID already exists"); } if (instances != null) { - for (Object instance : instances) { - INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; - int status = service.canCreateNeutronFirewallRule(test); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; + int status = service.canCreateNeutronFirewallRule(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -342,13 +354,19 @@ public class NeutronFirewallRulesNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronFirewallRuleAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; - int status = service.canUpdateNeutronFirewallRule(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; + int status = service.canUpdateNeutronFirewallRule(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -399,13 +417,19 @@ public class NeutronFirewallRulesNorthbound { NeutronFirewallRule singleton = firewallRuleInterface.getNeutronFirewallRule(firewallRuleUUID); Object[] instances = NeutronUtil.getInstances(INeutronFirewallRuleAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; - int status = service.canDeleteNeutronFirewallRule(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFirewallRuleAware service = (INeutronFirewallRuleAware) instance; + int status = service.canDeleteNeutronFirewallRule(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java index 812a09a0a6..3e6c2a4feb 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java @@ -242,12 +242,18 @@ public class NeutronFloatingIPsNorthbound { } Object[] instances = NeutronUtil.getInstances(INeutronFloatingIPAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; - int status = service.canCreateFloatingIP(singleton); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + int status = service.canCreateFloatingIP(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } floatingIPInterface.addFloatingIP(singleton); if (instances != null) { @@ -363,12 +369,18 @@ public class NeutronFloatingIPsNorthbound { NeutronFloatingIP target = floatingIPInterface.getFloatingIP(floatingipUUID); Object[] instances = NeutronUtil.getInstances(INeutronFloatingIPAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; - int status = service.canUpdateFloatingIP(singleton, target); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + int status = service.canUpdateFloatingIP(singleton, target); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } floatingIPInterface.updateFloatingIP(floatingipUUID, singleton); target = floatingIPInterface.getFloatingIP(floatingipUUID); @@ -406,12 +418,18 @@ public class NeutronFloatingIPsNorthbound { NeutronFloatingIP singleton = floatingIPInterface.getFloatingIP(floatingipUUID); Object[] instances = NeutronUtil.getInstances(INeutronFloatingIPAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; - int status = service.canDeleteFloatingIP(singleton); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + int status = service.canDeleteFloatingIP(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } floatingIPInterface.removeFloatingIP(floatingipUUID); if (instances != null) { diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerHealthMonitorNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerHealthMonitorNorthbound.java index 85aba5d690..aa30e948a2 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerHealthMonitorNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerHealthMonitorNorthbound.java @@ -210,13 +210,19 @@ public class NeutronLoadBalancerHealthMonitorNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerHealthMonitorAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance; + int status = service.canCreateNeutronLoadBalancerHealthMonitor(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } loadBalancerHealthMonitorInterface.addNeutronLoadBalancerHealthMonitor(singleton); if (instances != null) { @@ -245,13 +251,19 @@ public class NeutronLoadBalancerHealthMonitorNorthbound { 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance; + int status = service.canCreateNeutronLoadBalancerHealthMonitor(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -328,13 +340,19 @@ public class NeutronLoadBalancerHealthMonitorNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerHealthMonitorAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance; + int status = service.canUpdateNeutronLoadBalancerHealthMonitor(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -386,13 +404,19 @@ public class NeutronLoadBalancerHealthMonitorNorthbound { NeutronLoadBalancerHealthMonitor singleton = loadBalancerHealthMonitorInterface.getNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID); Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerHealthMonitorAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerHealthMonitorAware service = (INeutronLoadBalancerHealthMonitorAware) instance; + int status = service.canDeleteNeutronLoadBalancerHealthMonitor(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } loadBalancerHealthMonitorInterface.removeNeutronLoadBalancerHealthMonitor(loadBalancerHealthMonitorID); if (instances != null) { diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerListenerNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerListenerNorthbound.java index 345c7ee0f3..5d877c59f4 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerListenerNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerListenerNorthbound.java @@ -198,13 +198,19 @@ public class NeutronLoadBalancerListenerNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerListenerAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance; + int status = service.canCreateNeutronLoadBalancerListener(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } loadBalancerListenerInterface.addNeutronLoadBalancerListener(singleton); if (instances != null) { @@ -232,13 +238,19 @@ public class NeutronLoadBalancerListenerNorthbound { 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance; + int status = service.canCreateNeutronLoadBalancerListener(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -312,13 +324,19 @@ public class NeutronLoadBalancerListenerNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerListenerAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance; + int status = service.canUpdateNeutronLoadBalancerListener(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -366,13 +384,19 @@ public class NeutronLoadBalancerListenerNorthbound { NeutronLoadBalancerListener singleton = loadBalancerListenerInterface.getNeutronLoadBalancerListener(loadBalancerListenerID); Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerListenerAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerListenerAware service = (INeutronLoadBalancerListenerAware) instance; + int status = service.canDeleteNeutronLoadBalancerListener(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } loadBalancerListenerInterface.removeNeutronLoadBalancerListener(loadBalancerListenerID); diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerNorthbound.java index 308041fe59..67557ce41f 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerNorthbound.java @@ -186,14 +186,21 @@ public class NeutronLoadBalancerNorthbound { } Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance; + int status = service.canCreateNeutronLoadBalancer(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } + loadBalancerInterface.addNeutronLoadBalancer(singleton); if (instances != null) { for (Object instance : instances) { @@ -220,13 +227,19 @@ public class NeutronLoadBalancerNorthbound { 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance; + int status = service.canCreateNeutronLoadBalancer(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -298,13 +311,19 @@ public class NeutronLoadBalancerNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance; + int status = service.canUpdateNeutronLoadBalancer(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -355,15 +374,22 @@ public class NeutronLoadBalancerNorthbound { NeutronLoadBalancer singleton = loadBalancerInterface.getNeutronLoadBalancer(loadBalancerID); Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerAware service = (INeutronLoadBalancerAware) instance; + int status = service.canDeleteNeutronLoadBalancer(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } + loadBalancerInterface.removeNeutronLoadBalancer(loadBalancerID); if (instances != null) { for (Object instance : instances) { diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolMembersNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolMembersNorthbound.java index f9540679cd..22d118ae79 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolMembersNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolMembersNorthbound.java @@ -200,14 +200,21 @@ public Response createLoadBalancerPoolMember( Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolMemberAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance; + int status = service.canCreateNeutronLoadBalancerPoolMember(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } + if (instances != null) { for (Object instance : instances) { INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance; @@ -242,13 +249,19 @@ public Response createLoadBalancerPoolMember( 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance; + int status = service.canCreateNeutronLoadBalancerPoolMember(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -334,13 +347,19 @@ public Response deleteLoadBalancerPoolMember( Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolMemberAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance; - int status = service.canDeleteNeutronLoadBalancerPoolMember(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolMemberAware service = (INeutronLoadBalancerPoolMemberAware) instance; + int status = service.canDeleteNeutronLoadBalancerPoolMember(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } if (instances != null) { diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolNorthbound.java index 77bb525c84..ea4e2d1c9a 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronLoadBalancerPoolNorthbound.java @@ -198,13 +198,19 @@ public class NeutronLoadBalancerPoolNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance; + int status = service.canCreateNeutronLoadBalancerPool(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } loadBalancerPoolInterface.addNeutronLoadBalancerPool(singleton); if (instances != null) { @@ -232,13 +238,19 @@ public class NeutronLoadBalancerPoolNorthbound { 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance; + int status = service.canCreateNeutronLoadBalancerPool(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } /* @@ -311,13 +323,19 @@ public class NeutronLoadBalancerPoolNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolAware.class, this); 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(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance; + int status = service.canUpdateNeutronLoadBalancerPool(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -366,13 +384,19 @@ public class NeutronLoadBalancerPoolNorthbound { NeutronLoadBalancerPool singleton = loadBalancerPoolInterface.getNeutronLoadBalancerPool(loadBalancerPoolUUID); Object[] instances = NeutronUtil.getInstances(INeutronLoadBalancerPoolAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance; - int status = service.canDeleteNeutronLoadBalancerPool(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronLoadBalancerPoolAware service = (INeutronLoadBalancerPoolAware) instance; + int status = service.canDeleteNeutronLoadBalancerPool(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java index 9c99f346e8..3a3c657956 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java @@ -204,13 +204,19 @@ public class NeutronNetworksNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronNetworkAware service = (INeutronNetworkAware) instance; - int status = service.canCreateNetwork(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + int status = service.canCreateNetwork(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // add network to cache @@ -242,13 +248,19 @@ public class NeutronNetworksNorthbound { throw new BadRequestException("network UUID already exists"); } if (instances != null) { - for (Object instance: instances) { - INeutronNetworkAware service = (INeutronNetworkAware) instance; - int status = service.canCreateNetwork(test); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance: instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + int status = service.canCreateNetwork(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } testMap.put(test.getID(),test); } @@ -312,14 +324,20 @@ public class NeutronNetworksNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronNetworkAware service = (INeutronNetworkAware) instance; - NeutronNetwork original = networkInterface.getNetwork(netUUID); - int status = service.canUpdateNetwork(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + NeutronNetwork original = networkInterface.getNetwork(netUUID); + int status = service.canUpdateNetwork(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // update network object and return the modified object @@ -366,14 +384,21 @@ public class NeutronNetworksNorthbound { NeutronNetwork singleton = networkInterface.getNetwork(netUUID); Object[] instances = NeutronUtil.getInstances(INeutronNetworkAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronNetworkAware service = (INeutronNetworkAware) instance; - int status = service.canDeleteNetwork(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + int status = service.canDeleteNetwork(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } + networkInterface.removeNetwork(netUUID); if (instances != null) { for (Object instance : instances) { diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java index 23f4979f23..5ff3de58d6 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java @@ -259,16 +259,21 @@ public class NeutronPortsNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronPortAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronPortAware service = (INeutronPortAware) instance; - int status = service.canCreatePort(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canCreatePort(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } - // add the port to the cache portInterface.addPort(singleton); if (instances != null) { @@ -353,13 +358,19 @@ public class NeutronPortsNorthbound { } } if (instances != null) { - for (Object instance : instances) { - INeutronPortAware service = (INeutronPortAware) instance; - int status = service.canCreatePort(test); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canCreatePort(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } @@ -429,13 +440,19 @@ public class NeutronPortsNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronPortAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronPortAware service = (INeutronPortAware) instance; - int status = service.canUpdatePort(singleton, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canUpdatePort(singleton, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // Verify the new fixed ips are valid @@ -511,13 +528,19 @@ public class NeutronPortsNorthbound { NeutronPort singleton = portInterface.getPort(portUUID); Object[] instances = NeutronUtil.getInstances(INeutronPortAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronPortAware service = (INeutronPortAware) instance; - int status = service.canDeletePort(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canDeletePort(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } portInterface.removePort(portUUID); if (instances != null) { diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java index 45e84f4d15..ccf5ddd1a4 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java @@ -194,12 +194,18 @@ public class NeutronRoutersNorthbound { } Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronRouterAware service = (INeutronRouterAware) instance; - int status = service.canCreateRouter(singleton); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canCreateRouter(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -270,12 +276,18 @@ public class NeutronRoutersNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronRouterAware service = (INeutronRouterAware) instance; - int status = service.canUpdateRouter(singleton, original); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canUpdateRouter(singleton, original); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* * if the external gateway info is being changed, verify that the new network @@ -335,12 +347,18 @@ public class NeutronRoutersNorthbound { NeutronRouter singleton = routerInterface.getRouter(routerUUID); Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronRouterAware service = (INeutronRouterAware) instance; - int status = service.canDeleteRouter(singleton); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canDeleteRouter(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } routerInterface.removeRouter(routerUUID); if (instances != null) { @@ -415,12 +433,18 @@ public class NeutronRoutersNorthbound { throw new ResourceConflictException("Target Port already allocated"); Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronRouterAware service = (INeutronRouterAware) instance; - int status = service.canAttachInterface(target, input); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canAttachInterface(target, input); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } //mark the port device id and device owner fields @@ -493,12 +517,18 @@ public class NeutronRoutersNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronRouterAware service = (INeutronRouterAware) instance; - int status = service.canDetachInterface(target, input); - if (status < 200 || status > 299) - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canDetachInterface(target, input); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // reset the port ownership @@ -528,11 +558,25 @@ public class NeutronRoutersNorthbound { input.setSubnetUUID(targetInterface.getSubnetUUID()); input.setID(target.getID()); input.setTenantID(target.getTenantID()); + Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); + if (instances != null) { + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canDetachInterface(target, input); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); + } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); + } NeutronPort port = portInterface.getPort(input.getPortUUID()); port.setDeviceID(null); port.setDeviceOwner(null); target.removeInterface(input.getPortUUID()); - Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); for (Object instance : instances) { INeutronRouterAware service = (INeutronRouterAware) instance; service.neutronRouterInterfaceDetached(target, input); @@ -560,19 +604,32 @@ public class NeutronRoutersNorthbound { } if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress())) throw new ResourceConflictException("Target Port IP not in Target Subnet"); - input.setID(target.getID()); - input.setTenantID(target.getTenantID()); Object[] instances = NeutronUtil.getInstances(INeutronRouterAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronRouterAware service = (INeutronRouterAware) instance; - service.canDetachInterface(target, input); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canDetachInterface(target, input); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } + input.setID(target.getID()); + input.setTenantID(target.getTenantID()); port.setDeviceID(null); port.setDeviceOwner(null); target.removeInterface(input.getPortUUID()); - for (Object instance : instances) { + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.canDetachInterface(target, input); + } + } for (Object instance : instances) { INeutronRouterAware service = (INeutronRouterAware) instance; service.neutronRouterInterfaceDetached(target, input); } diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java index bce4de7cc2..d9ca6d4512 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityGroupsNorthbound.java @@ -178,13 +178,19 @@ public class NeutronSecurityGroupsNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronSecurityGroupAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; - int status = service.canCreateNeutronSecurityGroup(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canCreateNeutronSecurityGroup(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // Add to Neutron cache securityGroupInterface.addNeutronSecurityGroup(singleton); @@ -209,10 +215,18 @@ public class NeutronSecurityGroupsNorthbound { if (securityGroupInterface.neutronSecurityGroupExists(test.getSecurityGroupUUID())) { throw new BadRequestException("Security Group UUID already is already created"); } - if (instances != null) for (Object instance : instances) { - INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; - int status = service.canCreateNeutronSecurityGroup(test); - if ((status < 200) || (status > 299)) return Response.status(status).build(); + if (instances != null) { + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canCreateNeutronSecurityGroup(test); + if ((status < 200) || (status > 299)) return Response.status(status).build(); + } + } else { + throw new BadRequestException("No providers registered. Please try again later"); + } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } @@ -278,13 +292,19 @@ public class NeutronSecurityGroupsNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronSecurityGroupAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; - int status = service.canUpdateNeutronSecurityGroup(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canUpdateNeutronSecurityGroup(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -333,13 +353,19 @@ public class NeutronSecurityGroupsNorthbound { NeutronSecurityGroup singleton = securityGroupInterface.getNeutronSecurityGroup(securityGroupUUID); Object[] instances = NeutronUtil.getInstances(INeutronSecurityGroupAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; - int status = service.canDeleteNeutronSecurityGroup(singleton); - if ((status < 200) || (status > 299)) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityGroupAware service = (INeutronSecurityGroupAware) instance; + int status = service.canDeleteNeutronSecurityGroup(singleton); + if ((status < 200) || (status > 299)) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -354,4 +380,4 @@ public class NeutronSecurityGroupsNorthbound { } return Response.status(204).build(); } -} \ No newline at end of file +} diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java index 762317aaf8..9ce98e2b4f 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSecurityRulesNorthbound.java @@ -201,13 +201,19 @@ public class NeutronSecurityRulesNorthbound { } Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; - int status = service.canCreateNeutronSecurityRule(singleton); - if ((status < 200) || (status > 299)) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canCreateNeutronSecurityRule(singleton); + if ((status < 200) || (status > 299)) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } // add rule to cache @@ -246,13 +252,19 @@ public class NeutronSecurityRulesNorthbound { throw new BadRequestException("Security Rule UUID already exists"); } if (instances != null) { - for (Object instance : instances) { - INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; - int status = service.canCreateNeutronSecurityRule(test); - if ((status < 200) || (status > 299)) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canCreateNeutronSecurityRule(test); + if ((status < 200) || (status > 299)) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } @@ -328,13 +340,19 @@ public class NeutronSecurityRulesNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; - int status = service.canUpdateNeutronSecurityRule(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canUpdateNeutronSecurityRule(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -383,15 +401,22 @@ public class NeutronSecurityRulesNorthbound { NeutronSecurityRule singleton = securityRuleInterface.getNeutronSecurityRule(securityRuleUUID); Object[] instances = NeutronUtil.getInstances(INeutronSecurityRuleAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; - int status = service.canDeleteNeutronSecurityRule(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSecurityRuleAware service = (INeutronSecurityRuleAware) instance; + int status = service.canDeleteNeutronSecurityRule(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } + /* * remove it and return 204 status */ @@ -404,4 +429,4 @@ public class NeutronSecurityRulesNorthbound { } return Response.status(204).build(); } -} \ No newline at end of file +} diff --git a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java index 142b09f8e4..fa66501d0e 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java +++ b/opendaylight/networkconfiguration/neutron/northbound/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java @@ -219,13 +219,19 @@ public class NeutronSubnetsNorthbound { } Object[] instances = NeutronUtil.getInstances(INeutronSubnetAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSubnetAware service = (INeutronSubnetAware) instance; - int status = service.canCreateSubnet(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canCreateSubnet(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } subnetInterface.addSubnet(singleton); if (instances != null) { @@ -269,13 +275,19 @@ public class NeutronSubnetsNorthbound { throw new ResourceConflictException("IP pool overlaps with gateway"); } if (instances != null) { - for (Object instance : instances) { - INeutronSubnetAware service = (INeutronSubnetAware) instance; - int status = service.canCreateSubnet(test); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canCreateSubnet(test); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } } @@ -344,13 +356,19 @@ public class NeutronSubnetsNorthbound { Object[] instances = NeutronUtil.getInstances(INeutronSubnetAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSubnetAware service = (INeutronSubnetAware) instance; - int status = service.canUpdateSubnet(delta, original); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canUpdateSubnet(delta, original); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /* @@ -399,13 +417,19 @@ public class NeutronSubnetsNorthbound { NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID); Object[] instances = NeutronUtil.getInstances(INeutronSubnetAware.class, this); if (instances != null) { - for (Object instance : instances) { - INeutronSubnetAware service = (INeutronSubnetAware) instance; - int status = service.canDeleteSubnet(singleton); - if (status < 200 || status > 299) { - return Response.status(status).build(); + if (instances.length > 0) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canDeleteSubnet(singleton); + if (status < 200 || status > 299) { + return Response.status(status).build(); + } } + } else { + throw new ServiceUnavailableException("No providers registered. Please try again later"); } + } else { + throw new ServiceUnavailableException("Couldn't get providers list. Please try again later"); } /*