Add constant class for shared strings in SouthboundIT
[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.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;
17
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;
24
25 import java.net.InetAddress;
26 import java.net.UnknownHostException;
27 import java.util.Properties;
28 import java.util.concurrent.ExecutionException;
29
30 import javax.inject.Inject;
31
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;
64
65 /**
66  * Integration tests for southbound-impl
67  *
68  * @author Sam Hague (shague@redhat.com)
69  */
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;
83
84     @Inject
85     private BundleContext bc;
86
87     @Configuration
88     public Option[] config() {
89         return super.config();
90     }
91
92     @Override
93     public String getModuleName() {
94         return "southbound-impl";
95     }
96
97     @Override
98     public String getInstanceName() {
99         return "southbound-default";
100     }
101
102     @Override
103     public MavenUrlReference getFeatureRepo() {
104         return maven()
105                 .groupId("org.opendaylight.ovsdb")
106                 .artifactId("southbound-features")
107                 .classifier("features")
108                 .type("xml")
109                 .versionAsInProject();
110     }
111
112     @Override
113     public String getFeatureName() {
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[] 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())
129         };
130         options = ObjectArrays.concat(options, super.getLoggingOptions(), Option.class);
131         return options;
132     }
133
134     @Override
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);
143
144         LOG.info("Using the following properties: mode= {}, ip:port= {}:{}",
145                 connectionType, addressStr, portStr);
146
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)
154         };
155         return options;
156     }
157
158     @Before
159     public void setUp() throws InterruptedException {
160         if (setup == true) {
161             LOG.info("Skipping setUp, already initialized");
162             return;
163         }
164
165         try {
166             super.setup();
167         } catch (Exception e) {
168             e.printStackTrace();
169         }
170         //dataBroker = getSession().getSALService(DataBroker.class);
171         Thread.sleep(3000);
172         dataBroker = SouthboundProvider.getDb();
173         Assert.assertNotNull("db should not be null", dataBroker);
174
175         addressStr = bc.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
176         portStr = bc.getProperty(SouthboundITConstants.SERVER_PORT);
177         connectionType = bc.getProperty(SouthboundITConstants.CONNECTION_TYPE);
178
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) {
183                 fail(usage());
184             }
185         }
186
187         mdsalUtils = new MdsalUtils(dataBroker);
188         setup = true;
189     }
190
191     @Test
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);
196         }
197     }
198
199     @Test
200     public void testAddRemoveOvsdbNode() throws InterruptedException {
201         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
202
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>() {
208             @Override
209             public void onSuccess(final Void result) {
210                 LOG.info("success writing node to configuration: " + configNodeTx);
211                 writeStatus = true;
212             }
213
214             @Override
215             public void onFailure(final Throwable throwable) {
216                 fail("failed writing node to configuration: " + configNodeTx);
217             }
218         });
219
220         Thread.sleep(1000);
221
222         assertTrue("Failed to write node to configuration", writeStatus);
223
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>>() {
229             @Override
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());
235                     readStatus = true;
236                 }
237             }
238
239             @Override
240             public void onFailure(final Throwable throwable) {
241                 fail("failed reading node from operational: " + readNodeTx);
242             }
243         });
244
245         Thread.sleep(1000);
246
247         assertTrue("Failed to read node from operational", readStatus);
248
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>() {
254             @Override
255             public void onSuccess(final Void result) {
256                 LOG.info("success deleting node from configuration: " + deleteNodeTx);
257                 deleteStatus = true;
258             }
259
260             @Override
261             public void onFailure(final Throwable throwable) {
262                 fail("failed deleting node from configuration: " + deleteNodeTx);
263             }
264         });
265
266         Thread.sleep(1000);
267
268         assertTrue("Failed to delete node from configuration", deleteStatus);
269
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();
274         try {
275             node = readNodeTx2.read(LogicalDatastoreType.OPERATIONAL,
276                     SouthboundMapper.createInstanceIdentifier(connectionInfo)).checkedGet();
277             assertFalse("Failed to delete node from configuration and node is still connected",
278                     node.isPresent());
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);
283         }
284     }
285
286     @Test
287     public void testAddRemoveOvsdbNode2() throws InterruptedException {
288         addNode("192.168.120.31", "6640");
289         Thread.sleep(1000);
290         Node node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
291         assertNotNull(node);
292         LOG.info("Connected node: {}", node);
293         deleteNode("192.168.120.31", "6640");
294         Thread.sleep(1000);
295         node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
296         assertNull(node);
297     }
298
299     private ConnectionInfo getConnectionInfo(String addressStr, String portStr) {
300         InetAddress inetAddress = null;
301         try {
302             inetAddress = InetAddress.getByName(addressStr);
303         } catch (UnknownHostException e) {
304             fail("Could not allocate InetAddress: " + e);
305         }
306
307         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
308         PortNumber port = new PortNumber(Integer.parseInt(portStr));
309
310         return new ConnectionInfoBuilder()
311                        .setRemoteIp(address)
312                        .setRemotePort(port)
313                        .build();
314     }
315
316     private void addNode(String addressStr, String portStr) {
317         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
318
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();
323         try {
324             commitFuture.checkedGet();
325         } catch (TransactionCommitFailedException e) {
326             fail("Failed transaction: " + rwTx + e);
327         }
328     }
329
330     private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
331         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
332
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));
337         try {
338             node = read.checkedGet();
339             if (node.isPresent()) {
340                 return node.get();
341             }
342         } catch (ReadFailedException e) {
343             fail("Failed transaction: " + rwTx + e);
344         }
345
346         return null;
347     }
348
349     private void deleteNode(String addressStr, String portStr) {
350         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
351
352         final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
353         rwTx.delete(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo));
354         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
355         try {
356             commitFuture.get();
357         } catch (ExecutionException | InterruptedException e) {
358             fail("Failed transaction: " + rwTx + e);
359         }
360     }
361
362     private NetworkTopology readNetworkTopology(LogicalDatastoreType type) {
363         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
364
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));
369         try {
370             optional = read.checkedGet();
371             if (optional.isPresent()) {
372                 return optional.get();
373             }
374         } catch (ReadFailedException e) {
375             fail("Failed transaction: " + rwTx + e);
376         }
377
378         return null;
379     }
380
381     @Test
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,
386                 networkTopology);
387
388         networkTopology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL,
389                 InstanceIdentifier.create(NetworkTopology.class));
390         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
391                 networkTopology);
392     }
393
394     @Test
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));
399
400         Topology topology = MdsalUtils.readTransaction(LogicalDatastoreType.CONFIGURATION, path);
401         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
402                 topology);
403
404         topology = MdsalUtils.readTransaction(LogicalDatastoreType.OPERATIONAL, path);
405
406         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
407                 topology);
408     }
409 }