1 package org.opendaylight.ovsdb.southbound.it;
3 import static org.junit.Assert.assertFalse;
4 import static org.junit.Assert.assertNotNull;
5 import static org.junit.Assert.assertNull;
6 import static org.junit.Assert.assertTrue;
7 import static org.junit.Assert.fail;
8 import static org.ops4j.pax.exam.CoreOptions.maven;
9 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.net.InetAddress;
17 import java.net.UnknownHostException;
18 import java.util.Properties;
19 import java.util.concurrent.ExecutionException;
20 import javax.inject.Inject;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
29 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
30 import org.opendaylight.ovsdb.southbound.OvsdbClientKey;
31 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.ops4j.pax.exam.Configuration;
36 import org.ops4j.pax.exam.Option;
37 import org.ops4j.pax.exam.junit.PaxExam;
38 import org.ops4j.pax.exam.options.MavenUrlReference;
39 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
40 import org.ops4j.pax.exam.spi.reactors.PerClass;
41 import org.osgi.framework.BundleContext;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 @RunWith(PaxExam.class)
46 @ExamReactorStrategy(PerClass.class)
47 public class SouthboundIT extends AbstractMdsalTestBase {
48 private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
49 private static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
50 private static final String SERVER_PORT = "ovsdbserver.port";
51 private static final String CONNECTION_TYPE = "ovsdbserver.connection";
52 private static final String CONNECTION_TYPE_ACTIVE = "active";
53 private static final String CONNECTION_TYPE_PASSIVE = "passive";
54 private static final int CONNECTION_INIT_TIMEOUT = 10000;
55 private static final String DEFAULT_SERVER_IPADDRESS = "127.0.0.1";
56 private static final String DEFAULT_SERVER_PORT = "6640";
57 private static Boolean writeStatus = false;
58 private static Boolean readStatus = false;
59 private static Boolean deleteStatus = false;
60 private static DataBroker dataBroker = null;
61 private static String addressStr;
62 private static String portStr;
63 private static String connectionType;
64 private static Boolean setup = false;
67 private BundleContext bc;
70 public Option[] config() {
71 return super.config();
75 public String getModuleName() {
76 return "southbound-impl";
80 public String getInstanceName() {
81 return "southbound-default";
85 public MavenUrlReference getFeatureRepo() {
87 .groupId("org.opendaylight.ovsdb")
88 .artifactId("southbound-features")
89 .classifier("features")
91 .versionAsInProject();
95 public String getFeatureName() {
96 return "odl-ovsdb-southbound-impl-ui";
99 protected String usage() {
100 return "Integration Test needs a valid connection configuration as follows :\n"
101 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
102 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
106 public Option[] getPropertiesOptions() {
107 Properties props = new Properties(System.getProperties());
108 String addressStr = props.getProperty(SERVER_IPADDRESS, DEFAULT_SERVER_IPADDRESS);
109 String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
110 String connectionType = props.getProperty(CONNECTION_TYPE, CONNECTION_TYPE_ACTIVE);
112 LOG.info("1: Using the following properties: mode= {}, ip:port= {}:{}",
113 connectionType, addressStr, portStr);
115 Option[] options = new Option[] {
116 editConfigurationFilePut(CUSTOM_PROPERTIES, SERVER_IPADDRESS, addressStr),
117 editConfigurationFilePut(CUSTOM_PROPERTIES, SERVER_PORT, portStr),
118 editConfigurationFilePut(CUSTOM_PROPERTIES, CONNECTION_TYPE, connectionType)
124 public void setUp() {
126 LOG.info("Skipping setUp, already initialized");
132 } catch (Exception e) {
135 dataBroker = getSession().getSALService(DataBroker.class);
137 addressStr = bc.getProperty(SERVER_IPADDRESS);
138 portStr = bc.getProperty(SERVER_PORT);
139 connectionType = bc.getProperty(CONNECTION_TYPE);
141 LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
142 connectionType, addressStr, portStr);
143 if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
144 if (addressStr == null) {
153 public void testPassiveNode() throws InterruptedException {
154 if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_PASSIVE)) {
155 //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
156 Thread.sleep(CONNECTION_INIT_TIMEOUT);
161 public void testAddRemoveOvsdbNode() throws InterruptedException {
162 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
163 DataBroker dataBroker = getSession().getSALService(DataBroker.class);
165 // Write OVSDB node to configuration
166 final ReadWriteTransaction configNodeTx = dataBroker.newReadWriteTransaction();
167 configNodeTx.put(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier(),
168 SouthboundMapper.createNode(ovsdbClientKey));
169 Futures.addCallback(configNodeTx.submit(), new FutureCallback<Void>() {
171 public void onSuccess(final Void result) {
172 LOG.info("success writing node to configuration: " + configNodeTx);
177 public void onFailure(final Throwable throwable) {
178 fail("failed writing node to configuration: " + configNodeTx);
184 assertTrue("Failed to write node to configuration", writeStatus);
186 // Read from operational to verify if the OVSDB node is connected
187 final ReadOnlyTransaction readNodeTx = dataBroker.newReadOnlyTransaction();
188 ListenableFuture<Optional<Node>> dataFuture = readNodeTx.read(
189 LogicalDatastoreType.OPERATIONAL, ovsdbClientKey.toInstanceIndentifier());
190 Futures.addCallback(dataFuture, new FutureCallback<Optional<Node>>() {
192 public void onSuccess(final Optional<Node> result) {
193 LOG.info("success reading node from operational: " + readNodeTx);
194 LOG.info("Optional result: {}", result);
195 if (result.isPresent()) {
196 LOG.info("node: {}", result.get());
202 public void onFailure(final Throwable throwable) {
203 fail("failed reading node from operational: " + readNodeTx);
209 assertTrue("Failed to read node from operational", readStatus);
211 // Delete OVSDB node from configuration
212 final ReadWriteTransaction deleteNodeTx = dataBroker.newReadWriteTransaction();
213 deleteNodeTx.delete(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier());
214 Futures.addCallback(deleteNodeTx.submit(), new FutureCallback<Void>() {
216 public void onSuccess(final Void result) {
217 LOG.info("success deleting node from configuration: " + deleteNodeTx);
222 public void onFailure(final Throwable throwable) {
223 fail("failed deleting node from configuration: " + deleteNodeTx);
229 assertTrue("Failed to delete node from configuration", deleteStatus);
231 // Read from operational to verify if the OVSDB node is disconnected
232 // Similar to the earlier read, but this time synchronously
233 final ReadOnlyTransaction readNodeTx2 = dataBroker.newReadOnlyTransaction();
234 Optional<Node> node = Optional.absent();
236 node = readNodeTx2.read(LogicalDatastoreType.OPERATIONAL,
237 ovsdbClientKey.toInstanceIndentifier()).checkedGet();
238 assertFalse("Failed to delete node from configuration and node is still connected",
240 } catch (final ReadFailedException e) {
241 LOG.debug("Read Operational/DS for Node fail! {}", ovsdbClientKey.toInstanceIndentifier(), e);
242 fail("failed reading node from operational: " + readNodeTx2 + e);
247 public void testAddRemoveOvsdbNode2() throws InterruptedException {
248 addNode("192.168.120.31", "6640");
250 Node node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
252 LOG.info("Connected node: {}", node);
253 deleteNode("192.168.120.31", "6640");
255 node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
259 private OvsdbClientKey getOvsdbClientKey(String addressStr, String portStr) {
260 InetAddress inetAddress = null;
262 inetAddress = InetAddress.getByName(addressStr);
263 } catch (UnknownHostException e) {
264 fail("Could not allocate InetAddress: " + e);
267 IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
268 PortNumber port = new PortNumber(Integer.parseInt(portStr));
270 return new OvsdbClientKey(address, port);
273 private void addNode(String addressStr, String portStr) {
274 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
276 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
277 rwTx.put(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier(),
278 SouthboundMapper.createNode(ovsdbClientKey));
279 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
282 } catch (ExecutionException | InterruptedException e) {
283 fail("Failed transaction: " + rwTx + e);
287 private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
288 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
290 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
291 Optional<Node> node = Optional.absent();
292 CheckedFuture<Optional<Node>, ReadFailedException> read;
293 read = rwTx.read(type, ovsdbClientKey.toInstanceIndentifier());
295 node = read.checkedGet();
296 if (node.isPresent()) {
299 } catch (ReadFailedException e) {
300 fail("Failed transaction: " + rwTx + e);
306 private void deleteNode(String addressStr, String portStr) {
307 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
309 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
310 rwTx.delete(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier());
311 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
314 } catch (ExecutionException | InterruptedException e) {
315 fail("Failed transaction: " + rwTx + e);