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.ovsdb.integrationtest.ConfigurationBundles;
27 import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
28 import org.opendaylight.ovsdb.lib.OvsdbClient;
29 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
30 import org.opendaylight.ovsdb.lib.notation.Row;
31 import org.opendaylight.ovsdb.plugin.api.Connection;
32 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
34 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
35 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
36 import org.opendaylight.ovsdb.plugin.api.Status;
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(),
103 public void areWeReady() throws InterruptedException {
105 boolean debugit = false;
106 Bundle b[] = bc.getBundles();
107 for (Bundle element : b) {
108 int state = element.getState();
109 if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
110 log.info("Bundle:" + element.getSymbolicName() + " state:"
111 + stateToString(state));
116 log.debug("Do some debugging because some bundle is unresolved");
119 assertFalse(debugit);
121 node = getPluginTestConnection();
122 } catch (Exception e) {
123 fail("Exception : "+e.getMessage());
125 this.ovsdbConfigurationService = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class, this);
129 public void apiTests() throws Exception {
131 OvsdbConnectionService
132 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
134 // Check for the ovsdb Connection as seen by the Plugin layer
135 assertNotNull(connectionService.getNodes());
136 assertTrue(connectionService.getNodes().size() > 0);
137 Node node = connectionService.getNodes().get(0);
138 Connection connection = connectionService.getConnection(node);
139 OvsdbConnectionInfo connectionInfo = connection.getClient().getConnectionInfo();
140 String identifier = IDENTIFIER;
141 if (connectionInfo.getType().equals(OvsdbConnectionInfo.ConnectionType.PASSIVE)) {
142 identifier = connectionInfo.getRemoteAddress().getHostAddress()+":"+connectionInfo.getRemotePort();
144 assertEquals(node, connectionService.getNode("OVS|" + identifier));
145 System.out.println("Nodes = "+ connectionService.getNodes());
148 * 1. Print Cache and Assert to make sure the bridge is not created yet.
149 * 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
150 * 3. Assert to make sure the bridge is created with a valid Uuid.
151 * 4. Delete the bridge & Assert to make sure the return status is success.
152 * 5. Assert to make sure the bridge is deleted
155 this.endToEndApiTest(connection, getOpenVSwitchTableUUID(connection));
158 * Repeat all of the above tests without the parent_uuid
161 this.endToEndApiTest(connection, null);
165 public void testInventoryListeners() throws UnknownHostException {
166 DependencyManager dm = new DependencyManager(bc);
168 OvsdbInventoryListener listenerA = Mockito.mock(FakeListener.class);
169 OvsdbInventoryListener listenerB = Mockito.mock(FakeListener.class);
171 Component componentA = dm.createComponent();
172 componentA.setInterface(OvsdbInventoryListener.class.getName(), null);
173 componentA.setImplementation(listenerA);
176 Component componentB = dm.createComponent();
177 componentB.setInterface(OvsdbInventoryListener.class.getName(), null);
178 componentB.setImplementation(listenerB);
181 Node newNode = Node.fromString("OVS|10.10.10.10:65342");
182 InetAddress address = InetAddress.getByName("10.10.10.10");
186 ovsdbInventoryService.notifyNodeAdded(newNode, address, port);
188 Mockito.verify(listenerA, Mockito.times(1)).nodeAdded(newNode, address, port);
189 Mockito.verify(listenerB, Mockito.times(1)).nodeAdded(newNode, address, port);
191 dm.remove(componentA);
192 dm.remove(componentB);
197 public void testSetOFControllers() throws Exception {
199 OvsdbConnectionService
200 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
202 // 1. Check for the ovsdb Connection as seen by the Plugin layer
203 assertNotNull(connectionService.getNodes());
204 assertTrue(connectionService.getNodes().size() > 0);
205 Node node = connectionService.getNodes().get(0);
206 Connection connection = connectionService.getConnection(node);
207 assertNotNull(connection);
209 // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
210 final StatusWithUuid status = insertBridge(connection, getOpenVSwitchTableUUID(connection));
211 assertTrue(status.isSuccess());
213 // Thread.sleep(3000); // wait for _real_ controller to be added to bridge... or not (see below **)
215 // 3. Test against bug 960: Add same controller multiple times and make sure we do not end up with duplicates.
216 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
217 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
218 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
219 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
221 Row bridgeRow = ovsdbConfigurationService.getRow(node,
222 ovsdbConfigurationService.getTableName(node, Bridge.class),
223 status.getUuid().toString());
224 assertNotNull(bridgeRow);
225 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
226 assertTrue(bridge.getUuid().equals(status.getUuid()));
228 final int currControllersSize = bridge.getControllerColumn().getData().size();
230 log.debug("Bridge has " + bridge.getControllerColumn().getData().size() + " controllers");
232 // ** Note: we assert against 2 or less -- instead of 1 -- to account for the _real_ controller's connection
233 assertTrue( "Too few controllers added to bridge object. Is this bug 960?", currControllersSize >= 1 );
234 assertTrue( "Too many controllers added to bridge object. Is this bug 960?", currControllersSize <= 2 );
236 // Removal of bridge created in this test is done via tearDown(). It is done that way, so cleanup is ran
237 // even if test fails.
241 public void tearDown() throws InterruptedException {
243 OvsdbConnectionService
244 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
246 if (connectionService.getNodes() == null) {
247 return; // no nodes: noop
250 int bridgesRemoved = 0;
251 List<Node> nodes = connectionService.getNodes();
252 for (Node node : nodes) {
253 Map<String, Row> bridgeRows =
254 ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
255 if (bridgeRows == null) {
258 for (Row bridgeRow : bridgeRows.values()) {
259 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
260 log.trace("Test clean up removing Bridge " + bridge.getUuid());
261 Status delStatus = ovsdbConfigurationService.deleteRow(node,
262 bridge.getSchema().getName(),
263 bridge.getUuid().toString());
264 assertTrue(delStatus.isSuccess());
269 if (bridgesRemoved > 0) {
270 log.debug("Test clean up removed " + bridgesRemoved + " bridges");
271 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
275 public void endToEndApiTest(Connection connection, String parentUuid) throws Exception {
276 // 1. Print Cache and Assert to make sure the bridge is not created yet.
279 // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
280 StatusWithUuid status = insertBridge(connection, parentUuid);
281 assertTrue(status.isSuccess());
283 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
285 // 3. Assert to make sure the bridge is created with a valid Uuid.
287 Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
288 Row bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
289 assertNotNull(bridgeRow);
290 bridge = connection.getClient().getTypedRowWrapper(Bridge.class, bridgeRow);
291 assertEquals(bridge.getUuid(), status.getUuid());
293 // 4. Delete the bridge & Assert to make sure the return status is success.
294 Status delStatus = ovsdbConfigurationService.deleteRow(node, bridge.getSchema().getName(), status.getUuid().toString());
295 assertTrue(delStatus.isSuccess());
296 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
298 // 5. Assert to make sure the bridge is deleted
299 bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
300 assertNull(bridgeRow);
303 public StatusWithUuid insertBridge(Connection connection, String parentUuid) throws Exception {
304 Bridge bridge = connection.getClient().createTypedRowWrapper(Bridge.class);
305 bridge.setName("br_test1");
306 bridge.setStatus(ImmutableMap.of("key", "value"));
307 bridge.setFloodVlans(Sets.newHashSet(34L));
308 return ovsdbConfigurationService.insertRow(node, bridge.getSchema().getName(), parentUuid, bridge.getRow());
311 public String getOpenVSwitchTableUUID(Connection connection) throws Exception {
312 OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
313 ConcurrentMap<String, Row> row = ovsdbConfigurationService.getRows(node, openVSwitch.getSchema().getName());
314 if (row == null || row.size() == 0) return null;
315 return (String)row.keySet().toArray()[0];
318 public void printCache() throws Exception {
319 List<String> tables = ovsdbConfigurationService.getTables(node);
320 System.out.println("Tables = "+tables);
321 assertNotNull(tables);
322 for (String table : tables) {
323 System.out.println("Table "+table);
324 ConcurrentMap<String,Row> row = ovsdbConfigurationService.getRows(node, table);
325 System.out.println(row);
329 public class FakeListener implements OvsdbInventoryListener {
332 public void nodeAdded(Node node, InetAddress address, int port) {
337 public void nodeRemoved(Node node) {
342 public void rowAdded(Node node, String tableName, String uuid, Row row) {
347 public void rowUpdated(Node node, String tableName, String uuid, Row old, Row row) {
352 public void rowRemoved(Node node, String tableName, String uuid, Row row, Object context) {