blob: 36ffda93371bee1eaa86cdecb45364525deb19e0 [file] [log] [blame]
Yi Tsengf4e13e32017-03-30 15:38:39 -07001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.vpls;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.Sets;
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
25import org.onosproject.cluster.ClusterServiceAdapter;
26import org.onosproject.cluster.Leader;
27import org.onosproject.cluster.Leadership;
28import org.onosproject.cluster.LeadershipEvent;
29import org.onosproject.net.ConnectPoint;
30import org.onosproject.net.EncapsulationType;
31import org.onosproject.net.Host;
32import org.onosproject.net.host.HostServiceAdapter;
33import org.onosproject.net.intent.Intent;
34import org.onosproject.net.intent.IntentData;
35import org.onosproject.net.intent.IntentEvent;
36import org.onosproject.net.intent.IntentState;
37import org.onosproject.store.service.WallClockTimestamp;
38import org.onosproject.vpls.api.VplsData;
39import org.onosproject.vpls.api.VplsOperation;
40
41import java.util.ArrayDeque;
42import java.util.Collection;
43import java.util.Deque;
44import java.util.Set;
45
46import static org.junit.Assert.*;
47import static org.onlab.junit.TestTools.assertAfter;
48import static org.onlab.junit.TestTools.delay;
49
50/**
51 * Tests for {@link VplsOperationManager}.
52 */
53public class VplsOperationManagerTest extends VplsTest {
54
55 VplsOperationManager vplsOperationManager;
56 private static final int OPERATION_DELAY = 1000;
57 private static final int OPERATION_DURATION = 1500;
58
59 @Before
60 public void setup() {
61 if (idGenerator == null) {
62 idGenerator = new TestIdGenerator();
63 }
64 Intent.unbindIdGenerator(idGenerator);
65 Intent.bindIdGenerator(idGenerator);
66 vplsOperationManager = new VplsOperationManager();
67 vplsOperationManager.coreService = new TestCoreService();
68 vplsOperationManager.intentService = new TestIntentService();
69 vplsOperationManager.leadershipService = new TestLeadershipService();
70 vplsOperationManager.clusterService = new ClusterServiceAdapter();
71 vplsOperationManager.hostService = new TestHostService();
72 vplsOperationManager.vplsStore = new TestVplsStore();
73 vplsOperationManager.isLeader = true;
74 vplsOperationManager.activate();
75 }
76
77 @After
78 public void tearDown() {
79 vplsOperationManager.deactivate();
80 }
81
82 /**
83 * Sends leadership event to the manager and checks if the manager is
84 * leader or not.
85 */
86 @Test
87 public void testLeadershipEvent() {
88 vplsOperationManager.isLeader = false;
89 vplsOperationManager.localNodeId = NODE_ID_1;
90
91 // leader changed to self
92 Leader leader = new Leader(NODE_ID_1, 0, 0);
93 Leadership leadership = new Leadership(APP_NAME, leader, ImmutableList.of());
94 LeadershipEvent event = new LeadershipEvent(LeadershipEvent.Type.LEADER_CHANGED, leadership);
95 ((TestLeadershipService) vplsOperationManager.leadershipService).sendEvent(event);
96 assertTrue(vplsOperationManager.isLeader);
97
98 // leader changed to other
99 leader = new Leader(NODE_ID_2, 0, 0);
100 leadership = new Leadership(APP_NAME, leader, ImmutableList.of());
101 event = new LeadershipEvent(LeadershipEvent.Type.LEADER_CHANGED, leadership);
102 ((TestLeadershipService) vplsOperationManager.leadershipService).sendEvent(event);
103 assertFalse(vplsOperationManager.isLeader);
104 }
105
106 /**
107 * Submits an ADD operation to the operation manager; check if the VPLS
108 * store changed after a period.
109 */
110 @Test
111 public void testSubmitAddOperation() {
112 VplsData vplsData = VplsData.of(VPLS1);
113 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
114
115 VplsOperation vplsOperation = VplsOperation.of(vplsData,
116 VplsOperation.Operation.ADD);
117
118 vplsOperationManager.submit(vplsOperation);
119 assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
120 Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
121 assertEquals(1, vplss.size());
122 VplsData result = vplss.iterator().next();
123
124 assertEquals(vplsData, result);
125 assertEquals(VplsData.VplsState.ADDED, result.state());
126
127 Set<Intent> intentsInstalled =
128 Sets.newHashSet(vplsOperationManager.intentService.getIntents());
129 assertEquals(4, intentsInstalled.size());
130 });
131 }
132
133 /**
134 * Submits an ADD operation to the operation manager; check the VPLS state
135 * from store if Intent install failed.
136 */
137 @Test
138 public void testSubmitAddOperationFail() {
139 vplsOperationManager.intentService = new AlwaysFailureIntentService();
140 VplsData vplsData = VplsData.of(VPLS1);
141 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
142
143 VplsOperation vplsOperation = VplsOperation.of(vplsData,
144 VplsOperation.Operation.ADD);
145 vplsOperationManager.submit(vplsOperation);
146 assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
147 Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
148 assertEquals(1, vplss.size());
149 VplsData result = vplss.iterator().next();
150
151 assertEquals(vplsData, result);
152 assertEquals(VplsData.VplsState.FAILED, result.state());
153 });
154 }
155
156 /**
157 * Submits an REMOVE operation to the operation manager; check if the VPLS
158 * store changed after a period.
159 */
160 @Test
161 public void testSubmitRemoveOperation() {
162 VplsData vplsData = VplsData.of(VPLS1);
163 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
164 vplsData.state(VplsData.VplsState.REMOVING);
165
166 VplsOperation vplsOperation = VplsOperation.of(vplsData,
167 VplsOperation.Operation.REMOVE);
168
169 vplsOperationManager.submit(vplsOperation);
170
171 assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
172 Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
173 assertEquals(0, vplss.size());
174 });
175 }
176
177 /**
178 * Submits an UPDATE operation with VPLS interface update to the operation manager; check if the VPLS
179 * store changed after a period.
180 */
181 @Test
182 public void testSubmitUpdateOperation() {
183 VplsData vplsData = VplsData.of(VPLS1);
184 vplsData.addInterfaces(ImmutableSet.of(V100H1));
185 vplsData.state(VplsData.VplsState.ADDED);
186 vplsOperationManager.vplsStore.addVpls(vplsData);
187
188 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
189 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
190 vplsData.state(VplsData.VplsState.UPDATING);
191
192 VplsOperation vplsOperation = VplsOperation.of(vplsData,
193 VplsOperation.Operation.UPDATE);
194
195 vplsOperationManager.submit(vplsOperation);
196
197 assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
198 Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
199 VplsData result = vplss.iterator().next();
200 VplsData expected = VplsData.of(VPLS1, EncapsulationType.VLAN);
201 expected.addInterfaces(ImmutableSet.of(V100H1, V100H2));
202 expected.state(VplsData.VplsState.ADDED);
203
204 assertEquals(1, vplss.size());
205 assertEquals(expected, result);
206
207 Set<Intent> intentsInstalled =
208 Sets.newHashSet(vplsOperationManager.intentService.getIntents());
209 assertEquals(4, intentsInstalled.size());
210 });
211 }
212
213 /**
214 * Submits an UPDATE operation with VPLS host update to the operation manager; check if the VPLS
215 * store changed after a period.
216 */
217 @Test
218 public void testSubmitUpdateHostOperation() {
219 vplsOperationManager.hostService = new EmptyHostService();
220 VplsData vplsData = VplsData.of(VPLS1);
221 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
222
223 VplsOperation vplsOperation = VplsOperation.of(vplsData,
224 VplsOperation.Operation.ADD);
225 vplsOperationManager.submit(vplsOperation);
226 delay(1000);
227 vplsOperationManager.hostService = new TestHostService();
228
229 vplsData = VplsData.of(VPLS1);
230 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
231 vplsData.state(VplsData.VplsState.UPDATING);
232
233 vplsOperation = VplsOperation.of(vplsData,
234 VplsOperation.Operation.UPDATE);
235
236 vplsOperationManager.submit(vplsOperation);
237
238 assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
239 Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
240 VplsData result = vplss.iterator().next();
241 VplsData expected = VplsData.of(VPLS1);
242 expected.addInterfaces(ImmutableSet.of(V100H1, V100H2));
243 expected.state(VplsData.VplsState.ADDED);
244 assertEquals(1, vplss.size());
245 assertEquals(expected, result);
246
247 assertEquals(4, vplsOperationManager.intentService.getIntentCount());
248 });
249 }
250
251 /**
252 * Submits same operation twice to the manager; the manager should ignore
253 * duplicated operation.
254 */
255 @Test
256 public void testDuplicateOperationInQueue() {
257 VplsData vplsData = VplsData.of(VPLS1);
258 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
259
260 VplsOperation vplsOperation = VplsOperation.of(vplsData,
261 VplsOperation.Operation.ADD);
262
263 vplsOperationManager.submit(vplsOperation);
264 vplsOperationManager.submit(vplsOperation);
265 Deque<VplsOperation> opQueue = vplsOperationManager.pendingVplsOperations.get(VPLS1);
266 assertEquals(1, opQueue.size());
267
268 // Clear operation queue before scheduler process it
269 opQueue.clear();
270 }
271
272 /**
273 * Submits REMOVE operation after submits ADD operation; there should be no
274 * pending or running operation in the manager.
275 */
276 @Test
277 public void testDoNothingOperation() {
278 VplsData vplsData = VplsData.of(VPLS1);
279 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
280
281 VplsOperation vplsOperation = VplsOperation.of(vplsData,
282 VplsOperation.Operation.ADD);
283 vplsOperationManager.submit(vplsOperation);
284 vplsOperation = VplsOperation.of(vplsData,
285 VplsOperation.Operation.REMOVE);
286 vplsOperationManager.submit(vplsOperation);
287 assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
288 assertEquals(0, vplsOperationManager.pendingVplsOperations.size());
289
290 // Should not have any running operation
291 assertEquals(0, vplsOperationManager.runningOperations.size());
292 });
293 }
294
295 /**
296 * Optimize operations which don't need to be optimized.
297 */
298 @Test
299 public void testOptimizeOperationsNoOptimize() {
300 // empty queue
301 Deque<VplsOperation> operations = new ArrayDeque<>();
302 VplsOperation vplsOperation =
303 VplsOperationManager.getOptimizedVplsOperation(operations);
304 assertNull(vplsOperation);
305
306 // one operation
307 VplsData vplsData = VplsData.of(VPLS1);
308 vplsOperation = VplsOperation.of(vplsData, VplsOperation.Operation.ADD);
309 operations.add(vplsOperation);
310 VplsOperation result =
311 VplsOperationManager.getOptimizedVplsOperation(operations);
312 assertEquals(vplsOperation, result);
313
314 }
315
316 /**
317 * Optimize operations with first is ADD operation and last is also ADD
318 * operation.
319 */
320 @Test
321 public void testOptimizeOperationsAToA() {
322 Deque<VplsOperation> operations = new ArrayDeque<>();
323 VplsData vplsData = VplsData.of(VPLS1);
324 vplsData.addInterfaces(ImmutableSet.of(V100H1));
325 VplsOperation vplsOperation = VplsOperation.of(vplsData,
326 VplsOperation.Operation.ADD);
327 operations.add(vplsOperation);
328 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
329 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
330 vplsOperation = VplsOperation.of(vplsData,
331 VplsOperation.Operation.ADD);
332 operations.add(vplsOperation);
333 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
334 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.ADD), vplsOperation);
335 }
336
337 /**
338 * Optimize operations with first is ADD operation and last is REMOVE
339 * operation.
340 */
341 @Test
342 public void testOptimizeOperationsAToR() {
343 Deque<VplsOperation> operations = new ArrayDeque<>();
344 VplsData vplsData = VplsData.of(VPLS1);
345 vplsData.addInterfaces(ImmutableSet.of(V100H1));
346 VplsOperation vplsOperation = VplsOperation.of(vplsData,
347 VplsOperation.Operation.ADD);
348 operations.add(vplsOperation);
349 vplsOperation = VplsOperation.of(vplsData,
350 VplsOperation.Operation.REMOVE);
351 operations.add(vplsOperation);
352 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
353 assertNull(vplsOperation);
354 }
355
356 /**
357 * Optimize operations with first is ADD operation and last is UPDATE
358 * operation.
359 */
360 @Test
361 public void testOptimizeOperationsAToU() {
362 Deque<VplsOperation> operations = new ArrayDeque<>();
363 VplsData vplsData = VplsData.of(VPLS1);
364 vplsData.addInterfaces(ImmutableSet.of(V100H1));
365 VplsOperation vplsOperation = VplsOperation.of(vplsData,
366 VplsOperation.Operation.ADD);
367 operations.add(vplsOperation);
368 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
369 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
370 vplsOperation = VplsOperation.of(vplsData,
371 VplsOperation.Operation.UPDATE);
372 operations.add(vplsOperation);
373 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
374 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.ADD), vplsOperation);
375 }
376
377 /**
378 * Optimize operations with first is REMOVE operation and last is ADD
379 * operation.
380 */
381 @Test
382 public void testOptimizeOperationsRToA() {
383 Deque<VplsOperation> operations = new ArrayDeque<>();
384 VplsData vplsData = VplsData.of(VPLS1);
385 vplsData.addInterfaces(ImmutableSet.of(V100H1));
386 VplsOperation vplsOperation = VplsOperation.of(vplsData,
387 VplsOperation.Operation.REMOVE);
388 operations.add(vplsOperation);
389 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
390 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
391 vplsOperation = VplsOperation.of(vplsData,
392 VplsOperation.Operation.ADD);
393 operations.add(vplsOperation);
394 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
395 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
396 }
397
398 /**
399 * Optimize operations with first is REMOVE operation and last is also
400 * REMOVE operation.
401 */
402 @Test
403 public void testOptimizeOperationsRToR() {
404 Deque<VplsOperation> operations = new ArrayDeque<>();
405 VplsData vplsData = VplsData.of(VPLS1);
406 vplsData.addInterfaces(ImmutableSet.of(V100H1));
407 VplsOperation vplsOperation = VplsOperation.of(vplsData,
408 VplsOperation.Operation.REMOVE);
409 operations.add(vplsOperation);
410 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
411 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
412 vplsOperation = VplsOperation.of(vplsData,
413 VplsOperation.Operation.REMOVE);
414 operations.add(vplsOperation);
415 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
416 vplsData = VplsData.of(VPLS1);
417 vplsData.addInterfaces(ImmutableSet.of(V100H1));
418 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.REMOVE), vplsOperation);
419 }
420
421 /**
422 * Optimize operations with first is REMOVE operation and last is UPDATE
423 * operation.
424 */
425 @Test
426 public void testOptimizeOperationsRToU() {
427 Deque<VplsOperation> operations = new ArrayDeque<>();
428 VplsData vplsData = VplsData.of(VPLS1);
429 vplsData.addInterfaces(ImmutableSet.of(V100H1));
430 VplsOperation vplsOperation = VplsOperation.of(vplsData,
431 VplsOperation.Operation.REMOVE);
432 operations.add(vplsOperation);
433 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
434 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
435 vplsOperation = VplsOperation.of(vplsData,
436 VplsOperation.Operation.UPDATE);
437 operations.add(vplsOperation);
438 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
439 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
440 }
441
442 /**
443 * Optimize operations with first is UPDATE operation and last is ADD
444 * operation.
445 */
446 @Test
447 public void testOptimizeOperationsUToA() {
448 Deque<VplsOperation> operations = new ArrayDeque<>();
449 VplsData vplsData = VplsData.of(VPLS1);
450 vplsData.addInterfaces(ImmutableSet.of(V100H1));
451 VplsOperation vplsOperation = VplsOperation.of(vplsData,
452 VplsOperation.Operation.UPDATE);
453 operations.add(vplsOperation);
454 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
455 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
456 vplsOperation = VplsOperation.of(vplsData,
457 VplsOperation.Operation.ADD);
458 operations.add(vplsOperation);
459 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
460 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
461 }
462
463 /**
464 * Optimize operations with first is UPDATE operation and last is REMOVE
465 * operation.
466 */
467 @Test
468 public void testOptimizeOperationsUToR() {
469 Deque<VplsOperation> operations = new ArrayDeque<>();
470 VplsData vplsData = VplsData.of(VPLS1);
471 vplsData.addInterfaces(ImmutableSet.of(V100H1));
472 VplsOperation vplsOperation = VplsOperation.of(vplsData,
473 VplsOperation.Operation.UPDATE);
474 operations.add(vplsOperation);
475 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
476 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
477 vplsOperation = VplsOperation.of(vplsData,
478 VplsOperation.Operation.REMOVE);
479 operations.add(vplsOperation);
480 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
481 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.REMOVE), vplsOperation);
482 }
483
484 /**
485 * Optimize operations with first is UPDATE operation and last is also
486 * UPDATE operation.
487 */
488 @Test
489 public void testOptimizeOperationsUToU() {
490 Deque<VplsOperation> operations = new ArrayDeque<>();
491 VplsData vplsData = VplsData.of(VPLS1);
492 vplsData.addInterfaces(ImmutableSet.of(V100H1));
493 VplsOperation vplsOperation = VplsOperation.of(vplsData,
494 VplsOperation.Operation.UPDATE);
495 operations.add(vplsOperation);
496 vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
497 vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
498 vplsOperation = VplsOperation.of(vplsData,
499 VplsOperation.Operation.UPDATE);
500 operations.add(vplsOperation);
501 vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
502 assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
503 }
504
505 /**
506 * Test Intent service which always fail when submit or withdraw Intents.
507 */
508 class AlwaysFailureIntentService extends TestIntentService {
509 @Override
510 public void submit(Intent intent) {
511 intents.add(new IntentData(intent, IntentState.FAILED, new WallClockTimestamp()));
512 if (listener != null) {
513 IntentEvent event = IntentEvent.getEvent(IntentState.FAILED, intent).get();
514 listener.event(event);
515 }
516 }
517
518 @Override
519 public void withdraw(Intent intent) {
520 intents.forEach(intentData -> {
521 if (intentData.intent().key().equals(intent.key())) {
522 intentData.setState(IntentState.FAILED);
523
524 if (listener != null) {
525 IntentEvent event = IntentEvent.getEvent(IntentState.FAILED, intent).get();
526 listener.event(event);
527 }
528 }
529 });
530 }
531 }
532
533 /**
534 * Test host service without any hosts.
535 */
536 class EmptyHostService extends HostServiceAdapter {
537 @Override
538 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
539 return ImmutableSet.of();
540 }
541 }
542
543}