blob: 5e2d06cb9f8c6da621f43cc199e2f3369fc52bfe [file] [log] [blame]
Brian Stanke11f6d532016-07-05 16:17:59 -04001/*
2 * Copyright 2016-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.incubator.net.virtual.impl;
18
19import com.google.common.collect.Iterators;
20import com.google.common.collect.Lists;
21import org.junit.After;
22import org.junit.Before;
23import org.junit.Test;
24import org.onlab.junit.TestUtils;
25import org.onlab.osgi.ServiceDirectory;
26import org.onlab.osgi.TestServiceDirectory;
27import org.onlab.rest.BaseResource;
28import org.onosproject.TestApplicationId;
29import org.onosproject.common.event.impl.TestEventDispatcher;
30import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
32import org.onosproject.core.CoreServiceAdapter;
33import org.onosproject.core.IdGenerator;
34import org.onosproject.incubator.net.virtual.TenantId;
35import org.onosproject.incubator.net.virtual.VirtualDevice;
36import org.onosproject.incubator.net.virtual.VirtualLink;
37import org.onosproject.incubator.net.virtual.VirtualNetwork;
38import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
39import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
40import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
41import org.onosproject.net.ConnectPoint;
42import org.onosproject.net.DefaultPort;
43import org.onosproject.net.EncapsulationType;
44import org.onosproject.net.Link;
45import org.onosproject.net.NetTestTools;
46import org.onosproject.net.Port;
47import org.onosproject.net.PortNumber;
48import org.onosproject.net.TestDeviceParams;
49import org.onosproject.net.intent.Constraint;
50import org.onosproject.net.intent.FakeIntentManager;
51import org.onosproject.net.intent.FlowRuleIntent;
52import org.onosproject.net.intent.Intent;
53import org.onosproject.net.intent.IntentCompiler;
54import org.onosproject.net.intent.IntentEvent;
55import org.onosproject.net.intent.IntentExtensionService;
56import org.onosproject.net.intent.IntentListener;
57import org.onosproject.net.intent.IntentPartitionService;
58import org.onosproject.net.intent.IntentPartitionServiceAdapter;
59import org.onosproject.net.intent.IntentService;
60import org.onosproject.net.intent.IntentState;
61import org.onosproject.net.intent.IntentTestsMocks;
62import org.onosproject.net.intent.Key;
63import org.onosproject.net.intent.MockIdGenerator;
64import org.onosproject.net.intent.TestableIntentService;
65import org.onosproject.net.intent.constraint.EncapsulationConstraint;
66import org.onosproject.store.service.TestStorageService;
67
68import java.util.ArrayList;
69import java.util.Collections;
70import java.util.List;
71import java.util.concurrent.Semaphore;
72import java.util.concurrent.TimeUnit;
73import java.util.concurrent.atomic.AtomicLong;
74
75import static org.junit.Assert.*;
76
77/**
78 * Junit tests for VirtualNetworkIntentService.
79 */
80public class VirtualNetworkIntentServiceTest extends TestDeviceParams {
81
82 private final String tenantIdValue1 = "TENANT_ID1";
83 private static final ApplicationId APP_ID =
Brian Stanke682c19e2016-08-02 09:41:40 -040084 new TestApplicationId("MyAppId");
Brian Stanke11f6d532016-07-05 16:17:59 -040085
86 private ConnectPoint cp1;
87 private ConnectPoint cp2;
88 private ConnectPoint cp3;
89 private ConnectPoint cp4;
90 private ConnectPoint cp5;
91 private ConnectPoint cp6;
92 private VirtualLink link1;
93 private VirtualLink link2;
94 private VirtualLink link3;
95 private VirtualLink link4;
96 private VirtualLink link5;
97 private VirtualLink link6;
98
99 private VirtualNetworkManager manager;
100 private static DistributedVirtualNetworkStore virtualNetworkManagerStore;
101 private CoreService coreService;
102 private TestableIntentService intentService = new FakeIntentManager();
103 private VirtualNetworkIntentService vnetIntentService;
104 private TestIntentCompiler compiler = new TestIntentCompiler();
105 private IntentExtensionService intentExtensionService;
106 private IntentPartitionService intentPartitionService;
107 private ServiceDirectory testDirectory;
108 private TestListener listener = new TestListener();
109 private IdGenerator idGenerator = new MockIdGenerator();
110 private static final int MAX_WAIT_TIME = 5;
111 private static final int MAX_PERMITS = 1;
112 private static Semaphore created;
113 private static Semaphore withdrawn;
114 private static Semaphore purged;
115
116 @Before
117 public void setUp() throws Exception {
118 virtualNetworkManagerStore = new DistributedVirtualNetworkStore();
119
120 coreService = new VirtualNetworkIntentServiceTest.TestCoreService();
121
122 Intent.unbindIdGenerator(idGenerator);
123 Intent.bindIdGenerator(idGenerator);
124
125 virtualNetworkManagerStore.setCoreService(coreService);
126 TestUtils.setField(coreService, "coreService", new VirtualNetworkIntentServiceTest.TestCoreService());
127 TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
128 virtualNetworkManagerStore.activate();
129
130 manager = new VirtualNetworkManager();
131 manager.store = virtualNetworkManagerStore;
132 NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());
133 manager.intentService = intentService;
134 manager.activate();
135 intentService.addListener(listener);
136
137 // Register a compiler and an installer both setup for success.
138 intentExtensionService = intentService;
139 intentExtensionService.registerCompiler(VirtualNetworkIntent.class, compiler);
140
141 created = new Semaphore(0, true);
142 withdrawn = new Semaphore(0, true);
143 purged = new Semaphore(0, true);
144
145 intentPartitionService = new IntentPartitionServiceAdapter();
146 testDirectory = new TestServiceDirectory()
147 .add(VirtualNetworkStore.class, virtualNetworkManagerStore)
148 .add(IntentService.class, intentService)
149 .add(IntentPartitionService.class, intentPartitionService);
150 BaseResource.setServiceDirectory(testDirectory);
151 }
152
153 @After
154 public void tearDown() {
155 virtualNetworkManagerStore.deactivate();
156 manager.deactivate();
157 NetTestTools.injectEventDispatcher(manager, null);
158 Intent.unbindIdGenerator(idGenerator);
159 intentService.removeListener(listener);
160 created = null;
161 withdrawn = null;
162 purged = null;
163 }
164
165 /**
166 * Method to create the virtual network for further testing.
167 *
168 * @return virtual network
169 */
170 private VirtualNetwork setupVirtualNetworkTopology() {
171 manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
172 VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
173 VirtualDevice virtualDevice1 =
174 manager.createVirtualDevice(virtualNetwork.id(), DID1);
175 VirtualDevice virtualDevice2 =
176 manager.createVirtualDevice(virtualNetwork.id(), DID2);
177 VirtualDevice virtualDevice3 =
178 manager.createVirtualDevice(virtualNetwork.id(), DID3);
179 VirtualDevice virtualDevice4 =
180 manager.createVirtualDevice(virtualNetwork.id(), DID4);
181
182 Port port1 = new DefaultPort(virtualDevice1, PortNumber.portNumber(1), true);
183 manager.createVirtualPort(virtualNetwork.id(), virtualDevice1.id(), port1.number(), port1);
184 cp1 = new ConnectPoint(virtualDevice1.id(), port1.number());
185
186 Port port2 = new DefaultPort(virtualDevice1, PortNumber.portNumber(2), true);
187 manager.createVirtualPort(virtualNetwork.id(), virtualDevice1.id(), port2.number(), port2);
188 cp2 = new ConnectPoint(virtualDevice1.id(), port2.number());
189
190 Port port3 = new DefaultPort(virtualDevice2, PortNumber.portNumber(3), true);
191 manager.createVirtualPort(virtualNetwork.id(), virtualDevice2.id(), port3.number(), port3);
192 cp3 = new ConnectPoint(virtualDevice2.id(), port3.number());
193
194 Port port4 = new DefaultPort(virtualDevice2, PortNumber.portNumber(4), true);
195 manager.createVirtualPort(virtualNetwork.id(), virtualDevice2.id(), port4.number(), port4);
196 cp4 = new ConnectPoint(virtualDevice2.id(), port4.number());
197
198 Port port5 = new DefaultPort(virtualDevice3, PortNumber.portNumber(5), true);
199 manager.createVirtualPort(virtualNetwork.id(), virtualDevice3.id(), port5.number(), port5);
200 cp5 = new ConnectPoint(virtualDevice3.id(), port5.number());
201
202 Port port6 = new DefaultPort(virtualDevice3, PortNumber.portNumber(6), true);
203 manager.createVirtualPort(virtualNetwork.id(), virtualDevice3.id(), port6.number(), port6);
204 cp6 = new ConnectPoint(virtualDevice3.id(), port6.number());
205
206 link1 = manager.createVirtualLink(virtualNetwork.id(), cp1, cp3);
207 virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE);
208 link2 = manager.createVirtualLink(virtualNetwork.id(), cp3, cp1);
209 virtualNetworkManagerStore.updateLink(link2, link2.tunnelId(), Link.State.ACTIVE);
210 link3 = manager.createVirtualLink(virtualNetwork.id(), cp4, cp5);
211 virtualNetworkManagerStore.updateLink(link3, link3.tunnelId(), Link.State.ACTIVE);
212 link4 = manager.createVirtualLink(virtualNetwork.id(), cp5, cp4);
213 virtualNetworkManagerStore.updateLink(link4, link4.tunnelId(), Link.State.ACTIVE);
214
215 vnetIntentService = new VirtualNetworkIntentService(manager, virtualNetwork, testDirectory);
216 vnetIntentService.intentService = intentService;
217 vnetIntentService.store = virtualNetworkManagerStore;
218 vnetIntentService.partitionService = intentPartitionService;
219 return virtualNetwork;
220 }
221
222 /**
223 * Tests the submit(), withdraw(), and purge() methods.
224 */
225 @Test
226 public void testCreateAndRemoveIntent() {
227 VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();
228
229 Key intentKey = Key.of("test", APP_ID);
230
231 List<Constraint> constraints = new ArrayList<>();
232 constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
233
234 VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder()
235 .networkId(virtualNetwork.id())
236 .key(intentKey)
237 .appId(APP_ID)
238 .ingressPoint(cp1)
239 .egressPoint(cp5)
240 .constraints(constraints)
241 .build();
242 // Test the submit() method.
243 vnetIntentService.submit(virtualIntent);
244
245 // Wait for the both intents to go into an INSTALLED state.
246 try {
247 if (!created.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
248 fail("Failed to wait for intent to get installed.");
249 }
250 } catch (InterruptedException e) {
251 fail("Semaphore exception during intent installation." + e.getMessage());
252 }
253
254 // Test the getIntentState() method
255 assertEquals("The intent state did not match as expected.", IntentState.INSTALLED,
256 vnetIntentService.getIntentState(virtualIntent.key()));
257
258 // Test the withdraw() method.
259 vnetIntentService.withdraw(virtualIntent);
260 // Wait for the both intents to go into a WITHDRAWN state.
261 try {
262 if (!withdrawn.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
263 fail("Failed to wait for intent to get withdrawn.");
264 }
265 } catch (InterruptedException e) {
266 fail("Semaphore exception during intent withdrawal." + e.getMessage());
267 }
268
269 // Test the getIntentState() method
270 assertEquals("The intent state did not match as expected.", IntentState.WITHDRAWN,
271 vnetIntentService.getIntentState(virtualIntent.key()));
272
273 // Test the purge() method.
274 vnetIntentService.purge(virtualIntent);
275 // Wait for the both intents to be removed/purged.
276 try {
277 if (!purged.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
278 fail("Failed to wait for intent to get purged.");
279 }
280 } catch (InterruptedException e) {
281 fail("Semaphore exception during intent purging." + e.getMessage());
282 }
283
284 }
285
286 /**
287 * Tests the getIntents, getIntent(), getIntentData(), getIntentCount(),
288 * isLocal() methods.
289 */
290 @Test
291 public void testGetIntents() {
292 VirtualNetwork virtualNetwork = setupVirtualNetworkTopology();
293
294 Key intentKey = Key.of("test", APP_ID);
295
296 List<Constraint> constraints = new ArrayList<>();
297 constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
298
299 VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder()
300 .networkId(virtualNetwork.id())
301 .key(intentKey)
302 .appId(APP_ID)
303 .ingressPoint(cp1)
304 .egressPoint(cp5)
305 .constraints(constraints)
306 .build();
307 // Test the submit() method.
308 vnetIntentService.submit(virtualIntent);
309
310 // Wait for the both intents to go into an INSTALLED state.
311 try {
312 if (!created.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
313 fail("Failed to wait for intent to get installed.");
314 }
315 } catch (InterruptedException e) {
316 fail("Semaphore exception during intent installation." + e.getMessage());
317 }
318
319 // Test the getIntents() method
320 assertEquals("The intents size did not match as expected.", 1,
321 Iterators.size(vnetIntentService.getIntents().iterator()));
322
323 // Test the getIntent() method
324 assertNotNull("The intent should have been found.", vnetIntentService.getIntent(virtualIntent.key()));
325
326 // Test the getIntentData() method
327 assertEquals("The intent data size did not match as expected.", 1,
328 Iterators.size(vnetIntentService.getIntentData().iterator()));
329
330 // Test the getIntentCount() method
331 assertEquals("The intent count did not match as expected.", 1,
332 vnetIntentService.getIntentCount());
333
334 // Test the isLocal() method
335 assertTrue("The intent should be local.", vnetIntentService.isLocal(virtualIntent.key()));
336
337 }
338
339 /**
340 * Test listener to listen for intent events.
341 */
342 private static class TestListener implements IntentListener {
343
344 @Override
345 public void event(IntentEvent event) {
346 switch (event.type()) {
347 case INSTALLED:
348 // Release one permit on the created semaphore since the Intent event was received.
349 virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.INSTALLED);
350 created.release();
351 break;
352 case WITHDRAWN:
353 // Release one permit on the removed semaphore since the Intent event was received.
354 virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.WITHDRAWN);
355 withdrawn.release();
356 break;
357 case PURGED:
358 // Release one permit on the purged semaphore since the Intent event was received.
359 purged.release();
360 break;
361 default:
362 break;
363 }
364 }
365 }
366
367 /**
368 * Core service test class.
369 */
370 private class TestCoreService extends CoreServiceAdapter {
371
372 @Override
373 public IdGenerator getIdGenerator(String topic) {
374 return new IdGenerator() {
375 private AtomicLong counter = new AtomicLong(0);
376
377 @Override
378 public long getNewId() {
379 return counter.getAndIncrement();
380 }
381 };
382 }
383 }
384
385 private static class TestIntentCompiler implements IntentCompiler<VirtualNetworkIntent> {
386 @Override
387 public List<Intent> compile(VirtualNetworkIntent intent, List<Intent> installable) {
388 return Lists.newArrayList(new MockInstallableIntent());
389 }
390 }
391
392 private static class MockInstallableIntent extends FlowRuleIntent {
393
394 public MockInstallableIntent() {
395 super(APP_ID, Collections.singletonList(new IntentTestsMocks.MockFlowRule(100)), Collections.emptyList());
396 }
397 }
398}