Resolved the Serialization and Deserialization issues for MultiValued Columns with...
[ovsdb.git] / library / src / test / java / org / opendaylight / ovsdb / lib / OvsDBClientTestIT.java
1 /*
2  * Copyright (C) 2014 EBay Software Foundation
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 : Ashwin Raveendran
9  */
10 package org.opendaylight.ovsdb.lib;
11
12 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
13
14 import java.io.IOException;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.ExecutorService;
20 import java.util.concurrent.Executors;
21
22 import junit.framework.Assert;
23
24 import org.junit.After;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.opendaylight.ovsdb.lib.message.MonitorRequest;
28 import org.opendaylight.ovsdb.lib.message.MonitorRequestBuilder;
29 import org.opendaylight.ovsdb.lib.message.MonitorSelect;
30 import org.opendaylight.ovsdb.lib.message.OvsdbRPC;
31 import org.opendaylight.ovsdb.lib.message.TableUpdate;
32 import org.opendaylight.ovsdb.lib.message.TableUpdates;
33 import org.opendaylight.ovsdb.lib.message.UpdateNotification;
34 import org.opendaylight.ovsdb.lib.notation.Column;
35 import org.opendaylight.ovsdb.lib.notation.Mutator;
36 import org.opendaylight.ovsdb.lib.notation.Row;
37 import org.opendaylight.ovsdb.lib.notation.UUID;
38 import org.opendaylight.ovsdb.lib.operations.OperationResult;
39 import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
40 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
41 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
42 import org.opendaylight.ovsdb.lib.schema.TableSchema;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import com.google.common.collect.ImmutableMap;
47 import com.google.common.collect.Lists;
48 import com.google.common.collect.Maps;
49 import com.google.common.collect.Sets;
50 import com.google.common.util.concurrent.ListenableFuture;
51
52
53 public class OvsDBClientTestIT extends OvsdbTestBase {
54     Logger logger = LoggerFactory.getLogger(OvsDBClientTestIT.class);
55
56     OvsDBClientImpl ovs;
57     DatabaseSchema dbSchema = null;
58     static String testBridgeName = "br-test";
59     static UUID testBridgeUuid = null;
60     @Test
61     public void testTransact() throws IOException, InterruptedException, ExecutionException {
62         Assert.assertNotNull(dbSchema);
63         TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
64         ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
65
66         createBridgeTransaction();
67         abortTransaction();
68         assertTransaction();
69     }
70
71     @Test
72     public void testMonitorRequest() throws ExecutionException, InterruptedException, IOException {
73         Assert.assertNotNull(dbSchema);
74         // Create Test Bridge before testing the Monitor operation
75         createBridgeTransaction();
76
77         GenericTableSchema bridge = dbSchema.table("Bridge", GenericTableSchema.class);
78
79         List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
80         ColumnSchema<GenericTableSchema, Set<Integer>> flood_vlans = bridge.multiValuedColumn("flood_vlans", Integer.class);
81         ColumnSchema<GenericTableSchema, Map<String, String>> externalIds = bridge.multiValuedColumn("external_ids", String.class, String.class);
82         monitorRequests.add(
83                 MonitorRequestBuilder.builder(bridge)
84                         .addColumn(bridge.column("name"))
85                         .addColumn(bridge.column("fail_mode", String.class))
86                         .addColumn(flood_vlans)
87                         .addColumn(externalIds)
88                         .with(new MonitorSelect(true, true, true, true))
89                         .build());
90
91         final List<Object> results = Lists.newArrayList();
92
93         MonitorHandle monitor = ovs.monitor(dbSchema, monitorRequests, new MonitorCallBack() {
94             @Override
95             public void update(TableUpdates result) {
96                 results.add(result);
97                 System.out.println("result = " + result);
98             }
99
100             @Override
101             public void exception(Throwable t) {
102                 results.add(t);
103                 System.out.println("t = " + t);
104             }
105         });
106
107         for (int i = 0; i < 3 ; i++) { //wait 3 seconds to get a result
108             System.out.println("waiting on monitor response for Bridge Table...");
109             if (!results.isEmpty()) break;
110             Thread.sleep(1000);
111         }
112
113         Assert.assertTrue(!results.isEmpty());
114         Object result = results.get(0);
115         Assert.assertTrue(result instanceof TableUpdates);
116         TableUpdates updates = (TableUpdates) result;
117         TableUpdate<GenericTableSchema> update = updates.getUpdate(bridge);
118         Row<GenericTableSchema> aNew = update.getNew();
119         for (Column<GenericTableSchema, ?> column: aNew.getColumns()) {
120             if (column.getSchema().equals(flood_vlans)) {
121                 // Test for the 5 flood_vlans inserted in Bridge br-test in createBridgeTransaction
122                 Set<Integer> data = column.getData(flood_vlans);
123                 Assert.assertTrue(!data.isEmpty());
124                 Assert.assertEquals(5, data.size());
125             } else if (column.getSchema().equals(externalIds)) {
126                 // Test for the {"key", "value"} external_ids inserted in Bridge br-test in createBridgeTransaction
127                 Map<String, String> data = column.getData(externalIds);
128                 Assert.assertNotNull(data.get("key"));
129                 Assert.assertEquals("value", data.get("key"));
130             }
131         }
132     }
133
134     /*
135      * Ideally we should be using selectOpenVSwitchTableUuid() instead of this method.
136      * But Row.java needs some Jackson Jitsu to obtain the appropriate Row Json mapped to Java object
137      * for Select operation.
138      * Hence using the Monitor approach to obtain the uuid of the open_vSwitch table entry.
139      * Replace this method with selectOpenVSwitchTableUuid() once it is functional,
140      */
141     private UUID getOpenVSwitchTableUuid() throws ExecutionException, InterruptedException {
142         Assert.assertNotNull(dbSchema);
143         GenericTableSchema ovsTable = dbSchema.table("Open_vSwitch", GenericTableSchema.class);
144         List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
145         ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
146
147         monitorRequests.add(
148                 MonitorRequestBuilder.builder(ovsTable)
149                         .addColumn(_uuid)
150                         .with(new MonitorSelect(true, true, true, true))
151                         .build());
152
153         final List<Object> results = Lists.newArrayList();
154
155         MonitorHandle monitor = ovs.monitor(dbSchema, monitorRequests, new MonitorCallBack() {
156             @Override
157             public void update(TableUpdates result) {
158                 results.add(result);
159             }
160
161             @Override
162             public void exception(Throwable t) {
163                 results.add(t);
164                 System.out.println("t = " + t);
165             }
166         });
167
168         for (int i = 0; i < 3 ; i++) { //wait 5 seconds to get a result
169             System.out.println("waiting on monitor response for open_vSwtich Table...");
170             if (!results.isEmpty()) break;
171             Thread.sleep(1000);
172         }
173
174         Assert.assertTrue(!results.isEmpty());
175         Object result = results.get(0); // open_vSwitch table has just 1 row.
176         Assert.assertTrue(result instanceof TableUpdates);
177         TableUpdates updates = (TableUpdates) result;
178         TableUpdate<GenericTableSchema> update = updates.getUpdate(ovsTable);
179         return update.getUuid();
180     }
181
182     /*
183      * TODO : selectOpenVSwitchTableUuid method isn't working as expected due to the Jackson
184      * parsing challenges on the Row object returned by the Select operation.
185      */
186     private UUID selectOpenVSwitchTableUuid() throws ExecutionException, InterruptedException {
187         Assert.assertNotNull(dbSchema);
188         GenericTableSchema ovsTable = dbSchema.table("Open_vSwitch", GenericTableSchema.class);
189
190         List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
191         ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
192
193         List<OperationResult> results = ovs.transactBuilder()
194                .add(op.select(ovsTable)
195                       .column(_uuid))
196                       .execute()
197                       .get();
198
199         Assert.assertTrue(!results.isEmpty());
200         OperationResult result = results.get(0);
201         List<Row<GenericTableSchema>> rows = result.getRows();
202         Row<GenericTableSchema> ovsTableRow = rows.get(0);
203         return ovsTableRow.getColumn(_uuid).getData();
204     }
205
206     private void createBridgeTransaction() throws IOException, InterruptedException, ExecutionException {
207         Assert.assertNotNull(dbSchema);
208         TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
209         GenericTableSchema ovsTable = dbSchema.table("Open_vSwitch", GenericTableSchema.class);
210
211         ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
212         ColumnSchema<GenericTableSchema, String> fail_mode = bridge.column("fail_mode", String.class);
213         ColumnSchema<GenericTableSchema, Set<Integer>> flood_vlans = bridge.multiValuedColumn("flood_vlans", Integer.class);
214         ColumnSchema<GenericTableSchema, Map<String, String>> externalIds = bridge.multiValuedColumn("external_ids", String.class, String.class);
215         ColumnSchema<GenericTableSchema, Set<UUID>> bridges = ovsTable.multiValuedColumn("bridges", UUID.class);
216         ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
217
218         String namedUuid = "br_test";
219         int nOperations = 7;
220         int insertOperationIndex = 0;
221         UUID parentTable = getOpenVSwitchTableUuid();
222         ListenableFuture<List<OperationResult>> results = ovs.transactBuilder()
223                  /*
224                   * Make sure that the position of insert operation matches the insertOperationIndex.
225                   * This will be used later when the Results are processed.
226                   */
227                 .add(op.insert(bridge)
228                         .withId(namedUuid)
229                         .value(name, testBridgeName)
230                         .value(flood_vlans, Sets.newHashSet(100, 101, 4001))
231                         .value(externalIds, Maps.newHashMap(ImmutableMap.of("key","value"))))
232                 .add(op.comment("Inserting Bridge br-int"))
233                 .add(op.update(bridge)
234                         .set(fail_mode, "secure")
235                         .where(name.opEqual(testBridgeName))
236                         .build())
237                 .add(op.select(bridge)
238                         .column(name)
239                         .column(_uuid)
240                         .where(name.opEqual(testBridgeName))
241                         .build())
242                 .add(op.mutate(bridge)
243                         .addMutation(flood_vlans, Mutator.INSERT, Sets.newHashSet(200,400))
244                         .where(name.opEqual(testBridgeName))
245                         .build())
246                 .add(op.mutate(ovsTable)
247                         .addMutation(bridges, Mutator.INSERT, Sets.newHashSet(new UUID(namedUuid)))
248                         .where(_uuid.opEqual(parentTable))
249                         .build())
250                 .add(op.commit(true))
251                 .execute();
252
253         List<OperationResult> operationResults = results.get();
254         Assert.assertFalse(operationResults.isEmpty());
255         // Check if Results matches the number of operations in transaction
256         Assert.assertEquals(nOperations, operationResults.size());
257         System.out.println("Insert & Update operation results = " + operationResults);
258         testBridgeUuid = operationResults.get(insertOperationIndex).getUuid();
259     }
260
261     private void assertTransaction() throws InterruptedException, ExecutionException {
262         Assert.assertNotNull(dbSchema);
263         TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
264         ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
265
266         /*
267          * Adding a separate Assert operation in a transaction. Lets not mix this with other
268          * valid transactions as above.
269          */
270         ListenableFuture<List<OperationResult>> results = ovs.transactBuilder()
271                 .add(op.delete(bridge)
272                         .where(name.opEqual(testBridgeName))
273                         .build())
274                 .add(op.assertion("Assert12345")) // Failing intentionally
275                 .execute();
276
277         List<OperationResult> operationResults = results.get();
278         Assert.assertFalse(operationResults.isEmpty());
279         /* Testing for an Assertion Error */
280         Assert.assertFalse(operationResults.get(1).getError() == null);
281         System.out.println("Assert operation results = " + operationResults);
282     }
283
284     private void abortTransaction() throws InterruptedException, ExecutionException {
285         Assert.assertNotNull(dbSchema);
286         TableSchema<GenericTableSchema> bridge = dbSchema.table("Bridge", GenericTableSchema.class);
287         ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
288
289         /*
290          * Adding a separate Abort operation in a transaction. Lets not mix this with other
291          * valid transactions as above.
292          */
293         ListenableFuture<List<OperationResult>> results = ovs.transactBuilder()
294                 .add(op.delete(bridge)
295                         .where(name.opEqual(testBridgeName))
296                         .build())
297                 .add(op.abort())
298                 .execute();
299
300         List<OperationResult> operationResults = results.get();
301         Assert.assertFalse(operationResults.isEmpty());
302         /* Testing for Abort Error */
303         Assert.assertFalse(operationResults.get(1).getError() == null);
304         System.out.println("Abort operation results = " + operationResults);
305     }
306
307     public void testGetDBs() throws ExecutionException, InterruptedException {
308         ListenableFuture<List<String>> databases = ovs.getDatabases();
309         List<String> dbNames = databases.get();
310         Assert.assertNotNull(dbNames);
311         boolean hasOpenVswitchSchema = false;
312         for(String dbName : dbNames) {
313            if (dbName.equals(OPEN_VSWITCH_SCHEMA)) {
314                 hasOpenVswitchSchema = true;
315                 break;
316            }
317         }
318         Assert.assertTrue(OPEN_VSWITCH_SCHEMA+" schema is not supported by the switch", hasOpenVswitchSchema);
319     }
320
321     @Before
322     public  void setUp() throws IOException, ExecutionException, InterruptedException {
323         if (ovs != null) {
324             return;
325         }
326         OvsdbRPC rpc = getTestConnection();
327         if (rpc == null) {
328             System.out.println("Unable to Establish Test Connection");
329         }
330         ExecutorService executorService = Executors.newFixedThreadPool(3);
331         ovs = new OvsDBClientImpl(rpc, executorService);
332         testGetDBs();
333         dbSchema = ovs.getSchema(OPEN_VSWITCH_SCHEMA, true).get();
334     }
335
336     @After
337     public void tearDown() throws InterruptedException, ExecutionException {
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 = getOpenVSwitchTableUuid();
344
345         ListenableFuture<List<OperationResult>> results = ovs.transactBuilder()
346                 .add(op.delete(bridge)
347                         .where(name.opEqual(testBridgeName))
348                         .build())
349                 .add(op.mutate(ovsTable)
350                         .addMutation(bridges, Mutator.DELETE, Sets.newHashSet(testBridgeUuid))
351                         .where(_uuid.opEqual(parentTable))
352                         .build())
353                 .add(op.commit(true))
354                 .execute();
355
356         List<OperationResult> operationResults = results.get();
357         System.out.println("Delete operation results = " + operationResults);
358     }
359
360
361     @Override
362     public void update(Object node, UpdateNotification upadateNotification) {
363         // TODO Auto-generated method stub
364
365     }
366
367     @Override
368     public void locked(Object node, List<String> ids) {
369         // TODO Auto-generated method stub
370
371     }
372     @Override
373     public void stolen(Object node, List<String> ids) {
374         // TODO Auto-generated method stub
375
376     }
377 }