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.assertNotNull;
11 import static org.junit.Assert.fail;
12 import static org.ops4j.pax.exam.CoreOptions.maven;
13 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
14 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
16 import com.google.common.base.Optional;
17 import com.google.common.collect.ObjectArrays;
18 import com.google.common.util.concurrent.CheckedFuture;
20 import java.net.InetAddress;
21 import java.net.UnknownHostException;
22 import java.util.List;
23 import java.util.Properties;
24 import java.util.concurrent.ExecutionException;
26 import javax.inject.Inject;
28 import org.junit.Assert;
29 import org.junit.Assume;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
37 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
38 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
39 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
40 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.ops4j.pax.exam.Configuration;
53 import org.ops4j.pax.exam.Option;
54 import org.ops4j.pax.exam.junit.PaxExam;
55 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
56 import org.ops4j.pax.exam.options.MavenUrlReference;
57 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
58 import org.ops4j.pax.exam.spi.reactors.PerClass;
59 import org.osgi.framework.Bundle;
60 import org.osgi.framework.BundleContext;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
65 * Integration tests for southbound-impl
67 * @author Sam Hague (shague@redhat.com)
69 @RunWith(PaxExam.class)
70 @ExamReactorStrategy(PerClass.class)
71 public class SouthboundIT extends AbstractMdsalTestBase {
72 private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
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;
78 private MdsalUtils mdsalUtils = null;
79 private String extras = "false";
80 private static final String NETVIRT = "org.opendaylight.ovsdb.openstack.net-virt";
81 private static final String NETVIRTPROVIDERS = "org.opendaylight.ovsdb.openstack.net-virt-providers";
84 private BundleContext bundleContext;
87 public Option[] config() {
88 return super.config();
92 public String getModuleName() {
93 return "southbound-impl";
97 public String getInstanceName() {
98 return "southbound-default";
102 public MavenUrlReference getFeatureRepo() {
104 .groupId("org.opendaylight.ovsdb")
105 .artifactId("southbound-features")
106 .classifier("features")
108 .versionAsInProject();
112 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[] getFeaturesOptions() {
125 if (extras.equals("true")) {
126 Option[] options = new Option[] {
127 features("mvn:org.opendaylight.ovsdb/features-ovsdb/1.1.0-SNAPSHOT/xml/features",
128 "odl-ovsdb-openstack-sb")};
131 return new Option[]{};
136 public Option[] getLoggingOptions() {
137 Option[] options = new Option[] {
138 /*editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
139 "log4j.logger.org.opendaylight.ovsdb",
140 LogLevelOption.LogLevel.DEBUG.name()),*/
141 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
142 "log4j.logger.org.opendaylight.ovsdb.southbound-impl",
143 LogLevelOption.LogLevel.DEBUG.name())
146 if (extras.equals("true")) {
147 Option[] extraOptions = new Option[] {
148 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
149 "log4j.logger.org.opendaylight.ovsdb",
150 LogLevelOption.LogLevel.DEBUG.name()),
151 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
152 "log4j.logger.org.opendaylight.ovsdb.openstack.net-virt",
153 LogLevelOption.LogLevel.DEBUG.name())
155 options = ObjectArrays.concat(options, extraOptions, Option.class);
158 options = ObjectArrays.concat(options, super.getLoggingOptions(), Option.class);
163 public Option[] getPropertiesOptions() {
164 Properties props = new Properties(System.getProperties());
165 String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
166 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
167 String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
168 SouthboundITConstants.DEFAULT_SERVER_PORT);
169 String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
170 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
172 LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
173 connectionType, addressStr, portStr);
175 Option[] options = new Option[] {
176 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
177 SouthboundITConstants.SERVER_IPADDRESS, addressStr),
178 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
179 SouthboundITConstants.SERVER_PORT, portStr),
180 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
181 SouthboundITConstants.CONNECTION_TYPE, connectionType)
186 private void setExtras() {
187 Properties props = new Properties(System.getProperties());
188 extras = props.getProperty(SouthboundITConstants.SERVER_EXTRAS,
189 SouthboundITConstants.DEFAULT_SERVER_EXTRAS);
190 LOG.info("extras: {}", extras);
191 System.out.println("extras: " + extras);
195 public void setUp() throws InterruptedException {
197 LOG.info("Skipping setUp, already initialized");
203 } catch (Exception e) {
206 //dataBroker = getSession().getSALService(DataBroker.class);
208 dataBroker = SouthboundProvider.getDb();
209 Assert.assertNotNull("db should not be null", dataBroker);
211 addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
212 portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
213 connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
215 LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
216 connectionType, addressStr, portStr);
217 if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
218 if (addressStr == null) {
223 mdsalUtils = new MdsalUtils(dataBroker);
226 if (extras.equals("true")) {
227 isBundleReady(bundleContext, NETVIRT);
228 isBundleReady(bundleContext, NETVIRTPROVIDERS);
233 public void testPassiveNode() throws InterruptedException {
234 if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
235 //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
236 Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
241 public void testAddRemoveOvsdbNode() throws InterruptedException {
242 addNode(addressStr, portStr);
244 Node node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
246 LOG.info("Connected node: {}", node);
247 deleteNode(addressStr, portStr);
249 node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
250 Assume.assumeNotNull(node);//assertNull(node);
253 private ConnectionInfo getConnectionInfo(String addressStr, String portStr) {
254 InetAddress inetAddress = null;
256 inetAddress = InetAddress.getByName(addressStr);
257 } catch (UnknownHostException e) {
258 fail("Could not allocate InetAddress: " + e);
261 IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
262 PortNumber port = new PortNumber(Integer.parseInt(portStr));
264 return new ConnectionInfoBuilder()
265 .setRemoteIp(address)
270 private void addNode(String addressStr, String portStr) {
271 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
273 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
274 rwTx.put(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo),
275 SouthboundMapper.createNode(connectionInfo));
276 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
278 commitFuture.checkedGet();
279 } catch (TransactionCommitFailedException e) {
280 fail("Failed transaction: " + rwTx + e);
284 private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
285 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
287 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
288 Optional<Node> node = Optional.absent();
289 CheckedFuture<Optional<Node>, ReadFailedException> read;
290 read = rwTx.read(type, SouthboundMapper.createInstanceIdentifier(connectionInfo));
292 node = read.checkedGet();
293 if (node.isPresent()) {
296 } catch (ReadFailedException e) {
297 fail("Failed transaction: " + rwTx + e);
303 private void deleteNode(String addressStr, String portStr) {
304 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
306 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
307 rwTx.delete(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo));
308 CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
311 } catch (ExecutionException | InterruptedException e) {
312 fail("Failed transaction: " + rwTx + e);
316 private NetworkTopology readNetworkTopology(LogicalDatastoreType type) {
317 ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
319 final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
320 Optional<NetworkTopology> optional = Optional.absent();
321 CheckedFuture<Optional<NetworkTopology>, ReadFailedException> read;
322 read = rwTx.read(type, InstanceIdentifier.create(NetworkTopology.class));
324 optional = read.checkedGet();
325 if (optional.isPresent()) {
326 return optional.get();
328 } catch (ReadFailedException e) {
329 fail("Failed transaction: " + rwTx + e);
336 public void testNetworkTopology() throws InterruptedException {
337 NetworkTopology networkTopology = MdsalUtils.readTransaction(LogicalDatastoreType.CONFIGURATION,
338 InstanceIdentifier.create(NetworkTopology.class));
339 Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
342 networkTopology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL,
343 InstanceIdentifier.create(NetworkTopology.class));
344 Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
349 public void testOvsdbTopology() throws InterruptedException {
350 InstanceIdentifier<Topology> path = InstanceIdentifier
351 .create(NetworkTopology.class)
352 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
354 Topology topology = MdsalUtils.readTransaction(LogicalDatastoreType.CONFIGURATION, path);
355 Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
358 topology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL, path);
360 Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
364 public Node connectNode(String addressStr, String portStr) throws InterruptedException {
365 addNode(addressStr, portStr);
367 Node node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
369 LOG.info("Connected node: {}", node);
373 public void disconnectNode(String addressStr, String portStr) throws InterruptedException {
374 deleteNode(addressStr, portStr);
376 Node node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
377 Assume.assumeNotNull(node);//Assert.assertNull("node was found in operational", node);
381 public void testOpenVSwitchOtherConfig() throws InterruptedException {
382 Node node = connectNode(addressStr, portStr);
384 OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class);
385 assertNotNull(ovsdbNodeAugmentation);
386 List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
387 if (otherConfigsList != null) {
388 for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
389 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
390 LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
396 disconnectNode(addressStr, portStr);
400 * isBundleReady is used to check if the requested bundle is Active
402 public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException {
403 boolean ready = false;
406 int state = Bundle.UNINSTALLED;
407 Bundle[] bundles = bundleContext.getBundles();
408 for (Bundle element : bundles) {
409 if (element.getSymbolicName().equals(bundleName)) {
410 state = element.getState();
411 LOG.info(">>>>> bundle is ready {}", bundleName);
415 if (state != Bundle.ACTIVE) {
416 LOG.info(">>>>> bundle not ready {}", bundleName);