2 * Copyright © 2015 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
9 package org.opendaylight.ovsdb.lib.it;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.junit.Assume.assumeTrue;
17 import static org.ops4j.pax.exam.CoreOptions.composite;
18 import static org.ops4j.pax.exam.CoreOptions.maven;
19 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties;
20 import static org.ops4j.pax.exam.CoreOptions.vmOption;
21 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
22 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
24 import com.google.common.collect.Lists;
25 import com.google.common.util.concurrent.ListenableFuture;
26 import java.io.IOException;
27 import java.util.HashMap;
28 import java.util.List;
31 import java.util.concurrent.ExecutionException;
32 import java.util.concurrent.atomic.AtomicBoolean;
33 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
34 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
35 import org.opendaylight.ovsdb.lib.MonitorCallBack;
36 import org.opendaylight.ovsdb.lib.OvsdbClient;
37 import org.opendaylight.ovsdb.lib.message.MonitorRequest;
38 import org.opendaylight.ovsdb.lib.message.MonitorRequestBuilder;
39 import org.opendaylight.ovsdb.lib.message.MonitorSelect;
40 import org.opendaylight.ovsdb.lib.message.TableUpdate;
41 import org.opendaylight.ovsdb.lib.message.TableUpdates;
42 import org.opendaylight.ovsdb.lib.notation.Row;
43 import org.opendaylight.ovsdb.lib.notation.UUID;
44 import org.opendaylight.ovsdb.lib.notation.Version;
45 import org.opendaylight.ovsdb.lib.operations.OperationResult;
46 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
47 import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
48 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
49 import org.opendaylight.ovsdb.lib.schema.TableSchema;
50 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
51 import org.ops4j.pax.exam.Configuration;
52 import org.ops4j.pax.exam.Option;
53 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
54 import org.ops4j.pax.exam.options.MavenUrlReference;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
59 * Base class for library IT.
61 public abstract class LibraryIntegrationTestBase extends AbstractMdsalTestBase {
62 private static final Logger LOG = LoggerFactory.getLogger(LibraryIntegrationTestBase.class);
63 protected static final String ASSERT_TRANS_ERROR = "Transaction should not have errors";
64 protected static final String ASSERT_TRANS_RESULT_EMPTY = "Transaction should not be empty";
65 protected static final String ASSERT_TRANS_OPERATION_COUNT = "Transaction should match number of operations";
66 protected static final String ASSERT_TRANS_UUID = "Transaction UUID should not be null";
67 protected static Version schemaVersion;
68 private static boolean schemaSupported = false;
69 protected static OvsdbClient ovsdbClient;
70 private static Map<String, Map<UUID, Row>> tableCache = new HashMap<>();
71 private static boolean monitorReady = false;
74 protected static Map<String, Map<UUID, Row>> getTableCache() {
78 protected OvsdbClient getClient () {
82 protected static DatabaseSchema dbSchema;
83 protected DatabaseSchema getDbSchema () {
87 private static AtomicBoolean setup = new AtomicBoolean(false);
88 protected static boolean getSetup() {
92 protected static void setSetup(boolean setup) {
93 LibraryIntegrationTestBase.setup.set(setup);
97 public String getModuleName() {
102 public String getInstanceName() {
103 return "library-default";
107 public MavenUrlReference getFeatureRepo() {
109 .groupId("org.opendaylight.ovsdb")
110 .artifactId("library-features")
111 .classifier("features")
113 .versionAsInProject();
117 public String getFeatureName() {
118 return "odl-ovsdb-library";
123 public Option[] config() {
124 Option[] parentOptions = super.config();
125 Option[] propertiesOptions = getPropertiesOptions();
126 Option[] otherOptions = getOtherOptions();
127 Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
128 System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
129 System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
130 System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
131 otherOptions.length);
135 private Option[] getOtherOptions() {
136 return new Option[] {
137 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
142 public Option[] getPropertiesOptions() {
143 return new Option[] {
144 propagateSystemProperties(
145 LibraryIntegrationTestUtils.SERVER_IPADDRESS,
146 LibraryIntegrationTestUtils.SERVER_PORT,
147 LibraryIntegrationTestUtils.CONNECTION_TYPE),
152 public Option getLoggingOption() {
153 Option option = editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
154 logConfiguration(getClass()),
155 LogLevelOption.LogLevel.INFO.name());
156 option = composite(option, super.getLoggingOption());
160 protected BindingAwareBroker.ProviderContext getProviderContext() {
161 BindingAwareBroker.ProviderContext providerContext = null;
162 for (int i=0; i < 60; i++) {
163 LOG.info("Looking for ProviderContext, try {}", i);
164 providerContext = getSession();
165 if (providerContext != null) {
170 } catch (InterruptedException e) {
171 LOG.warn("Interrupted while waiting for provider context", e);
175 assertNotNull("providercontext should not be null", providerContext);
176 /* One more second to let the provider finish initialization */
179 } catch (InterruptedException e) {
180 LOG.warn("Interrupted while waiting for other provider", e);
182 return providerContext;
185 public boolean checkSchema (String schema) {
186 if (schemaSupported) {
187 LOG.info("Schema ({}) is supported", schema);
191 ovsdbClient = LibraryIntegrationTestUtils.getTestConnection(this);
192 assertNotNull("Invalid Client. Check connection params", ovsdbClient);
193 if (isSchemaSupported(ovsdbClient, schema)) {
194 dbSchema = ovsdbClient.getSchema(schema).get();
195 assertNotNull(dbSchema);
196 LOG.info("{} schema in {} with tables: {}",
197 schema, ovsdbClient.getConnectionInfo(), dbSchema.getTables());
198 schemaSupported = true;
201 } catch (Exception e) {
202 fail("Exception: " + e);
205 LOG.info("Schema ({}) is not supported", schema);
209 public boolean isSchemaSupported (String schema) throws ExecutionException,
210 InterruptedException {
211 return isSchemaSupported(ovsdbClient, schema);
214 public boolean isSchemaSupported (OvsdbClient client, String schema) throws ExecutionException, InterruptedException {
215 ListenableFuture<List<String>> databases = client.getDatabases();
216 List<String> dbNames = databases.get();
217 assertNotNull(dbNames);
218 return dbNames.contains(schema);
222 * As per RFC 7047, section 4.1.5, if a Monitor request is sent without any columns, the update response will not include
224 * ----------------------------------------------------------------------------------------------------------------------------------
225 * Each <monitor-request> specifies one or more columns and the manner in which the columns (or the entire table) are to be monitored.
226 * The "columns" member specifies the columns whose values are monitored. It MUST NOT contain duplicates.
227 * If "columns" is omitted, all columns in the table, except for "_uuid", are monitored.
228 * ----------------------------------------------------------------------------------------------------------------------------------
229 * In order to overcome this limitation, this method
231 * @return MonitorRequest that includes all the Bridge Columns including _uuid
233 public <T extends TypedBaseTable<GenericTableSchema>> MonitorRequest getAllColumnsMonitorRequest (Class <T> klazz) {
234 TypedBaseTable<GenericTableSchema> table = getClient().createTypedRowWrapper(klazz);
235 GenericTableSchema tableSchema = table.getSchema();
236 Set<String> columns = tableSchema.getColumns();
237 MonitorRequestBuilder<GenericTableSchema> bridgeBuilder = MonitorRequestBuilder.builder(table.getSchema());
238 for (String column : columns) {
239 bridgeBuilder.addColumn(column);
241 return bridgeBuilder.with(new MonitorSelect(true, true, true, true)).build();
244 public <T extends TableSchema<T>> MonitorRequest getAllColumnsMonitorRequest (T tableSchema) {
245 Set<String> columns = tableSchema.getColumns();
246 MonitorRequestBuilder<T> monitorBuilder = MonitorRequestBuilder.builder(tableSchema);
247 for (String column : columns) {
248 monitorBuilder.addColumn(column);
250 return monitorBuilder.with(new MonitorSelect(true, true, true, true)).build();
253 public boolean monitorTables () throws ExecutionException, InterruptedException, IOException {
255 LOG.info("Monitoring is already initialized.");
259 assertNotNull(getDbSchema());
261 List<MonitorRequest> monitorRequests = Lists.newArrayList();
262 Set<String> tables = getDbSchema().getTables();
263 assertNotNull("ovsdb tables should not be null", tables);
265 for (String tableName : tables) {
266 GenericTableSchema tableSchema = getDbSchema().table(tableName, GenericTableSchema.class);
267 monitorRequests.add(this.getAllColumnsMonitorRequest(tableSchema));
269 TableUpdates updates = getClient().monitor(getDbSchema(), monitorRequests, new UpdateMonitor());
270 assertNotNull(updates);
271 this.updateTableCache(updates);
274 LOG.info("Monitoring is initialized.");
278 @SuppressWarnings("unchecked")
279 protected void updateTableCache(TableUpdates updates) {
280 for (String tableName : updates.getUpdates().keySet()) {
281 Map<UUID, Row> tUpdate = getTableCache().get(tableName);
282 TableUpdate update = updates.getUpdates().get(tableName);
283 for (UUID uuid : (Set<UUID>)update.getRows().keySet()) {
284 if (update.getNew(uuid) != null) {
285 if (tUpdate == null) {
286 tUpdate = new HashMap<>();
287 getTableCache().put(tableName, tUpdate);
289 tUpdate.put(uuid, update.getNew(uuid));
291 tUpdate.remove(uuid);
297 public List<OperationResult> executeTransaction (TransactionBuilder transactionBuilder, String text)
298 throws ExecutionException, InterruptedException {
299 ListenableFuture<List<OperationResult>> results = transactionBuilder.execute();
300 List<OperationResult> operationResults = results.get();
301 LOG.info("{}: {}", text, operationResults);
302 org.junit.Assert.assertFalse(ASSERT_TRANS_RESULT_EMPTY, operationResults.isEmpty());
303 assertEquals(ASSERT_TRANS_OPERATION_COUNT, transactionBuilder.getOperations().size(), operationResults.size());
304 for (OperationResult result : operationResults) {
305 assertNull(ASSERT_TRANS_ERROR, result.getError());
307 //Thread.sleep(500); // Wait for a few seconds to ensure the cache updates
308 return operationResults;
311 public void setup() throws Exception {
313 LOG.info("Skipping setUp, already initialized");
319 } catch (Exception e) {
320 LOG.warn("Failed to setup test", e);
321 fail("Failed to setup test: " + e);
324 assertNotNull("ProviderContext was not found", getProviderContext());
325 if (schema.equals(LibraryIntegrationTestUtils.OPEN_VSWITCH)) {
326 assertTrue(schema + " is required.", checkSchema(schema));
328 assumeTrue(schema + " is required.", checkSchema(schema));
330 schemaVersion = getClient().getDatabaseSchema(schema).getVersion();
331 LOG.info("{} schema version = {}", schema, schemaVersion);
332 assertTrue("Failed to monitor tables", monitorTables());
336 public void setup2() throws Exception {
338 LOG.info("Skipping setUp, already initialized");
344 } catch (Exception e) {
345 LOG.warn("Failed to setup test", e);
346 fail("Failed to setup test: " + e);
349 assertNotNull("ProviderContext was not found", getProviderContext());
353 private class UpdateMonitor implements MonitorCallBack {
355 public void update(TableUpdates result, DatabaseSchema dbSchema) {
356 updateTableCache(result);
360 public void exception(Throwable t) {
361 LOG.error("Exception t = " + t);