Merge "Add pax exam schema integration tests"
[ovsdb.git] / integrationtest / src / test / java / org / opendaylight / ovsdb / integrationtest / neutron / NeutronIT.java
1 /*
2  * Copyright (C) 2014 Red Hat, Inc.
3  *
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
7  *
8  * Authors : Dave Tucker
9  */
10
11 package org.opendaylight.ovsdb.integrationtest.neutron;
12
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.fail;
16 import static org.ops4j.pax.exam.CoreOptions.junitBundles;
17 import static org.ops4j.pax.exam.CoreOptions.options;
18 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperty;
19 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
20
21 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
22 import org.opendaylight.controller.sal.core.Node;
23 import org.opendaylight.controller.sal.utils.Status;
24 import org.opendaylight.ovsdb.integrationtest.ConfigurationBundles;
25 import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
26 import org.opendaylight.ovsdb.lib.notation.Row;
27 import org.opendaylight.ovsdb.lib.notation.UUID;
28 import org.opendaylight.ovsdb.lib.notation.Version;
29 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
30 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
31 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
32 import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
34 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
35 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
36 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
37
38 import com.google.common.collect.ImmutableMap;
39 import org.apache.commons.lang3.tuple.ImmutablePair;
40 import org.apache.felix.dm.Component;
41 import org.apache.felix.dm.DependencyManager;
42 import org.junit.After;
43 import org.junit.Assert;
44 import org.junit.Before;
45 import org.junit.Ignore;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.ops4j.pax.exam.Configuration;
49 import org.ops4j.pax.exam.Option;
50 import org.ops4j.pax.exam.junit.PaxExam;
51 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
52 import org.ops4j.pax.exam.spi.reactors.PerClass;
53 import org.ops4j.pax.exam.util.PathUtils;
54 import org.osgi.framework.Bundle;
55 import org.osgi.framework.BundleContext;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import java.io.IOException;
60 import java.net.InetAddress;
61 import java.util.Map;
62 import java.util.Properties;
63 import java.util.concurrent.ExecutionException;
64 import java.util.concurrent.TimeoutException;
65
66 import javax.inject.Inject;
67
68
69 @RunWith(PaxExam.class)
70 @ExamReactorStrategy(PerClass.class)
71 public class NeutronIT extends OvsdbIntegrationTestBase {
72     private Logger log = LoggerFactory.getLogger(NeutronIT.class);
73     @Inject
74     private BundleContext bc;
75
76     @Inject
77     private OvsdbConfigurationService ovsdbConfigurationService;
78     private Node node = null;
79
80     Component of10Provider;
81     Component of13Provider;
82
83     @Inject
84     BridgeConfigurationManager bridgeConfigurationManager;
85     @Inject
86     ConfigurationService netVirtConfigurationService;
87
88     Boolean tearDownBridge = false;
89     ImmutablePair<UUID, Map<String, String>> tearDownOpenVSwitchOtherConfig = null;
90
91     // Configure the OSGi container
92     @Configuration
93     public Option[] config() {
94         return options(
95                 //
96                 systemProperty("logback.configurationFile").value(
97                         "file:" + PathUtils.getBaseDir()
98                         + "/src/test/resources/logback.xml"
99                 ),
100                 // To start OSGi console for inspection remotely
101                 systemProperty("osgi.console").value("2401"),
102
103                 propagateSystemProperty("ovsdbserver.ipaddress"),
104                 propagateSystemProperty("ovsdbserver.port"),
105
106                 ConfigurationBundles.controllerBundles(),
107                 ConfigurationBundles.ovsdbLibraryBundles(),
108                 ConfigurationBundles.ovsdbDefaultSchemaBundles(),
109                 ConfigurationBundles.ovsdbPluginBundles(),
110                 ConfigurationBundles.ovsdbNeutronBundles(),
111                 junitBundles()
112         );
113     }
114
115     @Before
116     public void areWeReady() throws InterruptedException, ExecutionException, IOException, TimeoutException {
117         assertNotNull(bc);
118         boolean debugit = false;
119         Bundle b[] = bc.getBundles();
120         for (Bundle element : b) {
121             int state = element.getState();
122             if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
123                 log.info("Bundle:" + element.getSymbolicName() + " state:"
124                          + stateToString(state));
125                 debugit = true;
126             }
127         }
128         if (debugit) {
129             log.debug("Do some debugging because some bundle is unresolved");
130         }
131
132         assertFalse(debugit);
133
134         if (node == null) {
135             try {
136                 node = getPluginTestConnection();
137             } catch (Exception e) {
138                 fail("Exception : " + e.getMessage());
139             }
140         }
141
142         //Register fake NetworkingProviders
143         Properties of10Properties = new Properties();
144         of10Properties.put(Constants.OPENFLOW_VERSION_PROPERTY, Constants.OPENFLOW10);
145
146         Properties of13Properties = new Properties();
147         of13Properties.put(Constants.OPENFLOW_VERSION_PROPERTY, Constants.OPENFLOW13);
148
149         DependencyManager dm = new DependencyManager(bc);
150
151         of10Provider = dm.createComponent();
152         of10Provider.setInterface(NetworkingProvider.class.getName(), of10Properties);
153         of10Provider.setImplementation(new FakeOF10Provider());
154
155         of13Provider = dm.createComponent();
156         of13Provider.setInterface(NetworkingProvider.class.getName(), of13Properties);
157         of13Provider.setImplementation(new FakeOF13Provider());
158
159         dm.add(of10Provider);
160         dm.add(of13Provider);
161     }
162
163     @Test
164     public void testPrepareNode() throws Exception {
165         Thread.sleep(5000);
166
167         // Create the integration bridge
168         bridgeConfigurationManager.prepareNode(node);
169
170         Map<String, Row>
171                 bridgeRows =
172                 ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
173         Assert.assertEquals(1, bridgeRows.size());
174
175         Bridge bridgeRow = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRows.values().iterator().next());
176         Assert.assertEquals(netVirtConfigurationService.getIntegrationBridgeName(), bridgeRow.getName());
177
178         String uuid = bridgeConfigurationManager.getBridgeUuid(node, netVirtConfigurationService.getIntegrationBridgeName());
179         Assert.assertEquals(uuid, bridgeRow.getUuid().toString());
180
181         tearDownBridge = true;
182     }
183
184     @Test
185     public void testGetTunnelEndpoint() throws Exception {
186         Thread.sleep(5000);
187
188         final String endpointAddress = "10.10.10.10";
189
190         Map<String, Row> ovsRows = ovsdbConfigurationService.getRows(node,
191                                                               ovsdbConfigurationService.getTableName(node, OpenVSwitch.class));
192         OpenVSwitch ovsRow = ovsdbConfigurationService.getTypedRow(node,
193                                                             OpenVSwitch.class,
194                                                             ovsRows.values().iterator().next());
195
196         Assert.assertEquals(null, netVirtConfigurationService.getTunnelEndPoint(node));
197         final UUID originalVersion = ovsRow.getVersion();
198
199         OpenVSwitch updateOvsRow = ovsdbConfigurationService.createTypedRow(node, OpenVSwitch.class);
200
201         updateOvsRow.setOtherConfig(
202                 ImmutableMap.of(netVirtConfigurationService.getTunnelEndpointKey(), endpointAddress));
203
204         ovsdbConfigurationService.updateRow(node,
205                                             ovsdbConfigurationService.getTableName(node, OpenVSwitch.class),
206                                             null,
207                                             ovsRow.getUuid().toString(),
208                                             updateOvsRow.getRow());
209
210         // Remember original value so it can be restored on tearDown
211         tearDownOpenVSwitchOtherConfig = ImmutablePair.of(ovsRow.getUuid(),
212                                                           ovsRow.getOtherConfigColumn().getData());
213
214         // Make sure tunnel end point was set
215         Assert.assertEquals(InetAddress.getByName(endpointAddress), netVirtConfigurationService.getTunnelEndPoint(node));
216
217         // Fetch rows again, and compare tunnel end point values
218         ovsRows = ovsdbConfigurationService.getRows(node,
219                                                     ovsdbConfigurationService.getTableName(node, OpenVSwitch.class));
220         ovsRow = ovsdbConfigurationService.getTypedRow(node,
221                                                        OpenVSwitch.class,
222                                                        ovsRows.values().iterator().next());
223
224         Assert.assertEquals(ovsRow.getOtherConfigColumn(), updateOvsRow.getOtherConfigColumn());
225
226         // expect version of row to be changed, due to the update
227         Assert.assertNotEquals(ovsRow.getVersion(), originalVersion);
228     }
229
230     // Note: The openFlow version is now determined by configuration's getProperty("ovsdb.of.version", "1.3").
231     // Thus, the ovs version attribute (returned by ovs' OpenVSwitch table) is not used to determine what is
232     // the openFlow version chosen by netVirtConfigurationService.
233     // See: https://git.opendaylight.org/gerrit/#/c/11084/
234     //      https://github.com/opendaylight/ovsdb/commit/2bc58c9cca16dc3e389cdfc18593578748fd52d5
235     @Ignore("netVirtConfigurationService.getOpenflowVersion(node) is not dependent on Constants.OPENFLOW13_SUPPORTED")
236     @Test
237     public void testGetOpenflowVersion() throws Exception {
238         Thread.sleep(5000);
239
240         Version ovsVersion = this.getOvsVersion();
241
242         if (ovsVersion.compareTo(Constants.OPENFLOW13_SUPPORTED) < 0) {
243             Assert.assertEquals(Constants.OPENFLOW10, netVirtConfigurationService.getOpenflowVersion(node));
244         } else {
245             Assert.assertEquals(Constants.OPENFLOW13, netVirtConfigurationService.getOpenflowVersion(node));
246         }
247     }
248
249     @Test
250     public void testGetDefaultGatewayMacAddress() throws Exception {
251         // Thread.sleep(5000);
252         String defaultGatewayMacAddress = netVirtConfigurationService.getDefaultGatewayMacAddress(node);
253
254         if (defaultGatewayMacAddress != null) {
255             String[] splits = defaultGatewayMacAddress.split(":");
256             Assert.assertTrue("Unexpected mac format", splits.length == 6);
257         }
258         // log.info("testGetDefaultGatewayMacAddress got mac {}", defaultGatewayMacAddress);
259     }
260
261     @After
262     public void tearDown() throws InterruptedException {
263         Thread.sleep(5000);
264
265         if (tearDownBridge) {
266             try {
267                 String uuid = bridgeConfigurationManager.getBridgeUuid(node,
268                                                                        netVirtConfigurationService.getIntegrationBridgeName());
269                 ovsdbConfigurationService.deleteRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), uuid);
270             } catch (Exception e) {
271                 log.error("tearDownBridge Exception : " + e.getMessage());
272             }
273             tearDownBridge = false;
274         }
275
276         if (tearDownOpenVSwitchOtherConfig != null) {
277             try {
278                 OpenVSwitch updateOvsRow = ovsdbConfigurationService.createTypedRow(node, OpenVSwitch.class);
279                 updateOvsRow.setOtherConfig(tearDownOpenVSwitchOtherConfig.getRight());
280                 ovsdbConfigurationService.updateRow(node,
281                                                     ovsdbConfigurationService.getTableName(node, OpenVSwitch.class),
282                                                     null,
283                                                     tearDownOpenVSwitchOtherConfig.getLeft().toString(),
284                                                     updateOvsRow.getRow());
285             } catch (Exception e) {
286                 log.error("tearDownOpenVSwitchOtherConfig Exception : " + e.getMessage());
287             }
288             tearDownOpenVSwitchOtherConfig = null;
289         }
290
291         DependencyManager dm = new DependencyManager(bc);
292         dm.remove(of10Provider);
293         dm.remove(of13Provider);
294     }
295
296     private Version getOvsVersion(){
297         Map<String, Row> ovsRows = ovsdbConfigurationService.getRows(node,
298                                                               ovsdbConfigurationService.getTableName(node, OpenVSwitch.class));
299         OpenVSwitch ovsRow = ovsdbConfigurationService.getTypedRow(node,
300                                                             OpenVSwitch.class,
301                                                             ovsRows.values().iterator().next());
302         return Version.fromString(ovsRow.getOvsVersionColumn().getData().iterator().next());
303     }
304
305     private class FakeOF10Provider implements NetworkingProvider {
306
307         @Override
308         public String getName() {
309             return null;
310         }
311
312         @Override
313         public boolean supportsServices() {
314             return false;
315         }
316
317         @Override
318         public boolean hasPerTenantTunneling() {
319             return true;
320         }
321
322         @Override
323         public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
324             return null;
325         }
326
327         @Override
328         public Status handleInterfaceUpdate(NeutronNetwork network, Node source, Interface intf) {
329             return null;
330         }
331
332         @Override
333         public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node source, Interface intf,
334                                             boolean isLastInstanceOnNode) {
335             return null;
336         }
337
338         @Override
339         public void initializeFlowRules(Node node) {
340
341         }
342
343         @Override
344         public void initializeOFFlowRules(Node openflowNode) {
345
346         }
347     }
348
349     private class FakeOF13Provider implements NetworkingProvider {
350
351         @Override
352         public String getName() {
353             return null;
354         }
355
356         @Override
357         public boolean supportsServices() {
358             return false;
359         }
360
361         @Override
362         public boolean hasPerTenantTunneling() {
363             return false;
364         }
365
366         @Override
367         public Status handleInterfaceUpdate(String tunnelType, String tunnelKey) {
368             return null;
369         }
370
371         @Override
372         public Status handleInterfaceUpdate(NeutronNetwork network, Node source, Interface intf) {
373             return null;
374         }
375
376         @Override
377         public Status handleInterfaceDelete(String tunnelType, NeutronNetwork network, Node source, Interface intf,
378                                             boolean isLastInstanceOnNode) {
379             return null;
380         }
381
382         @Override
383         public void initializeFlowRules(Node node) {
384
385         }
386
387         @Override
388         public void initializeOFFlowRules(Node openflowNode) {
389
390         }
391     }
392 }