2 * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.eos.akka;
10 import static org.awaitility.Awaitility.await;
12 import akka.actor.testkit.typed.javadsl.ActorTestKit;
13 import akka.cluster.Member;
14 import akka.cluster.MemberStatus;
15 import akka.cluster.typed.Cluster;
16 import com.google.common.collect.ImmutableList;
17 import java.time.Duration;
18 import java.util.List;
19 import org.junit.After;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.opendaylight.mdsal.eos.dom.api.DOMEntity;
24 public class ThreeNodeReachabilityTest extends AbstractNativeEosTest {
25 public static final DOMEntity ENTITY_1 = new DOMEntity("test-type", "entity-1");
26 public static final DOMEntity ENTITY_2 = new DOMEntity("test-type-2", "entity-2");
28 private ClusterNode node1 = null;
29 private ClusterNode node2 = null;
30 private ClusterNode node3 = null;
33 public void setUp() throws Exception {
34 node1 = startupRemote(2550, List.of("member-1"), TWO_NODE_SEED_NODES);
35 node2 = startupRemote(2551, List.of("member-2"), TWO_NODE_SEED_NODES);
37 // need to wait until all nodes are ready
38 final Cluster cluster = Cluster.get(node2.getActorSystem());
39 await().atMost(Duration.ofSeconds(20)).until(() -> {
40 final List<Member> members = ImmutableList.copyOf(cluster.state().getMembers());
41 if (members.size() != 2) {
45 for (final Member member : members) {
46 if (!member.status().equals(MemberStatus.up())) {
56 public void tearDown() {
57 ActorTestKit.shutdown(node1.getActorSystem(), Duration.ofSeconds(20));
58 ActorTestKit.shutdown(node2.getActorSystem(), Duration.ofSeconds(20));
61 ActorTestKit.shutdown(node3.getActorSystem(), Duration.ofSeconds(20));
66 public void testNodeLateStart() throws Exception {
67 registerCandidates(node1, ENTITY_1, "member-1");
68 registerCandidates(node2, ENTITY_1, "member-2");
70 registerCandidates(node2, ENTITY_2, "member-2");
71 waitUntillOwnerPresent(node2, ENTITY_2);
72 registerCandidates(node1, ENTITY_2, "member-1");
74 final MockEntityOwnershipListener firstEntityListener1 = registerListener(node1, ENTITY_1);
75 final MockEntityOwnershipListener firstEntityListener2 = registerListener(node2, ENTITY_1);
77 verifyListenerState(firstEntityListener1, ENTITY_1, true, true, false);
78 verifyListenerState(firstEntityListener2, ENTITY_1, true, false, false);
80 final MockEntityOwnershipListener secondEntityListener1 = registerListener(node1, ENTITY_2);
81 final MockEntityOwnershipListener secondEntityListener2 = registerListener(node2, ENTITY_2);
83 verifyListenerState(secondEntityListener1, ENTITY_2, true, false, false);
84 verifyListenerState(secondEntityListener2, ENTITY_2, true, true, false);
86 unregisterCandidates(node1, ENTITY_1, "member-1");
88 verifyListenerState(firstEntityListener1, ENTITY_1, true, false, true);
89 verifyListenerState(firstEntityListener2, ENTITY_1, true, true, false);
91 unregisterCandidates(node2, ENTITY_1, "member-2");
93 verifyListenerState(firstEntityListener1, ENTITY_1, false, false, false);
94 verifyListenerState(firstEntityListener2, ENTITY_1, false, false, true);
98 final MockEntityOwnershipListener firstEntityListener3 = registerListener(node3, ENTITY_1);
99 verifyListenerState(firstEntityListener3, ENTITY_1, false, false, false);
101 final MockEntityOwnershipListener secondEntityListener3 = registerListener(node3, ENTITY_2);
102 verifyListenerState(secondEntityListener3, ENTITY_2, true, false, false);
104 registerCandidates(node3, ENTITY_1, "member-3");
105 waitUntillOwnerPresent(node3, ENTITY_1);
107 verifyListenerState(firstEntityListener1, ENTITY_1, true, false, false);
108 verifyListenerState(firstEntityListener2, ENTITY_1, true, false, false);
110 verifyListenerState(firstEntityListener3, ENTITY_1, true, true, false);
114 public void testReachabilityChangesDuringRuntime() throws Exception {
117 registerCandidates(node2, ENTITY_1, "member-2");
118 // we want singleton on node1 but owner on node2
119 waitUntillOwnerPresent(node2, ENTITY_1);
121 registerCandidates(node1, ENTITY_1, "member-1");
122 registerCandidates(node3, ENTITY_1, "member-3");
124 registerCandidates(node2, ENTITY_2, "member-2");
125 waitUntillOwnerPresent(node2, ENTITY_2);
126 registerCandidates(node1, ENTITY_2, "member-1");
128 final MockEntityOwnershipListener firstEntityListener1 = registerListener(node1, ENTITY_1);
129 final MockEntityOwnershipListener firstEntityListener2 = registerListener(node2, ENTITY_1);
130 final MockEntityOwnershipListener firstEntityListener3 = registerListener(node3, ENTITY_1);
132 verifyListenerState(firstEntityListener1, ENTITY_1, true, false, false);
133 verifyListenerState(firstEntityListener2, ENTITY_1, true, true, false);
134 verifyListenerState(firstEntityListener3, ENTITY_1, true, false, false);
136 final MockEntityOwnershipListener secondEntityListener1 = registerListener(node1, ENTITY_2);
137 final MockEntityOwnershipListener secondEntityListener2 = registerListener(node2, ENTITY_2);
138 final MockEntityOwnershipListener secondEntityListener3 = registerListener(node3, ENTITY_2);
140 verifyListenerState(secondEntityListener1, ENTITY_2, true, false, false);
141 verifyListenerState(secondEntityListener2, ENTITY_2, true, true, false);
142 verifyListenerState(secondEntityListener3, ENTITY_2, true, false, false);
144 unreachableMember(node1, "member-2", DEFAULT_DATACENTER);
146 verifyListenerState(firstEntityListener1, ENTITY_1, true, true, false);
147 verifyListenerState(firstEntityListener2, ENTITY_1, true, false, true);
148 verifyListenerState(firstEntityListener3, ENTITY_1, true, false, false);
150 verifyListenerState(secondEntityListener1, ENTITY_2, true, true, false);
151 verifyListenerState(secondEntityListener2, ENTITY_2, true, false, true);
152 verifyListenerState(secondEntityListener3, ENTITY_2, true, false, false);
154 unreachableMember(node1, "member-3", DEFAULT_DATACENTER);
156 verifyListenerState(firstEntityListener1, ENTITY_1, true, true, false);
157 verifyListenerState(firstEntityListener2, ENTITY_1, true, false, true);
158 verifyListenerState(firstEntityListener3, ENTITY_1, true, false, false);
160 unregisterCandidates(node1, ENTITY_1, "member-1", DEFAULT_DATACENTER);
161 unregisterCandidates(node1, ENTITY_2, "member-1", DEFAULT_DATACENTER);
163 verifyListenerState(firstEntityListener1, ENTITY_1, false, false, true);
164 verifyListenerState(firstEntityListener2, ENTITY_1, false, false, false);
165 verifyListenerState(firstEntityListener3, ENTITY_1, false, false, false);
167 verifyListenerState(secondEntityListener1, ENTITY_2, false, false, true);
168 verifyListenerState(secondEntityListener2, ENTITY_2, false, false, false);
169 verifyListenerState(secondEntityListener3, ENTITY_2, false, false, false);
171 reachableMember(node1, "member-2", DEFAULT_DATACENTER);
172 verifyListenerState(firstEntityListener1, ENTITY_1, true, false, false);
173 verifyListenerState(firstEntityListener2, ENTITY_1, true, true, false);
174 verifyListenerState(firstEntityListener3, ENTITY_1, true, false, false);
178 public void testSingletonMoving() throws Exception {
179 final MockEntityOwnershipListener listener1 = registerListener(node2, ENTITY_1);
180 final MockEntityOwnershipListener listener2 = registerListener(node2, ENTITY_2);
181 verifyNoNotifications(listener1);
182 verifyNoNotifications(listener2);
184 registerCandidates(node1, ENTITY_1, "member-1");
185 registerCandidates(node2, ENTITY_1, "member-2");
187 registerCandidates(node2, ENTITY_2, "member-2");
188 waitUntillOwnerPresent(node2, ENTITY_2);
189 registerCandidates(node1, ENTITY_2, "member-1");
190 // end up with node1 - member-1, node2 - member-2 owners
191 verifyListenerState(listener1, ENTITY_1, true, false, false);
192 verifyListenerState(listener2, ENTITY_2, true, true, false);
194 ActorTestKit.shutdown(node1.getActorSystem(), Duration.ofSeconds(20));
196 verifyListenerState(listener1, ENTITY_1, true, true, false);
197 verifyListenerState(listener2, ENTITY_2, true, true, false);
201 final MockEntityOwnershipListener listener3 = registerListener(node3, ENTITY_2);
202 verifyListenerState(listener3, ENTITY_2, true, false, false);
204 node1 = startupRemote(2550, List.of("member-1"));
206 final Cluster cluster = Cluster.get(node2.getActorSystem());
207 await().atMost(Duration.ofSeconds(20)).until(() -> {
208 final List<Member> members = ImmutableList.copyOf(cluster.state().getMembers());
209 if (members.size() != 3) {
213 for (final Member member : members) {
214 if (!member.status().equals(MemberStatus.up())) {
222 final MockEntityOwnershipListener node1Listener = registerListener(node1, ENTITY_1);
223 verifyListenerState(node1Listener, ENTITY_1, true, false, false);
227 public void testOwnerNotReassignedWhenOnlyCandidate() throws Exception {
229 final MockEntityOwnershipListener listener1 = registerListener(node1, ENTITY_1);
230 final MockEntityOwnershipListener listener2 = registerListener(node2, ENTITY_1);
231 verifyNoNotifications(listener1);
232 verifyNoNotifications(listener2);
234 registerCandidates(node3, ENTITY_1, "member-3");
235 waitUntillOwnerPresent(node1, ENTITY_1);
237 MockEntityOwnershipListener listener3 = registerListener(node3, ENTITY_1);
238 verifyListenerState(listener1, ENTITY_1, true, false, false);
239 verifyListenerState(listener3, ENTITY_1, true, true, false);
241 ActorTestKit.shutdown(node3.getActorSystem(), Duration.ofSeconds(20));
243 verifyListenerState(listener1, ENTITY_1, true, false, false);
244 verifyListenerState(listener2, ENTITY_1, true, false, false);
247 verifyListenerState(listener1, ENTITY_1, false, false, false);
249 listener3 = registerListener(node3, ENTITY_1);
250 verifyListenerState(listener3, ENTITY_1, false, false, false);
252 registerCandidates(node1, ENTITY_1, "member-1");
254 verifyListenerState(listener1, ENTITY_1, true, true, false);
255 verifyListenerState(listener3, ENTITY_1, true, false, false);
259 private void startNode3() throws Exception {
263 private void startNode3(final int membersPresent) throws Exception {
264 node3 = startupRemote(2552, List.of("member-3"), THREE_NODE_SEED_NODES);
266 // need to wait until all nodes are ready
267 final Cluster cluster = Cluster.get(node2.getActorSystem());
268 await().atMost(Duration.ofSeconds(30)).until(() -> {
269 final List<Member> members = ImmutableList.copyOf(cluster.state().getMembers());
270 if (members.size() != membersPresent) {
274 for (final Member member : members) {
275 if (!member.status().equals(MemberStatus.up())) {