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.util.concurrent.CheckedFuture;
20 import com.google.common.util.concurrent.FutureCallback;
21 import com.google.common.util.concurrent.Futures;
22 import com.google.common.util.concurrent.ListenableFuture;
23 import java.net.InetAddress;
24 import java.net.UnknownHostException;
25 import java.util.Properties;
26 import java.util.concurrent.ExecutionException;
27 import javax.inject.Inject;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
33 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
36 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
37 import org.opendaylight.ovsdb.southbound.OvsdbClientKey;
38 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
42 import org.ops4j.pax.exam.Configuration;
43 import org.ops4j.pax.exam.Option;
44 import org.ops4j.pax.exam.junit.PaxExam;
45 import org.ops4j.pax.exam.options.MavenUrlReference;
46 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
47 import org.ops4j.pax.exam.spi.reactors.PerClass;
48 import org.osgi.framework.BundleContext;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
53 * Integration test for
54 * {@link org.opendaylight.ovsdb.southbound}
56 * @author Sam Hague (shague@redhat.com)
58 @RunWith(PaxExam.class)
59 @ExamReactorStrategy(PerClass.class)
60 public class SouthboundIT extends AbstractMdsalTestBase {
61 private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
62 private static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
63 private static final String SERVER_PORT = "ovsdbserver.port";
64 private static final String CONNECTION_TYPE = "ovsdbserver.connection";
65 private static final String CONNECTION_TYPE_ACTIVE = "active";
66 private static final String CONNECTION_TYPE_PASSIVE = "passive";
67 private static final int CONNECTION_INIT_TIMEOUT = 10000;
68 private static final String DEFAULT_SERVER_IPADDRESS = "127.0.0.1";
69 private static final String DEFAULT_SERVER_PORT = "6640";
70 private static Boolean writeStatus = false;
71 private static Boolean readStatus = false;
72 private static Boolean deleteStatus = false;
73 private static DataBroker dataBroker = null;
74 private static String addressStr;
75 private static String portStr;
76 private static String connectionType;
77 private static Boolean setup = false;
80 private BundleContext bc;
83 public Option[] config() {
84 return super.config();
88 public String getModuleName() {
89 return "southbound-impl";
93 public String getInstanceName() {
94 return "southbound-default";
98 public MavenUrlReference getFeatureRepo() {
100 .groupId("org.opendaylight.ovsdb")
101 .artifactId("southbound-features")
102 .classifier("features")
104 .versionAsInProject();
108 public String getFeatureName() {
109 return "odl-ovsdb-southbound-impl-ui";
112 protected String usage() {
113 return "Integration Test needs a valid connection configuration as follows :\n"
114 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
115 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
119 public Option[] getPropertiesOptions() {
120 Properties props = new Properties(System.getProperties());
121 String addressStr = props.getProperty(SERVER_IPADDRESS, DEFAULT_SERVER_IPADDRESS);
122 String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
123 String connectionType = props.getProperty(CONNECTION_TYPE, CONNECTION_TYPE_ACTIVE);
125 LOG.info("1: Using the following properties: mode= {}, ip:port= {}:{}",
126 connectionType, addressStr, portStr);
128 Option[] options = new Option[] {
129 editConfigurationFilePut(CUSTOM_PROPERTIES, SERVER_IPADDRESS, addressStr),
130 editConfigurationFilePut(CUSTOM_PROPERTIES, SERVER_PORT, portStr),
131 editConfigurationFilePut(CUSTOM_PROPERTIES, CONNECTION_TYPE, connectionType)
137 public void setUp() {
139 LOG.info("Skipping setUp, already initialized");
145 } catch (Exception e) {
148 dataBroker = getSession().getSALService(DataBroker.class);
150 addressStr = bc.getProperty(SERVER_IPADDRESS);
151 portStr = bc.getProperty(SERVER_PORT);
152 connectionType = bc.getProperty(CONNECTION_TYPE);
154 LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
155 connectionType, addressStr, portStr);
156 if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
157 if (addressStr == null) {
166 public void testPassiveNode() throws InterruptedException {
167 if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_PASSIVE)) {
168 //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
169 Thread.sleep(CONNECTION_INIT_TIMEOUT);
174 public void testAddRemoveOvsdbNode() throws InterruptedException {
175 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
176 DataBroker dataBroker = getSession().getSALService(DataBroker.class);
178 // Write OVSDB node to configuration
179 final ReadWriteTransaction configNodeTx = dataBroker.newReadWriteTransaction();
180 configNodeTx.put(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier(),
181 SouthboundMapper.createNode(ovsdbClientKey));
182 Futures.addCallback(configNodeTx.submit(), new FutureCallback<Void>() {
184 public void onSuccess(final Void result) {
185 LOG.info("success writing node to configuration: " + configNodeTx);
190 public void onFailure(final Throwable throwable) {
191 fail("failed writing node to configuration: " + configNodeTx);
197 assertTrue("Failed to write node to configuration", writeStatus);
199 // Read from operational to verify if the OVSDB node is connected
200 final ReadOnlyTransaction readNodeTx = dataBroker.newReadOnlyTransaction();
201 ListenableFuture<Optional<Node>> dataFuture = readNodeTx.read(
202 LogicalDatastoreType.OPERATIONAL, ovsdbClientKey.toInstanceIndentifier());
203 Futures.addCallback(dataFuture, new FutureCallback<Optional<Node>>() {
205 public void onSuccess(final Optional<Node> result) {
206 LOG.info("success reading node from operational: " + readNodeTx);
207 LOG.info("Optional result: {}", result);
208 if (result.isPresent()) {
209 LOG.info("node: {}", result.get());
215 public void onFailure(final Throwable throwable) {
216 fail("failed reading node from operational: " + readNodeTx);
222 assertTrue("Failed to read node from operational", readStatus);
224 // Delete OVSDB node from configuration
225 final ReadWriteTransaction deleteNodeTx = dataBroker.newReadWriteTransaction();
226 deleteNodeTx.delete(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier());
227 Futures.addCallback(deleteNodeTx.submit(), new FutureCallback<Void>() {
229 public void onSuccess(final Void result) {
230 LOG.info("success deleting node from configuration: " + deleteNodeTx);
235 public void onFailure(final Throwable throwable) {
236 fail("failed deleting node from configuration: " + deleteNodeTx);
242 assertTrue("Failed to delete node from configuration", deleteStatus);
244 // Read from operational to verify if the OVSDB node is disconnected
245 // Similar to the earlier read, but this time synchronously
246 final ReadOnlyTransaction readNodeTx2 = dataBroker.newReadOnlyTransaction();
247 Optional<Node> node = Optional.absent();
249 node = readNodeTx2.read(LogicalDatastoreType.OPERATIONAL,
250 ovsdbClientKey.toInstanceIndentifier()).checkedGet();
251 assertFalse("Failed to delete node from configuration and node is still connected",
253 } catch (final ReadFailedException e) {
254 LOG.debug("Read Operational/DS for Node fail! {}", ovsdbClientKey.toInstanceIndentifier(), e);
255 fail("failed reading node from operational: " + readNodeTx2 + e);
260 public void testAddRemoveOvsdbNode2() throws InterruptedException {
261 addNode("192.168.120.31", "6640");
263 Node node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
265 LOG.info("Connected node: {}", node);
266 deleteNode("192.168.120.31", "6640");
268 node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
272 private OvsdbClientKey getOvsdbClientKey(String addressStr, String portStr) {
273 InetAddress inetAddress = null;
275 inetAddress = InetAddress.getByName(addressStr);
276 } catch (UnknownHostException e) {
277 fail("Could not allocate InetAddress: " + e);
280 IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
281 PortNumber port = new PortNumber(Integer.parseInt(portStr));
283 return new OvsdbClientKey(address, port);
286 private void addNode(String addressStr, String portStr) {
287 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
289 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
290 rwTx.put(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier(),
291 SouthboundMapper.createNode(ovsdbClientKey));
292 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
295 } catch (ExecutionException | InterruptedException e) {
296 fail("Failed transaction: " + rwTx + e);
300 private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
301 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
303 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
304 Optional<Node> node = Optional.absent();
305 CheckedFuture<Optional<Node>, ReadFailedException> read;
306 read = rwTx.read(type, ovsdbClientKey.toInstanceIndentifier());
308 node = read.checkedGet();
309 if (node.isPresent()) {
312 } catch (ReadFailedException e) {
313 fail("Failed transaction: " + rwTx + e);
319 private void deleteNode(String addressStr, String portStr) {
320 OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
322 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
323 rwTx.delete(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier());
324 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
327 } catch (ExecutionException | InterruptedException e) {
328 fail("Failed transaction: " + rwTx + e);