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.options;
19 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperty;
20 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
22 import org.junit.After;
23 import org.junit.Ignore;
24 import org.opendaylight.ovsdb.integrationtest.ConfigurationBundles;
25 import org.opendaylight.ovsdb.integrationtest.OvsdbIntegrationTestBase;
26 import org.opendaylight.ovsdb.lib.OvsdbClient;
27 import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo;
28 import org.opendaylight.ovsdb.lib.notation.Row;
29 import org.opendaylight.ovsdb.plugin.api.Connection;
30 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
31 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
32 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
34 import org.opendaylight.ovsdb.plugin.api.Status;
35 import org.opendaylight.ovsdb.plugin.api.StatusWithUuid;
36 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
37 import org.opendaylight.ovsdb.schema.openvswitch.OpenVSwitch;
38 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
44 import com.google.common.collect.ImmutableMap;
45 import com.google.common.collect.Sets;
47 import org.apache.felix.dm.Component;
48 import org.apache.felix.dm.DependencyManager;
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.junit.runner.RunWith;
52 import org.mockito.Mockito;
53 import org.ops4j.pax.exam.Configuration;
54 import org.ops4j.pax.exam.Option;
55 import org.ops4j.pax.exam.junit.PaxExam;
56 import org.ops4j.pax.exam.util.PathUtils;
57 import org.osgi.framework.Bundle;
58 import org.osgi.framework.BundleContext;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 import java.net.InetAddress;
63 import java.net.UnknownHostException;
64 import java.util.List;
66 import java.util.concurrent.ConcurrentMap;
68 import javax.inject.Inject;
71 @RunWith(PaxExam.class)
72 public class OvsdbPluginIT extends OvsdbIntegrationTestBase {
73 private static final Logger LOG = LoggerFactory.getLogger(OvsdbPluginIT.class);
75 private BundleContext bc;
76 private OvsdbConfigurationService ovsdbConfigurationService = null;
79 private OvsdbInventoryService ovsdbInventoryService;
81 private Node node = null;
82 private OvsdbClient client = null;
84 // Configure the OSGi container
86 public Option[] config() {
89 systemProperty("logback.configurationFile").value(
90 "file:" + PathUtils.getBaseDir()
91 + "/src/test/resources/logback.xml"
93 // To start OSGi console for inspection remotely
94 systemProperty("osgi.console").value("2401"),
96 propagateSystemProperty("ovsdbserver.ipaddress"),
97 propagateSystemProperty("ovsdbserver.port"),
99 ConfigurationBundles.mdsalBundles(),
100 ConfigurationBundles.controllerBundles(),
101 ConfigurationBundles.ovsdbLibraryBundles(),
102 ConfigurationBundles.ovsdbDefaultSchemaBundles(),
103 ConfigurationBundles.ovsdbPluginBundles()
108 public void areWeReady() throws InterruptedException {
110 boolean debugit = false;
111 Bundle b[] = bc.getBundles();
112 for (Bundle element : b) {
113 int state = element.getState();
114 if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
115 LOG.info("Bundle: {} state: {}", element.getSymbolicName(), stateToString(state));
120 LOG.debug("Do some debugging because some bundle is unresolved");
123 assertFalse(debugit);
125 node = getPluginTestConnection();
126 } catch (Exception e) {
127 fail("Exception : "+e.getMessage());
129 this.ovsdbConfigurationService = (OvsdbConfigurationService)ServiceHelper.getGlobalInstance(OvsdbConfigurationService.class, this);
133 public void apiTests() throws Exception {
135 OvsdbConnectionService
136 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
138 // Check for the ovsdb Connection as seen by the Plugin layer
139 assertNotNull(connectionService.getNodes());
140 assertTrue(connectionService.getNodes().size() > 0);
141 Node node = connectionService.getNodes().get(0);
142 Connection connection = connectionService.getConnection(node);
143 OvsdbConnectionInfo connectionInfo = connection.getClient().getConnectionInfo();
144 String identifier = IDENTIFIER;
145 if (connectionInfo.getType().equals(OvsdbConnectionInfo.ConnectionType.PASSIVE)) {
146 identifier = connectionInfo.getRemoteAddress().getHostAddress()+":"+connectionInfo.getRemotePort();
148 assertEquals(node, connectionService.getNode("OVS|" + identifier));
149 System.out.println("Nodes = "+ connectionService.getNodes());
152 * 1. Print Cache and Assert to make sure the bridge is not created yet.
153 * 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
154 * 3. Assert to make sure the bridge is created with a valid Uuid.
155 * 4. Delete the bridge & Assert to make sure the return status is success.
156 * 5. Assert to make sure the bridge is deleted
159 this.endToEndApiTest(connection, getOpenVSwitchTableUUID(connection));
162 * Repeat all of the above tests without the parent_uuid
165 this.endToEndApiTest(connection, null);
169 public void testInventoryListeners() throws UnknownHostException {
170 DependencyManager dm = new DependencyManager(bc);
172 OvsdbInventoryListener listenerA = Mockito.mock(FakeListener.class);
173 OvsdbInventoryListener listenerB = Mockito.mock(FakeListener.class);
175 Component componentA = dm.createComponent();
176 componentA.setInterface(OvsdbInventoryListener.class.getName(), null);
177 componentA.setImplementation(listenerA);
180 Component componentB = dm.createComponent();
181 componentB.setInterface(OvsdbInventoryListener.class.getName(), null);
182 componentB.setImplementation(listenerB);
185 NodeId nodeId = new NodeId("OVS|10.10.10.10:65342");
186 NodeKey nodeKey = new NodeKey(nodeId);
187 node = new NodeBuilder()
191 InetAddress address = InetAddress.getByName("10.10.10.10");
195 ovsdbInventoryService.notifyNodeAdded(node, address, port);
197 Mockito.verify(listenerA, Mockito.times(1)).nodeAdded(node, address, port);
198 Mockito.verify(listenerB, Mockito.times(1)).nodeAdded(node, address, port);
200 dm.remove(componentA);
201 dm.remove(componentB);
206 public void testSetOFControllers() throws Exception {
208 OvsdbConnectionService
209 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
211 // 1. Check for the ovsdb Connection as seen by the Plugin layer
212 assertNotNull(connectionService.getNodes());
213 assertTrue(connectionService.getNodes().size() > 0);
214 Node node = connectionService.getNodes().get(0);
215 Connection connection = connectionService.getConnection(node);
216 assertNotNull(connection);
218 // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
219 final StatusWithUuid status = insertBridge(connection, getOpenVSwitchTableUUID(connection));
220 assertTrue(status.isSuccess());
222 // Thread.sleep(3000); // wait for _real_ controller to be added to bridge... or not (see below **)
224 // 3. Test against bug 960: Add same controller multiple times and make sure we do not end up with duplicates.
225 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
226 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
227 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
228 ovsdbConfigurationService.setOFController(node, status.getUuid().toString());
230 Row bridgeRow = ovsdbConfigurationService.getRow(node,
231 ovsdbConfigurationService.getTableName(node, Bridge.class),
232 status.getUuid().toString());
233 assertNotNull(bridgeRow);
234 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
235 assertTrue(bridge.getUuid().equals(status.getUuid()));
237 final int currControllersSize = bridge.getControllerColumn().getData().size();
239 LOG.debug("Bridge has {} controllers", currControllersSize);
241 // ** Note: we assert against 2 or less -- instead of 1 -- to account for the _real_ controller's connection
242 assertTrue( "Too few controllers added to bridge object. Is this bug 960?", currControllersSize >= 1 );
243 assertTrue( "Too many controllers added to bridge object. Is this bug 960?", currControllersSize <= 2 );
245 // Removal of bridge created in this test is done via tearDown(). It is done that way, so cleanup is ran
246 // even if test fails.
250 public void tearDown() throws InterruptedException {
252 OvsdbConnectionService
253 connectionService = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
255 if (connectionService.getNodes() == null) {
256 return; // no nodes: noop
259 int bridgesRemoved = 0;
260 List<Node> nodes = connectionService.getNodes();
261 for (Node node : nodes) {
262 Map<String, Row> bridgeRows =
263 ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Bridge.class));
264 if (bridgeRows == null) {
267 for (Row bridgeRow : bridgeRows.values()) {
268 Bridge bridge = ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow);
269 LOG.trace("Test clean up removing Bridge {}", bridge.getUuid());
270 Status delStatus = ovsdbConfigurationService.deleteRow(node,
271 bridge.getSchema().getName(),
272 bridge.getUuid().toString());
273 assertTrue(delStatus.isSuccess());
278 if (bridgesRemoved > 0) {
279 LOG.debug("Test clean up removed {} bridges", bridgesRemoved);
280 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
284 public void endToEndApiTest(Connection connection, String parentUuid) throws Exception {
285 // 1. Print Cache and Assert to make sure the bridge is not created yet.
288 // 2. Create a bridge with a valid parent_uuid & Assert to make sure the return status is success.
289 StatusWithUuid status = insertBridge(connection, parentUuid);
290 assertTrue(status.isSuccess());
292 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
294 // 3. Assert to make sure the bridge is created with a valid Uuid.
296 Bridge bridge = connection.getClient().getTypedRowWrapper(Bridge.class, null);
297 Row bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
298 assertNotNull(bridgeRow);
299 bridge = connection.getClient().getTypedRowWrapper(Bridge.class, bridgeRow);
300 assertEquals(bridge.getUuid(), status.getUuid());
302 // 4. Delete the bridge & Assert to make sure the return status is success.
303 Status delStatus = ovsdbConfigurationService.deleteRow(node, bridge.getSchema().getName(), status.getUuid().toString());
304 assertTrue(delStatus.isSuccess());
305 Thread.sleep(2000); // TODO : Remove this Sleep once the Select operation is resolved.
307 // 5. Assert to make sure the bridge is deleted
308 bridgeRow = ovsdbConfigurationService.getRow(node, bridge.getSchema().getName(), status.getUuid().toString());
309 assertNull(bridgeRow);
312 public StatusWithUuid insertBridge(Connection connection, String parentUuid) throws Exception {
313 Bridge bridge = connection.getClient().createTypedRowWrapper(Bridge.class);
314 bridge.setName("br_test1");
315 bridge.setStatus(ImmutableMap.of("key", "value"));
316 bridge.setFloodVlans(Sets.newHashSet(34L));
317 return ovsdbConfigurationService.insertRow(node, bridge.getSchema().getName(), parentUuid, bridge.getRow());
320 public String getOpenVSwitchTableUUID(Connection connection) throws Exception {
321 OpenVSwitch openVSwitch = connection.getClient().getTypedRowWrapper(OpenVSwitch.class, null);
322 ConcurrentMap<String, Row> row = ovsdbConfigurationService.getRows(node, openVSwitch.getSchema().getName());
323 if (row == null || row.size() == 0) {
326 return (String)row.keySet().toArray()[0];
329 public void printCache() throws Exception {
330 List<String> tables = ovsdbConfigurationService.getTables(node);
331 System.out.println("Tables = "+tables);
332 assertNotNull(tables);
333 for (String table : tables) {
334 System.out.println("Table "+table);
335 ConcurrentMap<String,Row> row = ovsdbConfigurationService.getRows(node, table);
336 System.out.println(row);
340 public class FakeListener implements OvsdbInventoryListener {
343 public void nodeAdded(Node node, InetAddress address, int port) {
348 public void nodeRemoved(Node node) {
353 public void rowAdded(Node node, String tableName, String uuid, Row row) {
358 public void rowUpdated(Node node, String tableName, String uuid, Row old, Row row) {
363 public void rowRemoved(Node node, String tableName, String uuid, Row row, Object context) {