2 * Copyright (C) 2014 EBay Software Foundation
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 : Ashwin Raveendran
10 package org.opendaylight.ovsdb.integrationtest.ovsdbclient;
12 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
14 import com.google.common.collect.ImmutableMap;
15 import com.google.common.collect.Lists;
16 import com.google.common.collect.Sets;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.io.IOException;
19 import java.util.List;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.TimeoutException;
24 import org.junit.After;
25 import org.junit.Assert;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.opendaylight.ovsdb.lib.MonitorCallBack;
30 import org.opendaylight.ovsdb.lib.OvsdbClient;
31 import org.opendaylight.ovsdb.lib.it.LibraryIntegrationTestBase;
32 import org.opendaylight.ovsdb.lib.it.LibraryIntegrationTestUtils;
33 import org.opendaylight.ovsdb.lib.message.MonitorRequest;
34 import org.opendaylight.ovsdb.lib.message.MonitorRequestBuilder;
35 import org.opendaylight.ovsdb.lib.message.MonitorSelect;
36 import org.opendaylight.ovsdb.lib.message.TableUpdate;
37 import org.opendaylight.ovsdb.lib.message.TableUpdates;
38 import org.opendaylight.ovsdb.lib.notation.Column;
39 import org.opendaylight.ovsdb.lib.notation.Mutator;
40 import org.opendaylight.ovsdb.lib.notation.Row;
41 import org.opendaylight.ovsdb.lib.notation.UUID;
42 import org.opendaylight.ovsdb.lib.operations.OperationResult;
43 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
44 import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
45 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
46 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
47 import org.opendaylight.ovsdb.lib.schema.TableSchema;
48 import org.ops4j.pax.exam.junit.PaxExam;
49 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
50 import org.ops4j.pax.exam.spi.reactors.PerSuite;
52 @RunWith(PaxExam.class)
53 @ExamReactorStrategy(PerSuite.class)
54 public class OvsdbClientTestIT extends LibraryIntegrationTestBase {
57 DatabaseSchema dbSchema = null;
58 static String testBridgeName = "br-test";
59 static UUID testBridgeUuid = null;
62 * Test general OVSDB transactions (viz., insert, select, update,
63 * mutate, comment, delete, where, commit) as well as the special
64 * transactions (viz., abort and assert)
67 public void testTransact() throws IOException, InterruptedException, ExecutionException {
68 Assert.assertNotNull(dbSchema);
69 TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
70 ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
72 createBridgeTransaction();
78 * Test OVS monitor request and reply, with and without specific column filters,
79 * for the Bridge table in the OVSDB. The setup involves creating a test bridge with 5
80 * flood_vlans and 2 key-value pairs, and monitoring the DB update.
83 public void testMonitorRequest() throws ExecutionException, InterruptedException, IOException {
84 Assert.assertNotNull(dbSchema);
85 // Create Test Bridge before testing the Monitor operation
86 createBridgeTransaction();
87 sendBridgeMonitorRequest(true); // Test monitor request with Column filters
88 sendBridgeMonitorRequest(false); // Test monitor request without filters
91 public void sendBridgeMonitorRequest(boolean filter) throws ExecutionException, InterruptedException, IOException {
92 Assert.assertNotNull(dbSchema);
93 GenericTableSchema bridge = dbSchema.table("Bridge", GenericTableSchema.class);
95 List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
96 ColumnSchema<GenericTableSchema, Set<Integer>> flood_vlans = bridge.multiValuedColumn("flood_vlans", Integer.class);
97 ColumnSchema<GenericTableSchema, Map<String, String>> externalIds = bridge.multiValuedColumn("external_ids", String.class, String.class);
98 ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
99 MonitorRequestBuilder<GenericTableSchema> builder = MonitorRequestBuilder.builder(bridge);
101 builder.addColumn(bridge.column("name"))
102 .addColumn(bridge.column("fail_mode", String.class))
103 .addColumn(flood_vlans)
104 .addColumn(externalIds);
106 monitorRequests.add(builder.with(new MonitorSelect(true, true, true, true))
109 final List<Object> results = Lists.newArrayList();
111 TableUpdates updates = ovs.monitor(dbSchema, monitorRequests, new MonitorCallBack() {
113 public void update(TableUpdates result, DatabaseSchema dbSchema) {
115 System.out.println("result = " + result);
119 public void exception(Throwable t) {
121 System.out.println("t = " + t);
124 if (updates != null) {
125 results.add(updates);
127 for (int i = 0; i < 3 ; i++) { //wait 3 seconds to get a result
128 System.out.println("waiting on monitor response for Bridge Table...");
129 if (!results.isEmpty()) {
135 Assert.assertTrue(!results.isEmpty());
136 Object result = results.get(0);
137 Assert.assertTrue(result instanceof TableUpdates);
138 updates = (TableUpdates) result;
139 TableUpdate<GenericTableSchema> update = updates.getUpdate(bridge);
140 Assert.assertTrue(update.getRows().size() > 0);
141 for (UUID uuid : update.getRows().keySet()) {
142 Row<GenericTableSchema> aNew = update.getNew(uuid);
143 if (!aNew.getColumn(name).getData().equals(testBridgeName)) {
147 Assert.assertEquals(builder.getColumns().size(), aNew.getColumns().size());
149 // As per RFC7047, Section 4.1.5 : If "columns" is omitted, all columns in the table, except for "_uuid", are monitored.
150 Assert.assertEquals(bridge.getColumns().size() - 1, aNew.getColumns().size());
152 for (Column<GenericTableSchema, ?> column: aNew.getColumns()) {
153 if (column.getSchema().equals(flood_vlans)) {
154 // Test for the 5 flood_vlans inserted in Bridge br-test in createBridgeTransaction
155 Set<Integer> data = column.getData(flood_vlans);
156 Assert.assertNotNull(data);
157 Assert.assertTrue(!data.isEmpty());
158 Assert.assertEquals(5, data.size());
159 } else if (column.getSchema().equals(externalIds)) {
160 // Test for the {"key", "value"} external_ids inserted in Bridge br-test in createBridgeTransaction
161 Map<String, String> data = column.getData(externalIds);
162 Assert.assertNotNull(data);
163 Assert.assertNotNull(data.get("key"));
164 Assert.assertEquals("value", data.get("key"));
165 // Test for {"key2", "value2"} external_ids mutation-inserted in Bridge br-test in createBridgeTransaction
166 Assert.assertNotNull(data.get("key2"));
167 Assert.assertEquals("value2", data.get("key2"));
172 Assert.fail("Bridge being monitored :"+testBridgeName+" Not found");
176 * TODO : selectOpenVSwitchTableUuid method isn't working as expected due to the Jackson
177 * parsing challenges on the Row object returned by the Select operation.
179 private UUID selectOpenVSwitchTableUuid() throws ExecutionException, InterruptedException {
180 Assert.assertNotNull(dbSchema);
181 GenericTableSchema ovsTable = dbSchema.table("Open_vSwitch", GenericTableSchema.class);
183 List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
184 ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
186 List<OperationResult> results = ovs.transactBuilder(dbSchema)
187 .add(op.select(ovsTable)
192 Assert.assertTrue(!results.isEmpty());
193 OperationResult result = results.get(0);
194 List<Row<GenericTableSchema>> rows = result.getRows();
195 Row<GenericTableSchema> ovsTableRow = rows.get(0);
196 return ovsTableRow.getColumn(_uuid).getData();
199 private void createBridgeTransaction() throws IOException, InterruptedException, ExecutionException {
200 Assert.assertNotNull(dbSchema);
201 TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
202 GenericTableSchema ovsTable = dbSchema.table("Open_vSwitch", GenericTableSchema.class);
204 ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
205 ColumnSchema<GenericTableSchema, String> fail_mode = bridge.column("fail_mode", String.class);
206 ColumnSchema<GenericTableSchema, Set<Integer>> flood_vlans = bridge.multiValuedColumn("flood_vlans", Integer.class);
207 ColumnSchema<GenericTableSchema, Map<String, String>> externalIds = bridge.multiValuedColumn("external_ids", String.class, String.class);
208 ColumnSchema<GenericTableSchema, Set<UUID>> bridges = ovsTable.multiValuedColumn("bridges", UUID.class);
209 ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
211 String namedUuid = "br_test";
212 int insertOperationIndex = 0;
213 UUID parentTable = selectOpenVSwitchTableUuid();
214 TransactionBuilder transactionBuilder = ovs.transactBuilder(dbSchema)
216 * Make sure that the position of insert operation matches the insertOperationIndex.
217 * This will be used later when the Results are processed.
219 .add(op.insert(bridge)
221 .value(name, testBridgeName)
222 .value(flood_vlans, Sets.newHashSet(100, 101, 4001))
223 .value(externalIds, ImmutableMap.of("key","value")))
224 .add(op.comment("Inserting Bridge br-int"))
225 .add(op.update(bridge)
226 .set(fail_mode, "secure")
227 .where(name.opEqual(testBridgeName))
229 .add(op.select(bridge)
232 .where(name.opEqual(testBridgeName))
234 .add(op.mutate(bridge)
235 .addMutation(flood_vlans, Mutator.INSERT, Sets.newHashSet(200,400))
236 .where(name.opEqual(testBridgeName))
238 .add(op.mutate(bridge)
239 .addMutation(externalIds, Mutator.INSERT, ImmutableMap.of("key2","value2"))
240 .where(name.opEqual(testBridgeName))
242 .add(op.mutate(ovsTable)
243 .addMutation(bridges, Mutator.INSERT, Sets.newHashSet(new UUID(namedUuid)))
244 .where(_uuid.opEqual(parentTable))
246 .add(op.commit(true));
248 ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
249 List<OperationResult> operationResults = results.get();
250 Assert.assertFalse(operationResults.isEmpty());
251 // Check if Results matches the number of operations in transaction
252 Assert.assertEquals(transactionBuilder.getOperations().size(), operationResults.size());
253 System.out.println("Insert & Update operation results = " + operationResults);
254 for (OperationResult result : operationResults) {
255 Assert.assertNull(result.getError());
257 testBridgeUuid = operationResults.get(insertOperationIndex).getUuid();
260 private void assertTransaction() throws InterruptedException, ExecutionException {
261 Assert.assertNotNull(dbSchema);
262 TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
263 ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
266 * Adding a separate Assert operation in a transaction. Lets not mix this with other
267 * valid transactions as above.
269 ListenableFuture<List<OperationResult>> results = ovs.transactBuilder(dbSchema)
270 .add(op.delete(bridge)
271 .where(name.opEqual(testBridgeName))
273 .add(op.assertion("Assert12345")) // Failing intentionally
276 List<OperationResult> operationResults = results.get();
277 Assert.assertFalse(operationResults.isEmpty());
278 /* Testing for an Assertion Error */
279 Assert.assertFalse(operationResults.get(1).getError() == null);
280 System.out.println("Assert operation results = " + operationResults);
283 private void abortTransaction() throws InterruptedException, ExecutionException {
284 Assert.assertNotNull(dbSchema);
285 TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
286 ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
289 * Adding a separate Abort operation in a transaction. Lets not mix this with other
290 * valid transactions as above.
292 ListenableFuture<List<OperationResult>> results = ovs.transactBuilder(dbSchema)
293 .add(op.delete(bridge)
294 .where(name.opEqual(testBridgeName))
299 List<OperationResult> operationResults = results.get();
300 Assert.assertFalse(operationResults.isEmpty());
301 /* Testing for Abort Error */
302 Assert.assertFalse(operationResults.get(1).getError() == null);
303 System.out.println("Abort operation results = " + operationResults);
306 public void testGetDBs() throws ExecutionException, InterruptedException {
307 ListenableFuture<List<String>> databases = ovs.getDatabases();
308 List<String> dbNames = databases.get();
309 Assert.assertNotNull(dbNames);
310 boolean hasOpenVswitchSchema = false;
311 for(String dbName : dbNames) {
312 if (dbName.equals(LibraryIntegrationTestUtils.OPEN_VSWITCH_SCHEMA)) {
313 hasOpenVswitchSchema = true;
317 Assert.assertTrue(LibraryIntegrationTestUtils.OPEN_VSWITCH_SCHEMA
318 + " schema is not supported by the switch", hasOpenVswitchSchema);
322 public void setUp() throws IOException, ExecutionException, InterruptedException, TimeoutException {
327 ovs = LibraryIntegrationTestUtils.getTestConnection(this);
328 System.out.println("Connection Info :" + ovs.getConnectionInfo().toString());
330 dbSchema = ovs.getSchema(LibraryIntegrationTestUtils.OPEN_VSWITCH_SCHEMA).get();
334 public void tearDown() throws InterruptedException, ExecutionException {
335 if (dbSchema == null) {
338 TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
339 ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
340 GenericTableSchema ovsTable = dbSchema.table("Open_vSwitch", GenericTableSchema.class);
341 ColumnSchema<GenericTableSchema, Set<UUID>> bridges = ovsTable.multiValuedColumn("bridges", UUID.class);
342 ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
343 UUID parentTable = selectOpenVSwitchTableUuid();
345 ListenableFuture<List<OperationResult>> results = ovs.transactBuilder(dbSchema)
346 .add(op.delete(bridge)
347 .where(name.opEqual(testBridgeName))
349 .add(op.mutate(ovsTable)
350 .addMutation(bridges, Mutator.DELETE, Sets.newHashSet(testBridgeUuid))
351 .where(_uuid.opEqual(parentTable))
353 .add(op.commit(true))
356 List<OperationResult> operationResults = results.get();
357 System.out.println("Delete operation results = " + operationResults);