2 * Copyright (c) 2014 Red Hat, Inc. 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 * Authors : Madhu Venugopal
10 package org.opendaylight.ovsdb.integrationtest.plugin;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertNull;
16 import static org.junit.Assert.assertTrue;
17 import static org.junit.Assert.fail;
18 import static org.ops4j.pax.exam.CoreOptions.junitBundles;
19 import static org.ops4j.pax.exam.CoreOptions.options;
20 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperty;
21 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
23 import org.junit.After;
24 import org.opendaylight.controller.sal.core.Node;
25 import org.opendaylight.controller.sal.utils.ServiceHelper;
26 import org.opendaylight.controller.sal.utils.Status;
27 import org.opendaylight.ovsdb.integrationtest.ConfigurationBundles;
28 import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
29 import org.opendaylight.ovsdb.lib.OvsdbClient;
30 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
31 import org.opendaylight.ovsdb.lib.notation.Row;
32 import org.opendaylight.ovsdb.plugin.api.Connection;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
34 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
35 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
36 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
37 import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
38 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
39 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
41 import com.google.common.collect.ImmutableMap;
42 import com.google.common.collect.Sets;
43 import org.apache.felix.dm.Component;
44 import org.apache.felix.dm.DependencyManager;
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.Mockito;
49 import org.ops4j.pax.exam.Configuration;
50 import org.ops4j.pax.exam.Option;
51 import org.ops4j.pax.exam.junit.PaxExam;
52 import org.ops4j.pax.exam.util.PathUtils;
53 import org.osgi.framework.Bundle;
54 import org.osgi.framework.BundleContext;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 import java.net.InetAddress;
59 import java.net.UnknownHostException;
60 import java.util.List;
62 import java.util.concurrent.ConcurrentMap;
64 import javax.inject.Inject;
66 @RunWith(PaxExam.class)
67 public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
68 private Logger log = LoggerFactory.getLogger(OvsdbPluginIT.class);
70 private BundleContext bc;
71 private OvsdbConfigurationService ovsdbConfigurationService = null;
74 private OvsdbInventoryService ovsdbInventoryService;
76 private Node node = null;
77 private OvsdbClient client = null;
79 // Configure the OSGi container
81 public Option[] config() {
84 systemProperty("logback.configurationFile").value(
85 "file:" + PathUtils.getBaseDir()
86 + "/src/test/resources/logback.xml"
88 // To start OSGi console for inspection remotely
89 systemProperty("osgi.console").value("2401"),
91 propagateSystemProperty("ovsdbserver.ipaddress"),
92 propagateSystemProperty("ovsdbserver.port"),
94 ConfigurationBundles.controllerBundles(),
95 ConfigurationBundles.ovsdbLibraryBundles(),
96 ConfigurationBundles.ovsdbDefaultSchemaBundles(),
97 ConfigurationBundles.ovsdbPluginBundles(),
102 private String stateToString(int state) {
106 case Bundle.INSTALLED:
108 case Bundle.RESOLVED:
110 case Bundle.UNINSTALLED:
111 return "UNINSTALLED";
113 return "Not CONVERTED";
118 public void areWeReady() throws InterruptedException {
120 boolean debugit = false;
121 Bundle b[] = bc.getBundles();
122 for (Bundle element : b) {
123 int state = element.getState();
124 if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
125 log.info("Bundle:" + element.getSymbolicName() + " state:"
126 + stateToString(state));
131 log.debug("Do some debugging because some bundle is unresolved");
134 assertFalse(debugit);
136 node = getPluginTestConnection();
137 } catch (Exception e) {
138 fail("Exception : "+e.getMessage());
140 this.ovsdbConfigurationService = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class, this);
144 public void apiTests() throws Exception {
146 OvsdbConnectionService
147 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
149 // Check for the ovsdb Connection as seen by the Plugin layer
150 assertNotNull(connectionService.getNodes());
151 assertTrue(connectionService.getNodes().size() > 0);
152 Node node = connectionService.getNodes().get(0);
153 Connection connection = connectionService.getConnection(node);
154 OvsdbConnectionInfo connectionInfo = connection.getClient().getConnectionInfo();
155 String identifier = IDENTIFIER;
156 if (connectionInfo.getType().equals(OvsdbConnectionInfo.ConnectionType.PASSIVE)) {
157 identifier = connectionInfo.getRemoteAddress().getHostAddress()+":"+connectionInfo.getRemotePort();
159 assertEquals(Node.fromString("OVS|" + identifier), connectionService.getNodes().get(0));
160 System.out.println("Nodes = "+ connectionService.getNodes());
163 * 1. Print Cache and Assert to make sure the bridge is not created yet.
164 * 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
165 * 3. Assert to make sure the bridge is created with a valid Uuid.
166 * 4. Delete the bridge & Assert to make sure the return status is success.
167 * 5. Assert to make sure the bridge is deleted
170 this.endToEndApiTest(connection, getOpenVSwitchTableUUID(connection));
173 * Repeat all of the above tests without the parent_uuid
176 this.endToEndApiTest(connection, null);
180 public void testInventoryListeners() throws UnknownHostException {
181 DependencyManager dm = new DependencyManager(bc);
183 OvsdbInventoryListener listenerA = Mockito.mock(FakeListener.class);
184 OvsdbInventoryListener listenerB = Mockito.mock(FakeListener.class);
186 Component componentA = dm.createComponent();
187 componentA.setInterface(OvsdbInventoryListener.class.getName(), null);
188 componentA.setImplementation(listenerA);
191 Component componentB = dm.createComponent();
192 componentB.setInterface(OvsdbInventoryListener.class.getName(), null);
193 componentB.setImplementation(listenerB);
196 Node newNode = Node.fromString("OVS:10.10.10.10:65342");
197 InetAddress address = InetAddress.getByName("10.10.10.10");
201 ovsdbInventoryService.notifyNodeAdded(newNode, address, port);
203 Mockito.verify(listenerA, Mockito.times(1)).nodeAdded(newNode, address, port);
204 Mockito.verify(listenerB, Mockito.times(1)).nodeAdded(newNode, address, port);
206 dm.remove(componentA);
207 dm.remove(componentB);
212 public void testSetOFControllers() throws Exception {
214 OvsdbConnectionService
215 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
217 // 1. Check for the ovsdb Connection as seen by the Plugin layer
218 assertNotNull(connectionService.getNodes());
219 assertTrue(connectionService.getNodes().size() > 0);
220 Node node = connectionService.getNodes().get(0);
221 Connection connection = connectionService.getConnection(node);
222 assertNotNull(connection);
224 // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
225 final StatusWithUuid status = insertBridge(connection, getOpenVSwitchTableUUID(connection));
226 assertTrue(status.isSuccess());
228 // Thread.sleep(3000); // wait for _real_ controller to be added to bridge... or not (see below **)
230 // 3. Test against bug 960: Add same controller multiple times and make sure we do not end up with duplicates.
231 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
232 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
233 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
234 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
236 Row bridgeRow = ovsdbConfigurationService.getRow(node,
237 ovsdbConfigurationService.getTableName(node, Bridge.class),
238 status.getUuid().toString());
239 assertNotNull(bridgeRow);
240 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
241 assertTrue(bridge.getUuid().equals(status.getUuid()));
243 final int currControllersSize = bridge.getControllerColumn().getData().size();
245 log.debug("Bridge has " + bridge.getControllerColumn().getData().size() + " controllers");
247 // ** Note: we assert against 2 or less -- instead of 1 -- to account for the _real_ controller's connection
248 assertTrue( "Too few controllers added to bridge object. Is this bug 960?", currControllersSize >= 1 );
249 assertTrue( "Too many controllers added to bridge object. Is this bug 960?", currControllersSize <= 2 );
251 // Removal of bridge created in this test is done via tearDown(). It is done that way, so cleanup is ran
252 // even if test fails.
256 public void tearDown() throws InterruptedException {
258 OvsdbConnectionService
259 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
261 if (connectionService.getNodes() == null) {
262 return; // no nodes: noop
265 int bridgesRemoved = 0;
266 List<Node> nodes = connectionService.getNodes();
267 for (Node node : nodes) {
268 Map<String, Row> bridgeRows =
269 ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
270 if (bridgeRows == null) {
273 for (Row bridgeRow : bridgeRows.values()) {
274 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
275 log.trace("Test clean up removing Bridge " + bridge.getUuid());
276 Status delStatus = ovsdbConfigurationService.deleteRow(node,
277 bridge.getSchema().getName(),
278 bridge.getUuid().toString());
279 assertTrue(delStatus.isSuccess());
284 if (bridgesRemoved > 0) {
285 log.debug("Test clean up removed " + bridgesRemoved + " bridges");
286 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
290 public void endToEndApiTest(Connection connection, String parentUuid) throws Exception {
291 // 1. Print Cache and Assert to make sure the bridge is not created yet.
294 // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
295 StatusWithUuid status = insertBridge(connection, parentUuid);
296 assertTrue(status.isSuccess());
298 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
300 // 3. Assert to make sure the bridge is created with a valid Uuid.
302 Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
303 Row bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
304 assertNotNull(bridgeRow);
305 bridge = connection.getClient().getTypedRowWrapper(Bridge.class, bridgeRow);
306 assertEquals(bridge.getUuid(), status.getUuid());
308 // 4. Delete the bridge & Assert to make sure the return status is success.
309 Status delStatus = ovsdbConfigurationService.deleteRow(node, bridge.getSchema().getName(), status.getUuid().toString());
310 assertTrue(delStatus.isSuccess());
311 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
313 // 5. Assert to make sure the bridge is deleted
314 bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
315 assertNull(bridgeRow);
318 public StatusWithUuid insertBridge(Connection connection, String parentUuid) throws Exception {
319 Bridge bridge = connection.getClient().createTypedRowWrapper(Bridge.class);
320 bridge.setName("br_test1");
321 bridge.setStatus(ImmutableMap.of("key", "value"));
322 bridge.setFloodVlans(Sets.newHashSet(34L));
323 return ovsdbConfigurationService.insertRow(node, bridge.getSchema().getName(), parentUuid, bridge.getRow());
326 public String getOpenVSwitchTableUUID(Connection connection) throws Exception {
327 OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
328 ConcurrentMap<String, Row> row = ovsdbConfigurationService.getRows(node, openVSwitch.getSchema().getName());
329 if (row == null || row.size() == 0) return null;
330 return (String)row.keySet().toArray()[0];
333 public void printCache() throws Exception {
334 List<String> tables = ovsdbConfigurationService.getTables(node);
335 System.out.println("Tables = "+tables);
336 assertNotNull(tables);
337 for (String table : tables) {
338 System.out.println("Table "+table);
339 ConcurrentMap<String,Row> row = ovsdbConfigurationService.getRows(node, table);
340 System.out.println(row);
344 public class FakeListener implements OvsdbInventoryListener {
347 public void nodeAdded(Node node, InetAddress address, int port) {
352 public void nodeRemoved(Node node) {
357 public void rowAdded(Node node, String tableName, String uuid, Row row) {
362 public void rowUpdated(Node node, String tableName, String uuid, Row old, Row row) {
367 public void rowRemoved(Node node, String tableName, String uuid, Row row, Object context) {