Add UT for SouthboundMapper and SouthboundProvider
[netvirt.git] / openstack / net-virt-it / src / test / java / org / opendaylight / ovsdb / openstack / netvirt / it / NetvirtIT.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.openstack.netvirt.it;
9
10 import static org.junit.Assert.fail;
11 import static org.ops4j.pax.exam.CoreOptions.composite;
12 import static org.ops4j.pax.exam.CoreOptions.maven;
13 import static org.ops4j.pax.exam.CoreOptions.when;
14 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
15 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
17 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
18
19 import com.google.common.collect.ImmutableBiMap;
20 import com.google.common.collect.Lists;
21 import com.google.common.collect.ObjectArrays;
22
23 import java.io.File;
24 import java.net.InetAddress;
25 import java.net.NetworkInterface;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.Enumeration;
29 import java.util.List;
30 import java.util.Properties;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import javax.inject.Inject;
33 import org.junit.Assert;
34 import org.junit.Before;
35 import org.junit.Ignore;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
41 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
42 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.ops4j.pax.exam.Configuration;
63 import org.ops4j.pax.exam.Option;
64 import org.ops4j.pax.exam.junit.PaxExam;
65 import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
66 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
67 import org.ops4j.pax.exam.options.MavenUrlReference;
68 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
69 import org.ops4j.pax.exam.spi.reactors.PerClass;
70 import org.osgi.framework.Bundle;
71 import org.osgi.framework.BundleContext;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 /**
76  * Integration tests for netvirt
77  *
78  * @author Sam Hague (shague@redhat.com)
79  */
80 @RunWith(PaxExam.class)
81 @ExamReactorStrategy(PerClass.class)
82 public class NetvirtIT extends AbstractMdsalTestBase {
83     private static final Logger LOG = LoggerFactory.getLogger(NetvirtIT.class);
84     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
85     private static DataBroker dataBroker = null;
86     private static String addressStr;
87     private static String portStr;
88     private static String connectionType;
89     private static AtomicBoolean setup = new AtomicBoolean(false);
90     private static MdsalUtils mdsalUtils = null;
91     private static Southbound southbound = null;
92     private static final String NETVIRT = "org.opendaylight.ovsdb.openstack.net-virt";
93     private static final String NETVIRTPROVIDERS = "org.opendaylight.ovsdb.openstack.net-virt-providers";
94
95     // TODO Constants copied frmo AbstractConfigTestBase, need to be removed (see TODO below)
96     private static final String PAX_EXAM_UNPACK_DIRECTORY = "target/exam";
97     private static final String KARAF_DEBUG_PORT = "5005";
98     private static final String KARAF_DEBUG_PROP = "karaf.debug";
99     private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
100
101     @Inject
102     private BundleContext bundleContext;
103
104     @Configuration
105     public Option[] config() {
106         // TODO Figure out how to use the parent Karaf setup, then just use super.config()
107         Option[] options = new Option[] {
108                 when(Boolean.getBoolean(KARAF_DEBUG_PROP))
109                         .useOptions(KarafDistributionOption.debugConfiguration(KARAF_DEBUG_PORT, true)),
110                 karafDistributionConfiguration().frameworkUrl(getKarafDistro())
111                         .unpackDirectory(new File(PAX_EXAM_UNPACK_DIRECTORY))
112                         .useDeployFolder(false),
113                 when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
114                 // Works only if we don't specify the feature repo and name
115                 getLoggingOption()};
116         Option[] propertyOptions = getPropertiesOptions();
117         Option[] combinedOptions = new Option[options.length + propertyOptions.length];
118         System.arraycopy(options, 0, combinedOptions, 0, options.length);
119         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
120         return combinedOptions;
121     }
122
123     @Override
124     public String getKarafDistro() {
125         return maven()
126                 .groupId("org.opendaylight.ovsdb")
127                 .artifactId("karaf")
128                 .versionAsInProject()
129                 .type("zip")
130                 .getURL();
131     }
132
133     @Override
134     public String getModuleName() {
135         return "openstack.net-virt-providers";
136     }
137
138     @Override
139     public String getInstanceName() {
140         return "net-virt-providers-default";
141     }
142
143     @Override
144     public MavenUrlReference getFeatureRepo() {
145         return maven()
146                 .groupId("org.opendaylight.ovsdb")
147                 .artifactId("features-ovsdb")
148                 .classifier("features")
149                 .type("xml")
150                 .versionAsInProject();
151     }
152
153     @Override
154     public String getFeatureName() {
155         return "odl-ovsdb-openstack";
156     }
157
158     protected String usage() {
159         return "Integration Test needs a valid connection configuration as follows :\n"
160                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
161                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
162     }
163
164     @Override
165     public Option getLoggingOption() {
166         return composite(
167                 editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
168                         "log4j.logger.org.opendaylight.ovsdb",
169                         LogLevelOption.LogLevel.DEBUG.name()),
170                 editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
171                         "log4j.logger.org.opendaylight.ovsdb.lib",
172                         LogLevelOption.LogLevel.INFO.name()),
173                 super.getLoggingOption());
174             /*editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
175                     "log4j.logger.org.opendaylight.ovsdb.openstack.net-virt",
176                     LogLevelOption.LogLevel.DEBUG.name())*/
177     }
178
179     private Option[] getPropertiesOptions() {
180         Properties props = new Properties(System.getProperties());
181         String addressStr = props.getProperty(NetvirtITConstants.SERVER_IPADDRESS,
182                 NetvirtITConstants.DEFAULT_SERVER_IPADDRESS);
183         String portStr = props.getProperty(NetvirtITConstants.SERVER_PORT,
184                 NetvirtITConstants.DEFAULT_SERVER_PORT);
185         String connectionType = props.getProperty(NetvirtITConstants.CONNECTION_TYPE,
186                 NetvirtITConstants.CONNECTION_TYPE_ACTIVE);
187
188         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
189                 connectionType, addressStr, portStr);
190
191         Option[] options = new Option[] {
192                 editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES,
193                         NetvirtITConstants.SERVER_IPADDRESS, addressStr),
194                 editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES,
195                         NetvirtITConstants.SERVER_PORT, portStr),
196                 editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES,
197                         NetvirtITConstants.CONNECTION_TYPE, connectionType),
198         };
199         return options;
200     }
201
202     @Before
203     @Override
204     public void setup() throws InterruptedException {
205         if (setup.get()) {
206             LOG.info("Skipping setUp, already initialized");
207             return;
208         }
209
210         try {
211             super.setup();
212         } catch (Exception e) {
213             e.printStackTrace();
214         }
215
216         addressStr = bundleContext.getProperty(NetvirtITConstants.SERVER_IPADDRESS);
217         portStr = bundleContext.getProperty(NetvirtITConstants.SERVER_PORT);
218         connectionType = bundleContext.getProperty(NetvirtITConstants.CONNECTION_TYPE);
219
220         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
221                 connectionType, addressStr, portStr);
222         if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_ACTIVE)) {
223             if (addressStr == null) {
224                 fail(usage());
225             }
226         }
227
228         isBundleReady(bundleContext, NETVIRT);
229         isBundleReady(bundleContext, NETVIRTPROVIDERS);
230
231         //dataBroker = getSession().getSALService(DataBroker.class);
232         //Thread.sleep(3000);
233         //dataBroker = OvsdbInventoryServiceImpl.getDataBroker();
234         for (int i=0; i<20; i++) {
235             southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
236             if (southbound != null) {
237                 dataBroker = southbound.getDatabroker();
238                 if (dataBroker != null) {
239                     break;
240                 }
241             }
242             LOG.warn("NetvirtIT: dataBroker is null");
243             Thread.sleep(5000);
244         }
245         Assert.assertNotNull("dataBroker should not be null", dataBroker);
246         Thread.sleep(5000);
247
248         mdsalUtils = new MdsalUtils(dataBroker);
249         setup.set(true);
250     }
251
252     /**
253      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
254      * 6640. This test will wait for incoming connections for {@link NetvirtITConstants.CONNECTION_INIT_TIMEOUT} ms.
255      *
256      * @throws InterruptedException
257      */
258     @Test
259     public void testPassiveNode() throws InterruptedException {
260         if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_PASSIVE)) {
261             //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
262             Thread.sleep(NetvirtITConstants.CONNECTION_INIT_TIMEOUT);
263         }
264     }
265
266     private ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
267         InetAddress inetAddress = null;
268         try {
269             inetAddress = InetAddress.getByName(addressStr);
270         } catch (UnknownHostException e) {
271             fail("Could not allocate InetAddress: " + e);
272         }
273
274         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
275         PortNumber port = new PortNumber(Integer.parseInt(portStr));
276
277         LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
278                 .setRemoteIp(address)
279                 .setRemotePort(port)
280                 .build());
281         return new ConnectionInfoBuilder()
282                        .setRemoteIp(address)
283                        .setRemotePort(port)
284                        .build();
285     }
286
287     private String connectionInfoToString(final ConnectionInfo connectionInfo) {
288         return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
289     }
290
291     private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
292         boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
293                 SouthboundMapper.createInstanceIdentifier(connectionInfo),
294                 SouthboundMapper.createNode(connectionInfo));
295         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
296         return result;
297     }
298
299     private Node getOvsdbNode(final ConnectionInfo connectionInfo) {
300         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
301                 SouthboundMapper.createInstanceIdentifier(connectionInfo));
302         return node;
303     }
304
305     private boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
306         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
307                 SouthboundMapper.createInstanceIdentifier(connectionInfo));
308         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
309         return result;
310     }
311
312     private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
313         Assert.assertTrue(addOvsdbNode(connectionInfo));
314         Node node = getOvsdbNode(connectionInfo);
315         Assert.assertNotNull("Should find OVSDB node after connect", node);
316         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
317         return node;
318     }
319
320     private boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
321         Assert.assertTrue(deleteOvsdbNode(connectionInfo));
322         Node node = getOvsdbNode(connectionInfo);
323         Assert.assertNull("Should not find OVSDB node after disconnect", node);
324         //Assume.assumeNotNull(node); // Using assumeNotNull because there is no assumeNull
325         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
326         return true;
327     }
328
329     private String getLocalControllerHostIpAddress() {
330         String ipaddress = null;
331         try{
332             for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
333                  ifaces.hasMoreElements();) {
334                 NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
335
336                 for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
337                     InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
338                     if (!inetAddr.isLoopbackAddress()) {
339                         if (inetAddr.isSiteLocalAddress()) {
340                             ipaddress = inetAddr.getHostAddress();
341                             break;
342                         }
343                     }
344                 }
345             }
346         }catch (Exception e){
347             LOG.warn("Exception while fetching local host ip address ",e);
348         }
349         return ipaddress;
350     }
351
352     private String getControllerTarget(Node ovsdbNode) {
353         String target = null;
354         String ipAddr = null;
355         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
356         ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
357         LOG.info("connectionInfo: {}", connectionInfo);
358         if (connectionInfo != null && connectionInfo.getLocalIp() != null) {
359             ipAddr = new String(connectionInfo.getLocalIp().getValue());
360         }
361         if (ipAddr == null) {
362             ipAddr = getLocalControllerHostIpAddress();
363         }
364
365         if (ipAddr != null) {
366             target = NetvirtITConstants.OPENFLOW_CONNECTION_PROTOCOL + ":"
367                     + ipAddr + ":" + NetvirtITConstants.DEFAULT_OPENFLOW_PORT;
368         }
369
370         return target;
371     }
372
373     //@Ignore//
374     @Test
375     public void testAddDeleteOvsdbNode() throws InterruptedException {
376         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
377         connectOvsdbNode(connectionInfo);
378         ControllerEntry controllerEntry;
379         for (int i = 0; i < 10; i++) {
380             Node ovsdbNode = getOvsdbNode(connectionInfo);
381             Assert.assertNotNull("ovsdb node not found", ovsdbNode);
382             String controllerTarget = getControllerTarget(ovsdbNode);
383             Assert.assertNotNull("Failed to get controller target", controllerTarget);
384             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
385             Assert.assertNotNull(bridge);
386             Assert.assertNotNull(bridge.getControllerEntry());
387             controllerEntry = bridge.getControllerEntry().iterator().next();
388             Assert.assertEquals(controllerTarget, controllerEntry.getTarget().getValue());
389             if (controllerEntry.isIsConnected()) {
390                 Assert.assertTrue(controllerEntry.isIsConnected());
391                 break;
392             }
393             Thread.sleep(1000);
394         }
395
396         Assert.assertTrue(deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME));
397         Thread.sleep(1000);
398         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
399     }
400
401     @Ignore
402     @Test
403     public void testOpenVSwitchOtherConfig() throws InterruptedException {
404         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
405         Node ovsdbNode = connectOvsdbNode(connectionInfo);
406         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
407         Assert.assertNotNull(ovsdbNodeAugmentation);
408         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
409         if (otherConfigsList != null) {
410             for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
411                 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
412                     LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
413                     break;
414                 } else {
415                     LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
416                 }
417             }
418         } else {
419             LOG.info("other_config is not present");
420         }
421         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
422         //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
423     }
424
425     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
426                               final ConnectionInfo connectionInfo) {
427         InstanceIdentifier<Node> connectionNodePath = SouthboundMapper.createInstanceIdentifier(connectionInfo);
428         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
429     }
430
431     private List<ProtocolEntry> createMdsalProtocols() {
432         List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
433         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
434                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
435         protocolList.add(new ProtocolEntryBuilder().
436                 setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
437         return protocolList;
438     }
439
440     private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() {
441         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder =
442                 new OvsdbTerminationPointAugmentationBuilder();
443         ovsdbTerminationPointAugmentationBuilder.setInterfaceType(
444                 new InterfaceTypeEntryBuilder()
445                         .setInterfaceType(
446                                 SouthboundMapper.createInterfaceType("internal"))
447                         .build().getInterfaceType());
448         return ovsdbTerminationPointAugmentationBuilder;
449     }
450
451     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
452             final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder)
453         throws InterruptedException {
454
455         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
456         NodeBuilder portNodeBuilder = new NodeBuilder();
457         NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid);
458         portNodeBuilder.setNodeId(portNodeId);
459         TerminationPointBuilder entry = new TerminationPointBuilder();
460         entry.setKey(new TerminationPointKey(new TpId(portName)));
461         entry.addAugmentation(
462                 OvsdbTerminationPointAugmentation.class,
463                 ovsdbTerminationPointAugmentationBuilder.build());
464         portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build()));
465         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
466                 portIid, portNodeBuilder.build());
467         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
468         return result;
469     }
470
471     /*
472      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
473      *
474      * @param connectionInfo
475      * @param bridgeIid if passed null, one is created
476      * @param bridgeName cannot be null
477      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
478      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
479      * @param failMode toggles whether default fail mode is set for the bridge
480      * @param setManagedBy toggles whether to setManagedBy for the bridge
481      * @param dpType if passed null, this parameter is ignored
482      * @param externalIds if passed null, this parameter is ignored
483      * @param otherConfig if passed null, this parameter is ignored
484      * @return success of bridge addition
485      * @throws InterruptedException
486      */
487     private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
488             final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
489             final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
490             final Class<? extends DatapathTypeBase> dpType,
491             final List<BridgeExternalIds> externalIds,
492             final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
493
494         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
495         if (bridgeIid == null) {
496             bridgeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
497         }
498         if (bridgeNodeId == null) {
499             bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
500         }
501         bridgeNodeBuilder.setNodeId(bridgeNodeId);
502         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
503         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
504         if (setProtocolEntries) {
505             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
506         }
507         if (failMode != null) {
508             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
509         }
510         if (setManagedBy) {
511             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
512         }
513         if (dpType != null) {
514             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
515         }
516         if (externalIds != null) {
517             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
518         }
519         if (otherConfigs != null) {
520             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
521         }
522         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
523         LOG.debug("Built with the intent to store bridge data {}",
524                 ovsdbBridgeAugmentationBuilder.toString());
525         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
526                 bridgeIid, bridgeNodeBuilder.build());
527         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
528         return result;
529     }
530
531     private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
532         throws InterruptedException {
533
534         return addBridge(connectionInfo, null, bridgeName, null, true,
535                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null);
536     }
537
538     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
539         return getBridge(connectionInfo, NetvirtITConstants.BRIDGE_NAME);
540     }
541
542     /**
543      * Extract the <code>store</code> type data store contents for the particular bridge identified by
544      * <code>bridgeName</code>.
545      *
546      * @param connectionInfo
547      * @param bridgeName
548      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
549      * @return <code>store</code> type data store contents
550      */
551     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
552             LogicalDatastoreType store) {
553         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
554         Assert.assertNotNull(bridgeNode);
555         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
556         Assert.assertNotNull(ovsdbBridgeAugmentation);
557         return ovsdbBridgeAugmentation;
558     }
559
560     /**
561      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
562      * identified by <code>bridgeName</code>
563      *
564      * @param connectionInfo
565      * @param bridgeName
566      * @see <code>NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
567      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
568      */
569     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
570         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
571     }
572
573     /**
574      * Extract the node contents from <code>store</code> type data store for the
575      * bridge identified by <code>bridgeName</code>
576      *
577      * @param connectionInfo
578      * @param bridgeName
579      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
580      * @return <code>store</code> type data store contents
581      */
582     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
583         InstanceIdentifier<Node> bridgeIid =
584                 SouthboundMapper.createInstanceIdentifier(connectionInfo,
585                     new OvsdbBridgeName(bridgeName));
586         return mdsalUtils.read(store, bridgeIid);
587     }
588
589     /**
590      * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
591      * bridge identified by <code>bridgeName</code>
592      *
593      * @param connectionInfo
594      * @param bridgeName
595      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
596      */
597     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
598         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
599     }
600
601     private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException {
602         return deleteBridge(connectionInfo, NetvirtITConstants.BRIDGE_NAME);
603     }
604
605     private boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName)
606         throws InterruptedException {
607
608         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
609                 SouthboundMapper.createInstanceIdentifier(connectionInfo,
610                         new OvsdbBridgeName(bridgeName)));
611         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
612         return result;
613     }
614
615     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
616         return SouthboundMapper.createInstanceIdentifier(connectionInfo,
617             bridge.getBridgeName());
618     }
619
620     /**
621      * isBundleReady is used to check if the requested bundle is Active
622      */
623     public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException {
624         boolean ready = false;
625
626         while (!ready) {
627             int state = Bundle.UNINSTALLED;
628             Bundle[] bundles = bundleContext.getBundles();
629             for (Bundle element : bundles) {
630                 if (element.getSymbolicName().equals(bundleName)) {
631                     state = element.getState();
632                     LOG.info(">>>>> bundle is ready {}", bundleName);
633                     break;
634                 }
635             }
636             if (state != Bundle.ACTIVE) {
637                 LOG.info(">>>>> bundle not ready {}", bundleName);
638                 Thread.sleep(5000);
639             } else {
640                 ready = true;
641             }
642         }
643     }
644
645     private void netVirtAddPort(ConnectionInfo connectionInfo) throws InterruptedException {
646         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME);
647         Assert.assertNotNull(bridge);
648         NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier(
649                 connectionInfo, bridge.getBridgeName()));
650         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
651                 createGenericOvsdbTerminationPointAugmentationBuilder();
652         String portName = NetvirtITConstants.PORT_NAME;
653         ovsdbTerminationBuilder.setName(portName);
654         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
655         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
656         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
657         Assert.assertNotNull(terminationPointNode);
658     }
659
660     /**
661      * Test for basic southbound events to netvirt.
662      * <pre>The test will:
663      * - connect to an OVSDB node and verify it is added to operational
664      * - then verify that br-int was created on the node and stored in operational
665      * - a port is then added to the bridge to verify that it is ignored by netvirt
666      * - remove the bridge
667      * - remove the node and verify it is not in operational
668      * </pre>
669      * @throws InterruptedException
670      */
671     // TODO add verification of flows
672     //@Ignore //
673     @Test
674     public void testNetVirt() throws InterruptedException {
675         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
676         connectOvsdbNode(connectionInfo);
677         Thread.sleep(10000);
678         netVirtAddPort(connectionInfo);
679         Thread.sleep(10000);
680         Assert.assertTrue(deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME));
681         Thread.sleep(10000);
682         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
683     }
684
685     @Ignore
686     @Test
687     public void testNetVirt2() throws InterruptedException {
688         Thread.sleep(60000);
689     }
690
691     @Test
692     public void testReadOvsdbTopologyNodes() throws InterruptedException {
693         Thread.sleep(10000);
694         List<Node> ovsdbNodes = southbound.readOvsdbTopologyNodes();
695         for (Node node : ovsdbNodes) {
696             LOG.info(">>>>> node: {}", node);
697         }
698     }
699 }