Merge "Update gogo versions to account for new karaf 3.0.3 constraints"
[ovsdb.git] / southbound / southbound-it / src / test / java / org / opendaylight / ovsdb / southbound / it / SouthboundIT.java
1 /*
2  * Copyright (c) 2015 Red Hat, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.ovsdb.southbound.it;
9
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;
15
16 import com.google.common.base.Optional;
17 import com.google.common.collect.ObjectArrays;
18 import com.google.common.util.concurrent.CheckedFuture;
19
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;
25
26 import javax.inject.Inject;
27
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;
63
64 /**
65  * Integration tests for southbound-impl
66  *
67  * @author Sam Hague (shague@redhat.com)
68  */
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";
82
83     @Inject
84     private BundleContext bundleContext;
85
86     @Configuration
87     public Option[] config() {
88         return super.config();
89     }
90
91     @Override
92     public String getModuleName() {
93         return "southbound-impl";
94     }
95
96     @Override
97     public String getInstanceName() {
98         return "southbound-default";
99     }
100
101     @Override
102     public MavenUrlReference getFeatureRepo() {
103         return maven()
104                 .groupId("org.opendaylight.ovsdb")
105                 .artifactId("southbound-features")
106                 .classifier("features")
107                 .type("xml")
108                 .versionAsInProject();
109     }
110
111     @Override
112     public String getFeatureName() {
113         setExtras();
114         return "odl-ovsdb-southbound-impl-ui";
115     }
116
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";
121     }
122
123     @Override
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")};
129             return options;
130         } else {
131             return new Option[]{};
132         }
133     }
134
135     @Override
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())
144         };
145
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())
154             };
155             options = ObjectArrays.concat(options, extraOptions, Option.class);
156         }
157
158         options = ObjectArrays.concat(options, super.getLoggingOptions(), Option.class);
159         return options;
160     }
161
162     @Override
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);
171
172         LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
173                 connectionType, addressStr, portStr);
174
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)
182         };
183         return options;
184     }
185
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);
192     }
193
194     @Before
195     public void setUp() throws InterruptedException {
196         if (setup == true) {
197             LOG.info("Skipping setUp, already initialized");
198             return;
199         }
200
201         try {
202             super.setup();
203         } catch (Exception e) {
204             e.printStackTrace();
205         }
206         //dataBroker = getSession().getSALService(DataBroker.class);
207         Thread.sleep(3000);
208         dataBroker = SouthboundProvider.getDb();
209         Assert.assertNotNull("db should not be null", dataBroker);
210
211         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
212         portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
213         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
214
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) {
219                 fail(usage());
220             }
221         }
222
223         mdsalUtils = new MdsalUtils(dataBroker);
224         setup = true;
225
226         if (extras.equals("true")) {
227             isBundleReady(bundleContext, NETVIRT);
228             isBundleReady(bundleContext, NETVIRTPROVIDERS);
229         }
230     }
231
232     @Test
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);
237         }
238     }
239
240     @Test
241     public void testAddRemoveOvsdbNode() throws InterruptedException {
242         addNode(addressStr, portStr);
243         Thread.sleep(1000);
244         Node node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
245         assertNotNull(node);
246         LOG.info("Connected node: {}", node);
247         deleteNode(addressStr, portStr);
248         Thread.sleep(1000);
249         node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
250         Assume.assumeNotNull(node);//assertNull(node);
251     }
252
253     private ConnectionInfo getConnectionInfo(String addressStr, String portStr) {
254         InetAddress inetAddress = null;
255         try {
256             inetAddress = InetAddress.getByName(addressStr);
257         } catch (UnknownHostException e) {
258             fail("Could not allocate InetAddress: " + e);
259         }
260
261         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
262         PortNumber port = new PortNumber(Integer.parseInt(portStr));
263
264         return new ConnectionInfoBuilder()
265                        .setRemoteIp(address)
266                        .setRemotePort(port)
267                        .build();
268     }
269
270     private void addNode(String addressStr, String portStr) {
271         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
272
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();
277         try {
278             commitFuture.checkedGet();
279         } catch (TransactionCommitFailedException e) {
280             fail("Failed transaction: " + rwTx + e);
281         }
282     }
283
284     private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
285         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
286
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));
291         try {
292             node = read.checkedGet();
293             if (node.isPresent()) {
294                 return node.get();
295             }
296         } catch (ReadFailedException e) {
297             fail("Failed transaction: " + rwTx + e);
298         }
299
300         return null;
301     }
302
303     private void deleteNode(String addressStr, String portStr) {
304         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
305
306         final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
307         rwTx.delete(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo));
308         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
309         try {
310             commitFuture.get();
311         } catch (ExecutionException | InterruptedException e) {
312             fail("Failed transaction: " + rwTx + e);
313         }
314     }
315
316     private NetworkTopology readNetworkTopology(LogicalDatastoreType type) {
317         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
318
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));
323         try {
324             optional = read.checkedGet();
325             if (optional.isPresent()) {
326                 return optional.get();
327             }
328         } catch (ReadFailedException e) {
329             fail("Failed transaction: " + rwTx + e);
330         }
331
332         return null;
333     }
334
335     @Test
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,
340                 networkTopology);
341
342         networkTopology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL,
343                 InstanceIdentifier.create(NetworkTopology.class));
344         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
345                 networkTopology);
346     }
347
348     @Test
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));
353
354         Topology topology = MdsalUtils.readTransaction(LogicalDatastoreType.CONFIGURATION, path);
355         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
356                 topology);
357
358         topology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL, path);
359
360         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
361                 topology);
362     }
363
364     public Node connectNode(String addressStr, String portStr) throws InterruptedException {
365         addNode(addressStr, portStr);
366         Thread.sleep(5000);
367         Node node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
368         assertNotNull(node);
369         LOG.info("Connected node: {}", node);
370         return node;
371     }
372
373     public void disconnectNode(String addressStr, String portStr) throws InterruptedException {
374         deleteNode(addressStr, portStr);
375         Thread.sleep(5000);
376         Node node = readNode(addressStr, portStr, LogicalDatastoreType.OPERATIONAL);
377         Assume.assumeNotNull(node);//Assert.assertNull("node was found in operational", node);
378     }
379
380     @Test
381     public void testOpenVSwitchOtherConfig() throws InterruptedException {
382         Node node = connectNode(addressStr, portStr);
383         Thread.sleep(5000);
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());
391                     break;
392                 }
393             }
394         }
395         Thread.sleep(5000);
396         disconnectNode(addressStr, portStr);
397     }
398
399     /**
400      * isBundleReady is used to check if the requested bundle is Active
401      */
402     public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException {
403         boolean ready = false;
404
405         while (!ready) {
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);
412                     break;
413                 }
414             }
415             if (state != Bundle.ACTIVE) {
416                 LOG.info(">>>>> bundle not ready {}", bundleName);
417                 Thread.sleep(5000);
418             } else {
419                 ready = true;
420             }
421         }
422     }
423 }