Updating fix for bug 3989 based on discussion in OVSDB meeting
[ovsdb.git] / integrationtest / src / test / java / org / opendaylight / ovsdb / integrationtest / OvsdbIntegrationTestBase.java
1 /*
2  * Copyright (c) 2014 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  * Authors : Madhu Venugopal, Sam Hague
9  */
10 package org.opendaylight.ovsdb.integrationtest;
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import java.io.IOException;
19 import java.net.InetAddress;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Properties;
24 import java.util.concurrent.Callable;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.Future;
29 import java.util.concurrent.TimeUnit;
30 import java.util.concurrent.TimeoutException;
31
32 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
34 import org.opendaylight.ovsdb.lib.OvsdbClient;
35 import org.opendaylight.ovsdb.lib.OvsdbConnection;
36 import org.opendaylight.ovsdb.lib.OvsdbConnectionListener;
37 import org.opendaylight.ovsdb.plugin.api.ConnectionConstants;
38 import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
39
40 import org.junit.Rule;
41 import org.junit.rules.TestRule;
42 import org.junit.rules.TestWatcher;
43 import org.junit.runner.Description;
44 import org.osgi.framework.Bundle;
45 import org.osgi.framework.BundleContext;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 public abstract class OvsdbIntegrationTestBase {
50     private static final Logger LOG = LoggerFactory.getLogger(OvsdbIntegrationTestBase.class);
51     protected final static String IDENTIFIER = "TEST";
52     protected final static String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
53     protected final static String SERVER_PORT = "ovsdbserver.port";
54     protected final static String CONNECTION_TYPE = "ovsdbserver.connection";
55     protected final static String CONNECTION_TYPE_ACTIVE = "active";
56     protected final static String CONNECTION_TYPE_PASSIVE = "passive";
57     protected final static int CONNECTION_INIT_TIMEOUT = 10000;
58     protected final static String DEFAULT_SERVER_PORT = "6640";
59
60     private static boolean bundlesReady = false;
61     public final static String OPEN_VSWITCH_SCHEMA = "Open_vSwitch";
62     public final static String HARDWARE_VTEP = "hardware_vtep";
63
64     public Properties loadProperties() {
65         Properties props = new Properties(System.getProperties());
66         return props;
67     }
68
69     public Node getPluginTestConnection() throws IOException, InterruptedException, ExecutionException, TimeoutException {
70         Properties props = loadProperties();
71         String addressStr = props.getProperty(SERVER_IPADDRESS);
72         String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
73         String connectionType = props.getProperty(CONNECTION_TYPE, "active");
74         Node node = null;
75
76         OvsdbConnectionService
77                 connection = (OvsdbConnectionService)ServiceHelper.getGlobalInstance(OvsdbConnectionService.class, this);
78         // If the connection type is active, controller connects to the ovsdb-server
79         if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
80             if (addressStr == null) {
81                 fail(usage());
82             }
83
84             Map<ConnectionConstants, String> params = new HashMap<ConnectionConstants, String>();
85             params.put(ConnectionConstants.ADDRESS, addressStr);
86             params.put(ConnectionConstants.PORT, portStr);
87             node = connection.connect(IDENTIFIER, params);
88         }  else if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_PASSIVE)) {
89             // Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
90             Thread.sleep(CONNECTION_INIT_TIMEOUT);
91             List<Node> nodes = connection.getNodes();
92             assertNotNull(nodes);
93             assertTrue(nodes.size() > 0);
94             node = nodes.get(0);
95         }
96
97         if (node != null) {
98             LOG.info("getPluginTestConnection: Successfully connected to {}", node);
99         } else {
100             fail("Connection parameter (" + CONNECTION_TYPE + ") must be active or passive");
101         }
102         return node;
103     }
104
105     public OvsdbClient getTestConnection() throws IOException, InterruptedException, ExecutionException, TimeoutException {
106         Properties props = loadProperties();
107         String addressStr = props.getProperty(SERVER_IPADDRESS);
108         String portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
109         String connectionType = props.getProperty(CONNECTION_TYPE, "active");
110
111         // If the connection type is active, controller connects to the ovsdb-server
112         if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
113             if (addressStr == null) {
114                 fail(usage());
115             }
116
117             InetAddress address;
118             try {
119                 address = InetAddress.getByName(addressStr);
120             } catch (Exception e) {
121                 System.out.println("Unable to resolve " + addressStr);
122                 e.printStackTrace();
123                 return null;
124             }
125
126             Integer port;
127             try {
128                 port = Integer.parseInt(portStr);
129             } catch (NumberFormatException e) {
130                 System.out.println("Invalid port number : " + portStr);
131                 e.printStackTrace();
132                 return null;
133             }
134
135             OvsdbConnection connection = (OvsdbConnection)ServiceHelper.getGlobalInstance(OvsdbConnection.class, this);
136             return connection.connect(address, port);
137         } else if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_PASSIVE)) {
138             ExecutorService executor = Executors.newFixedThreadPool(1);
139             Future<OvsdbClient> passiveConnection = executor.submit(new PassiveListener());
140             return passiveConnection.get(60, TimeUnit.SECONDS);
141         }
142         fail("Connection parameter ("+CONNECTION_TYPE+") must be either active or passive");
143         return null;
144     }
145
146     protected String usage() {
147         return "Integration Test needs a valid connection configuration as follows :\n" +
148                "active connection : mvn -Pintegrationtest -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"+
149                "passive connection : mvn -Pintegrationtest -Dovsdbserver.connection=passive verify\n";
150     }
151
152     public class PassiveListener implements Callable<OvsdbClient>, OvsdbConnectionListener {
153         OvsdbClient client = null;
154         @Override
155         public OvsdbClient call() throws Exception {
156             OvsdbConnection connection = (OvsdbConnection)ServiceHelper.getGlobalInstance(OvsdbConnection.class, this);
157             connection.registerConnectionListener(this);
158             while (client == null) {
159                 Thread.sleep(500);
160             }
161             return client;
162         }
163
164         @Override
165         public void connected(OvsdbClient client) {
166             this.client = client;
167         }
168
169         @Override
170         public void disconnected(OvsdbClient client) {
171             assertEquals(this.client.getConnectionInfo(), client.getConnectionInfo());
172             this.client = null;
173         }
174     }
175
176     public String stateToString(int state) {
177         switch (state) {
178             case Bundle.ACTIVE:
179                 return "ACTIVE";
180             case Bundle.INSTALLED:
181                 return "INSTALLED";
182             case Bundle.RESOLVED:
183                 return "RESOLVED";
184             case Bundle.UNINSTALLED:
185                 return "UNINSTALLED";
186             default:
187                 return "Not CONVERTED";
188         }
189     }
190
191     public void areWeReady(BundleContext bc) throws InterruptedException {
192         if (bundlesReady) {
193             LOG.info("Bundles already loaded");
194             return;
195         }
196         assertNotNull(bc);
197         boolean debugit = false;
198         Bundle b[] = bc.getBundles();
199         for (Bundle element : b) {
200             int state = element.getState();
201             if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
202                 LOG.info("Bundle:" + element.getSymbolicName() + " state:"
203                         + stateToString(state));
204                 debugit = true;
205             }
206         }
207         if (debugit) {
208             LOG.debug("Do some debugging because some bundle is unresolved");
209             Thread.sleep(600000);
210         }
211
212         // Assert if true, if false we are good to go!
213         assertFalse("There is a problem with loading the bundles.", debugit);
214         bundlesReady = true;
215         LOG.info("Bundles loaded");
216     }
217
218     /*
219      * Method adds a log as each test method starts and finishes. This is useful when
220      * the test suite is used because the suites only print a final summary.
221      */
222     @Rule
223     public TestRule watcher = new TestWatcher() {
224         @Override
225         protected void starting(Description description) {
226             LOG.info("TestWatcher: Starting test: {}",
227                      description.getDisplayName());
228         }
229
230         @Override
231         protected void finished(Description description) {
232             LOG.info("TestWatcher: Finished test: {}", description.getDisplayName());
233         }
234     };
235 }