2 * Copyright (c) 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
8 package org.opendaylight.ovsdb.southbound.it;
10 import static org.junit.Assert.assertFalse;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
15 import static org.ops4j.pax.exam.CoreOptions.maven;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
18 import com.google.common.base.Optional;
19 import com.google.common.collect.ObjectArrays;
20 import com.google.common.util.concurrent.CheckedFuture;
21 import com.google.common.util.concurrent.FutureCallback;
22 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture;
25 import java.net.InetAddress;
26 import java.net.UnknownHostException;
27 import java.util.Properties;
28 import java.util.concurrent.ExecutionException;
30 import javax.inject.Inject;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
37 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
38 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
41 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
42 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
43 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
44 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.ops4j.pax.exam.Configuration;
55 import org.ops4j.pax.exam.Option;
56 import org.ops4j.pax.exam.junit.PaxExam;
57 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
58 import org.ops4j.pax.exam.options.MavenUrlReference;
59 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
60 import org.ops4j.pax.exam.spi.reactors.PerClass;
61 import org.osgi.framework.BundleContext;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
66 * Integration tests for southbound-impl
68 * @author Sam Hague (shague@redhat.com)
70 @RunWith(PaxExam.class)
71 @ExamReactorStrategy(PerClass.class)
72 public class SouthboundIT extends AbstractMdsalTestBase {
73 private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
74 private static Boolean writeStatus = false;
75 private static Boolean readStatus = false;
76 private static Boolean deleteStatus = false;
77 private static DataBroker dataBroker = null;
78 private static String addressStr;
79 private static String portStr;
80 private static String connectionType;
81 private static Boolean setup = false;
82 private static MdsalUtils mdsalUtils = null;
85 private BundleContext bc;
88 public Option[] config() {
89 return super.config();
93 public String getModuleName() {
94 return "southbound-impl";
98 public String getInstanceName() {
99 return "southbound-default";
103 public MavenUrlReference getFeatureRepo() {
105 .groupId("org.opendaylight.ovsdb")
106 .artifactId("southbound-features")
107 .classifier("features")
109 .versionAsInProject();
113 public String getFeatureName() {
114 return "odl-ovsdb-southbound-impl-ui";
117 protected String usage() {
118 return "Integration Test needs a valid connection configuration as follows :\n"
119 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
120 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
124 public Option[] getLoggingOptions() {
125 Option[] options = new Option[] {
126 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
127 "log4j.logger.org.opendaylight.ovsdb.southbound-impl",
128 LogLevelOption.LogLevel.DEBUG.name())
130 options = ObjectArrays.concat(options, super.getLoggingOptions(), Option.class);
135 public Option[] getPropertiesOptions() {
136 Properties props = new Properties(System.getProperties());
137 String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
138 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
139 String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
140 SouthboundITConstants.DEFAULT_SERVER_PORT);
141 String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
142 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
144 LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
145 connectionType, addressStr, portStr);
147 Option[] options = new Option[] {
148 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
149 SouthboundITConstants.SERVER_IPADDRESS, addressStr),
150 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
151 SouthboundITConstants.SERVER_PORT, portStr),
152 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
153 SouthboundITConstants.CONNECTION_TYPE, connectionType)
159 public void setUp() throws InterruptedException {
161 LOG.info("Skipping setUp, already initialized");
167 } catch (Exception e) {
170 //dataBroker = getSession().getSALService(DataBroker.class);
172 dataBroker = SouthboundProvider.getDb();
173 Assert.assertNotNull("db should not be null", dataBroker);
175 addressStr = bc.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
176 portStr = bc.getProperty(SouthboundITConstants.SERVER_PORT);
177 connectionType = bc.getProperty(SouthboundITConstants.CONNECTION_TYPE);
179 LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
180 connectionType, addressStr, portStr);
181 if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
182 if (addressStr == null) {
187 mdsalUtils = new MdsalUtils(dataBroker);
192 public void testPassiveNode() throws InterruptedException {
193 if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
194 //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
195 Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
200 public void testAddRemoveOvsdbNode() throws InterruptedException {
201 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
203 // Write OVSDB node to configuration
204 final ReadWriteTransaction configNodeTx = dataBroker.newReadWriteTransaction();
205 configNodeTx.put(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo),
206 SouthboundMapper.createNode(connectionInfo));
207 Futures.addCallback(configNodeTx.submit(), new FutureCallback<Void>() {
209 public void onSuccess(final Void result) {
210 LOG.info("success writing node to configuration: " + configNodeTx);
215 public void onFailure(final Throwable throwable) {
216 fail("failed writing node to configuration: " + configNodeTx);
222 assertTrue("Failed to write node to configuration", writeStatus);
224 // Read from operational to verify if the OVSDB node is connected
225 final ReadOnlyTransaction readNodeTx = dataBroker.newReadOnlyTransaction();
226 ListenableFuture<Optional<Node>> dataFuture = readNodeTx.read(
227 LogicalDatastoreType.OPERATIONAL, SouthboundMapper.createInstanceIdentifier(connectionInfo));
228 Futures.addCallback(dataFuture, new FutureCallback<Optional<Node>>() {
230 public void onSuccess(final Optional<Node> result) {
231 LOG.info("success reading node from operational: " + readNodeTx);
232 LOG.info("Optional result: {}", result);
233 if (result.isPresent()) {
234 LOG.info("node: {}", result.get());
240 public void onFailure(final Throwable throwable) {
241 fail("failed reading node from operational: " + readNodeTx);
247 assertTrue("Failed to read node from operational", readStatus);
249 // Delete OVSDB node from configuration
250 final ReadWriteTransaction deleteNodeTx = dataBroker.newReadWriteTransaction();
251 deleteNodeTx.delete(LogicalDatastoreType.CONFIGURATION,
252 SouthboundMapper.createInstanceIdentifier(connectionInfo));
253 Futures.addCallback(deleteNodeTx.submit(), new FutureCallback<Void>() {
255 public void onSuccess(final Void result) {
256 LOG.info("success deleting node from configuration: " + deleteNodeTx);
261 public void onFailure(final Throwable throwable) {
262 fail("failed deleting node from configuration: " + deleteNodeTx);
268 assertTrue("Failed to delete node from configuration", deleteStatus);
270 // Read from operational to verify if the OVSDB node is disconnected
271 // Similar to the earlier read, but this time synchronously
272 final ReadOnlyTransaction readNodeTx2 = dataBroker.newReadOnlyTransaction();
273 Optional<Node> node = Optional.absent();
275 node = readNodeTx2.read(LogicalDatastoreType.OPERATIONAL,
276 SouthboundMapper.createInstanceIdentifier(connectionInfo)).checkedGet();
277 assertFalse("Failed to delete node from configuration and node is still connected",
279 } catch (final ReadFailedException e) {
280 LOG.debug("Read Operational/DS for Node fail! {}",
281 SouthboundMapper.createInstanceIdentifier(connectionInfo), e);
282 fail("failed reading node from operational: " + readNodeTx2 + e);
287 public void testAddRemoveOvsdbNode2() throws InterruptedException {
288 addNode("192.168.120.31", "6640");
290 Node node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
292 LOG.info("Connected node: {}", node);
293 deleteNode("192.168.120.31", "6640");
295 node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
299 private ConnectionInfo getConnectionInfo(String addressStr, String portStr) {
300 InetAddress inetAddress = null;
302 inetAddress = InetAddress.getByName(addressStr);
303 } catch (UnknownHostException e) {
304 fail("Could not allocate InetAddress: " + e);
307 IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
308 PortNumber port = new PortNumber(Integer.parseInt(portStr));
310 return new ConnectionInfoBuilder()
311 .setRemoteIp(address)
316 private void addNode(String addressStr, String portStr) {
317 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
319 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
320 rwTx.put(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo),
321 SouthboundMapper.createNode(connectionInfo));
322 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
324 commitFuture.checkedGet();
325 } catch (TransactionCommitFailedException e) {
326 fail("Failed transaction: " + rwTx + e);
330 private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
331 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
333 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
334 Optional<Node> node = Optional.absent();
335 CheckedFuture<Optional<Node>, ReadFailedException> read;
336 read = rwTx.read(type, SouthboundMapper.createInstanceIdentifier(connectionInfo));
338 node = read.checkedGet();
339 if (node.isPresent()) {
342 } catch (ReadFailedException e) {
343 fail("Failed transaction: " + rwTx + e);
349 private void deleteNode(String addressStr, String portStr) {
350 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
352 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
353 rwTx.delete(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo));
354 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
357 } catch (ExecutionException | InterruptedException e) {
358 fail("Failed transaction: " + rwTx + e);
362 private NetworkTopology readNetworkTopology(LogicalDatastoreType type) {
363 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
365 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
366 Optional<NetworkTopology> optional = Optional.absent();
367 CheckedFuture<Optional<NetworkTopology>, ReadFailedException> read;
368 read = rwTx.read(type, InstanceIdentifier.create(NetworkTopology.class));
370 optional = read.checkedGet();
371 if (optional.isPresent()) {
372 return optional.get();
374 } catch (ReadFailedException e) {
375 fail("Failed transaction: " + rwTx + e);
382 public void testNetworkTopology() throws InterruptedException {
383 NetworkTopology networkTopology = MdsalUtils.readTransaction(LogicalDatastoreType.CONFIGURATION,
384 InstanceIdentifier.create(NetworkTopology.class));
385 Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
388 networkTopology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL,
389 InstanceIdentifier.create(NetworkTopology.class));
390 Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
395 public void testOvsdbTopology() throws InterruptedException {
396 InstanceIdentifier<Topology> path = InstanceIdentifier
397 .create(NetworkTopology.class)
398 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
400 Topology topology = MdsalUtils.readTransaction(LogicalDatastoreType.CONFIGURATION, path);
401 Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
404 topology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL, path);
406 Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,