Add copyright's to southbound-it files.
[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.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;
51
52 /**
53  * Integration test for
54  * {@link org.opendaylight.ovsdb.southbound}
55  *
56  * @author Sam Hague (shague@redhat.com)
57  */
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;
78
79     @Inject
80     private BundleContext bc;
81
82     @Configuration
83     public Option[] config() {
84         return super.config();
85     }
86
87     @Override
88     public String getModuleName() {
89         return "southbound-impl";
90     }
91
92     @Override
93     public String getInstanceName() {
94         return "southbound-default";
95     }
96
97     @Override
98     public MavenUrlReference getFeatureRepo() {
99         return maven()
100                 .groupId("org.opendaylight.ovsdb")
101                 .artifactId("southbound-features")
102                 .classifier("features")
103                 .type("xml")
104                 .versionAsInProject();
105     }
106
107     @Override
108     public String getFeatureName() {
109         return "odl-ovsdb-southbound-impl-ui";
110     }
111
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";
116     }
117
118     @Override
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);
124
125         LOG.info("1: Using the following properties: mode= {}, ip:port= {}:{}",
126                 connectionType, addressStr, portStr);
127
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)
132         };
133         return options;
134     }
135
136     @Before
137     public void setUp() {
138         if (setup == true) {
139             LOG.info("Skipping setUp, already initialized");
140             return;
141         }
142
143         try {
144             super.setup();
145         } catch (Exception e) {
146             e.printStackTrace();
147         }
148         dataBroker = getSession().getSALService(DataBroker.class);
149
150         addressStr = bc.getProperty(SERVER_IPADDRESS);
151         portStr = bc.getProperty(SERVER_PORT);
152         connectionType = bc.getProperty(CONNECTION_TYPE);
153
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) {
158                 fail(usage());
159             }
160         }
161
162         setup = true;
163     }
164
165     @Test
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);
170         }
171     }
172
173     @Test
174     public void testAddRemoveOvsdbNode() throws InterruptedException {
175         OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
176         DataBroker dataBroker = getSession().getSALService(DataBroker.class);
177
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>() {
183             @Override
184             public void onSuccess(final Void result) {
185                 LOG.info("success writing node to configuration: " + configNodeTx);
186                 writeStatus = true;
187             }
188
189             @Override
190             public void onFailure(final Throwable throwable) {
191                 fail("failed writing node to configuration: " + configNodeTx);
192             }
193         });
194
195         Thread.sleep(1000);
196
197         assertTrue("Failed to write node to configuration", writeStatus);
198
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>>() {
204             @Override
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());
210                     readStatus = true;
211                 }
212             }
213
214             @Override
215             public void onFailure(final Throwable throwable) {
216                 fail("failed reading node from operational: " + readNodeTx);
217             }
218         });
219
220         Thread.sleep(1000);
221
222         assertTrue("Failed to read node from operational", readStatus);
223
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>() {
228             @Override
229             public void onSuccess(final Void result) {
230                 LOG.info("success deleting node from configuration: " + deleteNodeTx);
231                 deleteStatus = true;
232             }
233
234             @Override
235             public void onFailure(final Throwable throwable) {
236                 fail("failed deleting node from configuration: " + deleteNodeTx);
237             }
238         });
239
240         Thread.sleep(1000);
241
242         assertTrue("Failed to delete node from configuration", deleteStatus);
243
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();
248         try {
249             node = readNodeTx2.read(LogicalDatastoreType.OPERATIONAL,
250                     ovsdbClientKey.toInstanceIndentifier()).checkedGet();
251             assertFalse("Failed to delete node from configuration and node is still connected",
252                     node.isPresent());
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);
256         }
257     }
258
259     @Test
260     public void testAddRemoveOvsdbNode2() throws InterruptedException {
261         addNode("192.168.120.31", "6640");
262         Thread.sleep(1000);
263         Node node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
264         assertNotNull(node);
265         LOG.info("Connected node: {}", node);
266         deleteNode("192.168.120.31", "6640");
267         Thread.sleep(1000);
268         node = readNode("192.168.120.31", "6640", LogicalDatastoreType.OPERATIONAL);
269         assertNull(node);
270     }
271
272     private OvsdbClientKey getOvsdbClientKey(String addressStr, String portStr) {
273         InetAddress inetAddress = null;
274         try {
275             inetAddress = InetAddress.getByName(addressStr);
276         } catch (UnknownHostException e) {
277             fail("Could not allocate InetAddress: " + e);
278         }
279
280         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
281         PortNumber port = new PortNumber(Integer.parseInt(portStr));
282
283         return new OvsdbClientKey(address, port);
284     }
285
286     private void addNode(String addressStr, String portStr) {
287         OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
288
289         final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
290         rwTx.put(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier(),
291                 SouthboundMapper.createNode(ovsdbClientKey));
292         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
293         try {
294             commitFuture.get();
295         } catch (ExecutionException | InterruptedException e) {
296             fail("Failed transaction: " + rwTx + e);
297         }
298     }
299
300     private Node readNode(String addressStr, String portStr, LogicalDatastoreType type) {
301         OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
302
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());
307         try {
308             node = read.checkedGet();
309             if (node.isPresent()) {
310                 return node.get();
311             }
312         } catch (ReadFailedException e) {
313             fail("Failed transaction: " + rwTx + e);
314         }
315
316         return null;
317     }
318
319     private void deleteNode(String addressStr, String portStr) {
320         OvsdbClientKey ovsdbClientKey = getOvsdbClientKey(addressStr, portStr);
321
322         final ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
323         rwTx.delete(LogicalDatastoreType.CONFIGURATION, ovsdbClientKey.toInstanceIndentifier());
324         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = rwTx.submit();
325         try {
326             commitFuture.get();
327         } catch (ExecutionException | InterruptedException e) {
328             fail("Failed transaction: " + rwTx + e);
329         }
330     }
331 }