/* * Copyright (c) 2015 Red Hat, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.ovsdb.openstack.netvirt.it; import static org.junit.Assert.fail; import static org.ops4j.pax.exam.CoreOptions.maven; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.Lists; import com.google.common.collect.ObjectArrays; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.inject.Inject; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.karaf.options.LogLevelOption; import org.ops4j.pax.exam.options.MavenUrlReference; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Integration tests for netvirt * * @author Sam Hague (shague@redhat.com) */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerClass.class) public class NetvirtIT extends AbstractMdsalTestBase { private static final Logger LOG = LoggerFactory.getLogger(NetvirtIT.class); private static final int OVSDB_UPDATE_TIMEOUT = 1000; private static DataBroker dataBroker = null; private static String addressStr; private static String portStr; private static String connectionType; private static Boolean setup = false; private static MdsalUtils mdsalUtils = null; private static final String NETVIRT = "org.opendaylight.ovsdb.openstack.net-virt"; private static final String NETVIRTPROVIDERS = "org.opendaylight.ovsdb.openstack.net-virt-providers"; @Inject private BundleContext bundleContext; @Configuration public Option[] config() { return super.config(); } @Override public String getModuleName() { return "openstack.net-virt-providers"; } @Override public String getInstanceName() { return "net-virt-providers-default"; } @Override public MavenUrlReference getFeatureRepo() { return maven() .groupId("org.opendaylight.ovsdb") .artifactId("features-ovsdb") .classifier("features") .type("xml") .versionAsInProject(); } @Override public String getFeatureName() { return "odl-ovsdb-openstack"; } protected String usage() { return "Integration Test needs a valid connection configuration as follows :\n" + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n" + "passive connection : mvn -Dovsdbserver.connection=passive verify\n"; } @Override public Option[] getFeaturesOptions() { return new Option[]{}; } @Override public Option[] getLoggingOptions() { Option[] options; options = new Option[] { editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG, "log4j.logger.org.opendaylight.ovsdb", LogLevelOption.LogLevel.DEBUG.name()), editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG, "log4j.logger.org.opendaylight.ovsdb.lib", LogLevelOption.LogLevel.INFO.name()), /*editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG, "log4j.logger.org.opendaylight.ovsdb.openstack.net-virt", LogLevelOption.LogLevel.DEBUG.name())*/ }; options = ObjectArrays.concat(options, super.getLoggingOptions(), Option.class); return options; } @Override public Option[] getPropertiesOptions() { Properties props = new Properties(System.getProperties()); String addressStr = props.getProperty(NetvirtITConstants.SERVER_IPADDRESS, NetvirtITConstants.DEFAULT_SERVER_IPADDRESS); String portStr = props.getProperty(NetvirtITConstants.SERVER_PORT, NetvirtITConstants.DEFAULT_SERVER_PORT); String connectionType = props.getProperty(NetvirtITConstants.CONNECTION_TYPE, NetvirtITConstants.CONNECTION_TYPE_ACTIVE); LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}", connectionType, addressStr, portStr); Option[] options = new Option[] { editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES, NetvirtITConstants.SERVER_IPADDRESS, addressStr), editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES, NetvirtITConstants.SERVER_PORT, portStr), editConfigurationFilePut(NetvirtITConstants.CUSTOM_PROPERTIES, NetvirtITConstants.CONNECTION_TYPE, connectionType), }; return options; } @Before public void setUp() throws InterruptedException { if (setup == true) { LOG.info("Skipping setUp, already initialized"); return; } try { super.setup(); } catch (Exception e) { e.printStackTrace(); } addressStr = bundleContext.getProperty(NetvirtITConstants.SERVER_IPADDRESS); portStr = bundleContext.getProperty(NetvirtITConstants.SERVER_PORT); connectionType = bundleContext.getProperty(NetvirtITConstants.CONNECTION_TYPE); LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}", connectionType, addressStr, portStr); if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_ACTIVE)) { if (addressStr == null) { fail(usage()); } } isBundleReady(bundleContext, NETVIRT); isBundleReady(bundleContext, NETVIRTPROVIDERS); //dataBroker = getSession().getSALService(DataBroker.class); //Thread.sleep(3000); //dataBroker = OvsdbInventoryServiceImpl.getDataBroker(); for (int i=0; i<10; i++) { dataBroker = org.opendaylight.ovsdb.openstack.netvirt.MdsalUtils.getDatabroker(); if (dataBroker == null) { LOG.warn("NetvirtIT: dataBroker is null"); Thread.sleep(5000); continue; } else { break; } } Assert.assertNotNull("dataBroker should not be null", dataBroker); Thread.sleep(5000); mdsalUtils = new MdsalUtils(dataBroker); setup = true; } /** * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port * 6640. This test will wait for incoming connections for {@link NetvirtITConstants.CONNECTION_INIT_TIMEOUT} ms. * * @throws InterruptedException */ @Test public void testPassiveNode() throws InterruptedException { if (connectionType.equalsIgnoreCase(NetvirtITConstants.CONNECTION_TYPE_PASSIVE)) { //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server. Thread.sleep(NetvirtITConstants.CONNECTION_INIT_TIMEOUT); } } private ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) { InetAddress inetAddress = null; try { inetAddress = InetAddress.getByName(addressStr); } catch (UnknownHostException e) { fail("Could not allocate InetAddress: " + e); } IpAddress address = SouthboundMapper.createIpAddress(inetAddress); PortNumber port = new PortNumber(Integer.parseInt(portStr)); LOG.info("connectionInfo: {}", new ConnectionInfoBuilder() .setRemoteIp(address) .setRemotePort(port) .build()); return new ConnectionInfoBuilder() .setRemoteIp(address) .setRemotePort(port) .build(); } private String connectionInfoToString(final ConnectionInfo connectionInfo) { return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue(); } private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo), SouthboundMapper.createNode(connectionInfo)); Thread.sleep(OVSDB_UPDATE_TIMEOUT); return result; } private Node getOvsdbNode(final ConnectionInfo connectionInfo) { Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, SouthboundMapper.createInstanceIdentifier(connectionInfo)); return node; } private boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo)); Thread.sleep(OVSDB_UPDATE_TIMEOUT); return result; } private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { Assert.assertTrue(addOvsdbNode(connectionInfo)); Node node = getOvsdbNode(connectionInfo); Assert.assertNotNull("Should find OVSDB node after connect", node); LOG.info("Connected to {}", connectionInfoToString(connectionInfo)); return node; } private boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException { Assert.assertTrue(deleteOvsdbNode(connectionInfo)); Node node = getOvsdbNode(connectionInfo); Assert.assertNull("Should not find OVSDB node after disconnect", node); //Assume.assumeNotNull(node); // Using assumeNotNull because there is no assumeNull LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo)); return true; } @Test public void testAddDeleteOvsdbNode() throws InterruptedException { ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); connectOvsdbNode(connectionInfo); Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo)); } @Ignore @Test public void testOpenVSwitchOtherConfig() throws InterruptedException { ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); Node ovsdbNode = connectOvsdbNode(connectionInfo); OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class); Assert.assertNotNull(ovsdbNodeAugmentation); List otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs(); if (otherConfigsList != null) { for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) { if (otherConfig.getOtherConfigKey().equals("local_ip")) { LOG.info("local_ip: {}", otherConfig.getOtherConfigValue()); break; } else { LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue()); } } } else { LOG.info("other_config is not present"); } Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo)); } private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder, final ConnectionInfo connectionInfo) { InstanceIdentifier connectionNodePath = SouthboundMapper.createInstanceIdentifier(connectionInfo); ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath)); } private List createMdsalProtocols() { List protocolList = new ArrayList(); ImmutableBiMap> mapper = SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse(); protocolList.add(new ProtocolEntryBuilder(). setProtocol((Class) mapper.get("OpenFlow13")).build()); return protocolList; } private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() { OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder(); ovsdbTerminationPointAugmentationBuilder.setInterfaceType( new InterfaceTypeEntryBuilder() .setInterfaceType( SouthboundMapper.createInterfaceType("internal")) .build().getInterfaceType()); return ovsdbTerminationPointAugmentationBuilder; } private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName, final OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder) throws InterruptedException { InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId); NodeBuilder portNodeBuilder = new NodeBuilder(); NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid); portNodeBuilder.setNodeId(portNodeId); TerminationPointBuilder entry = new TerminationPointBuilder(); entry.setKey(new TerminationPointKey(new TpId(portName))); entry.addAugmentation( OvsdbTerminationPointAugmentation.class, ovsdbTerminationPointAugmentationBuilder.build()); portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build())); boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portNodeBuilder.build()); Thread.sleep(OVSDB_UPDATE_TIMEOUT); return result; } /* * base method for adding test bridges. Other helper methods used to create bridges should utilize this method. * * @param connectionInfo * @param bridgeIid if passed null, one is created * @param bridgeName cannot be null * @param bridgeNodeId if passed null, one is created based on bridgeIid * @param setProtocolEntries toggles whether default protocol entries are set for the bridge * @param failMode toggles whether default fail mode is set for the bridge * @param setManagedBy toggles whether to setManagedBy for the bridge * @param dpType if passed null, this parameter is ignored * @param externalIds if passed null, this parameter is ignored * @param otherConfig if passed null, this parameter is ignored * @return success of bridge addition * @throws InterruptedException */ private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier bridgeIid, final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries, final Class failMode, final boolean setManagedBy, final Class dpType, final List externalIds, final List otherConfigs) throws InterruptedException { NodeBuilder bridgeNodeBuilder = new NodeBuilder(); if (bridgeIid == null) { bridgeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)); } if (bridgeNodeId == null) { bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid); } bridgeNodeBuilder.setNodeId(bridgeNodeId); OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder(); ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName)); if (setProtocolEntries) { ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols()); } if (failMode != null) { ovsdbBridgeAugmentationBuilder.setFailMode(failMode); } if (setManagedBy) { setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo); } if (dpType != null) { ovsdbBridgeAugmentationBuilder.setDatapathType(dpType); } if (externalIds != null) { ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds); } if (otherConfigs != null) { ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs); } bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build()); LOG.debug("Built with the intent to store bridge data {}", ovsdbBridgeAugmentationBuilder.toString()); boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build()); Thread.sleep(OVSDB_UPDATE_TIMEOUT); return result; } private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName) throws InterruptedException { return addBridge(connectionInfo, null, bridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null); } private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) { return getBridge(connectionInfo, NetvirtITConstants.BRIDGE_NAME); } /** * Extract the store type data store contents for the particular bridge identified by * bridgeName. * * @param connectionInfo * @param bridgeName * @param store defined by the LogicalDatastoreType enumeration * @return store type data store contents */ private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) { Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store); Assert.assertNotNull(bridgeNode); OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class); Assert.assertNotNull(ovsdbBridgeAugmentation); return ovsdbBridgeAugmentation; } /** * extract the LogicalDataStoreType.OPERATIONAL type data store contents for the particular bridge * identified by bridgeName * * @param connectionInfo * @param bridgeName * @see NetvirtIT.getBridge(ConnectionInfo, String, LogicalDatastoreType) * @return LogicalDatastoreType.OPERATIONAL type data store contents */ private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) { return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL); } /** * Extract the node contents from store type data store for the * bridge identified by bridgeName * * @param connectionInfo * @param bridgeName * @param store defined by the LogicalDatastoreType enumeration * @return store type data store contents */ private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) { InstanceIdentifier bridgeIid = SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName)); return mdsalUtils.read(store, bridgeIid); } /** * Extract the node contents from LogicalDataStoreType.OPERATIONAL data store for the * bridge identified by bridgeName * * @param connectionInfo * @param bridgeName * @return LogicalDatastoreType.OPERATIONAL type data store contents */ private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) { return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL); } private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException { return deleteBridge(connectionInfo, NetvirtITConstants.BRIDGE_NAME); } private boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName) throws InterruptedException { boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, SouthboundMapper.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName))); Thread.sleep(OVSDB_UPDATE_TIMEOUT); return result; } private InstanceIdentifier getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) { return SouthboundMapper.createInstanceIdentifier(connectionInfo, bridge.getBridgeName()); } /** * isBundleReady is used to check if the requested bundle is Active */ public void isBundleReady(BundleContext bundleContext, String bundleName) throws InterruptedException { boolean ready = false; while (!ready) { int state = Bundle.UNINSTALLED; Bundle[] bundles = bundleContext.getBundles(); for (Bundle element : bundles) { if (element.getSymbolicName().equals(bundleName)) { state = element.getState(); LOG.info(">>>>> bundle is ready {}", bundleName); break; } } if (state != Bundle.ACTIVE) { LOG.info(">>>>> bundle not ready {}", bundleName); Thread.sleep(5000); } else { ready = true; } } } private void netVirtAddPort(ConnectionInfo connectionInfo) throws InterruptedException { OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME); Assert.assertNotNull(bridge); NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundMapper.createInstanceIdentifier( connectionInfo, bridge.getBridgeName())); OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = createGenericOvsdbTerminationPointAugmentationBuilder(); String portName = NetvirtITConstants.PORT_NAME; ovsdbTerminationBuilder.setName(portName); Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); Assert.assertNotNull(terminationPointNode); } /** * Test for basic southbound events to netvirt. *
The test will:
     * - connect to an OVSDB node and verify it is added to operational
     * - then verify that br-int was created on the node and stored in operational
     * - a port is then added to the bridge to verify that it is ignored by netvirt
     * - remove the bridge
     * - remove the node and verify it is not in operational
     * 
* @throws InterruptedException */ // TODO add verification of flows @Test public void testNetVirt() throws InterruptedException { ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr); connectOvsdbNode(connectionInfo); Thread.sleep(10000); netVirtAddPort(connectionInfo); Thread.sleep(10000); Assert.assertTrue(deleteBridge(connectionInfo, NetvirtITConstants.INTEGRATION_BRIDGE_NAME)); Thread.sleep(10000); Assert.assertTrue(disconnectOvsdbNode(connectionInfo)); } @Test public void testNetVirt2() throws InterruptedException { Thread.sleep(60000); } }