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