2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.it;
10 import static org.junit.Assert.assertNotNull;
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13 import static org.ops4j.pax.exam.CoreOptions.composite;
14 import static org.ops4j.pax.exam.CoreOptions.maven;
15 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
16 import static org.ops4j.pax.exam.CoreOptions.vmOption;
17 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
18 import static org.ops4j.pax.exam.MavenUtils.asInProject;
19 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
20 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
21 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
23 import java.util.Properties;
24 import java.util.concurrent.atomic.AtomicBoolean;
25 import javax.inject.Inject;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
32 import org.opendaylight.netvirt.it.NetvirtITConstants.DefaultFlow;
33 import org.opendaylight.netvirt.utils.netvirt.it.utils.FlowITUtil;
34 import org.opendaylight.netvirt.utils.netvirt.it.utils.NetITUtil;
35 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
36 import org.opendaylight.ovsdb.utils.ovsdb.it.utils.DockerOvs;
37 import org.opendaylight.ovsdb.utils.ovsdb.it.utils.NodeInfo;
38 import org.opendaylight.ovsdb.utils.ovsdb.it.utils.OvsdbItUtils;
39 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.ops4j.pax.exam.Configuration;
48 import org.ops4j.pax.exam.Option;
49 import org.ops4j.pax.exam.junit.PaxExam;
50 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
51 import org.ops4j.pax.exam.options.MavenUrlReference;
52 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
53 import org.ops4j.pax.exam.spi.reactors.PerClass;
54 import org.ops4j.pax.exam.util.Filter;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
60 * Integration tests for Netvirt
64 @RunWith(PaxExam.class)
65 @ExamReactorStrategy(PerClass.class)
66 public class NetvirtIT extends AbstractMdsalTestBase {
68 private static final Logger LOG = LoggerFactory.getLogger(NetvirtIT.class);
69 private static OvsdbItUtils itUtils;
70 private static MdsalUtils mdsalUtils = null;
71 private static SouthboundUtils southboundUtils;
72 private static FlowITUtil flowITUtil;
73 private static String addressStr;
74 private static String portStr;
75 private static String connectionType;
76 private static String controllerStr;
77 private static AtomicBoolean setup = new AtomicBoolean(false);
78 private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
79 @Inject @Filter(timeout=60000)
80 private static DataBroker dataBroker = null;
83 public MavenUrlReference getFeatureRepo() {
85 .groupId("org.opendaylight.netvirt")
86 .artifactId("vpnservice-features")
87 .classifier("features")
89 .versionAsInProject();
93 public String getFeatureName() {
94 return "odl-netvirt-openstack-it";
99 public Option[] config() {
100 Option[] ovsProps = super.config();
101 Option[] propertiesOptions = DockerOvs.getSysPropOptions();
102 Option[] otherOptions = getOtherOptions();
103 Option[] options = new Option[ovsProps.length + propertiesOptions.length + otherOptions.length];
104 System.arraycopy(ovsProps, 0, options, 0, ovsProps.length);
105 System.arraycopy(propertiesOptions, 0, options, ovsProps.length, propertiesOptions.length);
106 System.arraycopy(otherOptions, 0, options, ovsProps.length + propertiesOptions.length,
107 otherOptions.length);
111 private Option[] getOtherOptions() {
112 return new Option[] {
114 mavenBundle("org.opendaylight.netvirt", "utils.mdsal-openflow")
115 .version(asInProject())
118 // mavenBundle("org.opendaylight.netvirt", "utils.config")
119 // .version(asInProject())
121 configureConsole().startLocalConsole(),
122 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
128 public Option getLoggingOption() {
130 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
131 logConfiguration(NetvirtIT.class),
132 LogLevel.INFO.name()),
133 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
134 "log4j.logger.org.opendaylight.netvirt",
135 LogLevel.DEBUG.name()),
136 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
137 "log4j.logger.org.opendaylight.openflowjava.protocol.impl.util.ListDeserializer",
138 LogLevel.ERROR.name()),
139 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
140 "log4j.logger.org.opendaylight.controller.configpusherfeature.internal.FeatureConfigPusher",
141 LogLevel.ERROR.name()),
142 // editConfigurationFilePut(NetvirtITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
143 // "log4j.logger.org.opendaylight.ovsdb",
144 // LogLevel.TRACE.name()),
145 super.getLoggingOption());
150 public void setup() throws InterruptedException {
152 LOG.info("Skipping setUp, already initialized");
158 } catch (Exception e) {
159 LOG.warn("Failed to setup test", e);
160 fail("Failed to setup test: " + e);
163 Thread.sleep(10*1000);
166 assertNotNull("dataBroker should not be null", dataBroker);
167 itUtils = new OvsdbItUtils(dataBroker);
168 mdsalUtils = new MdsalUtils(dataBroker);
169 assertNotNull("mdsalUtils should not be null", mdsalUtils);
170 southboundUtils = new SouthboundUtils(mdsalUtils);
171 assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, this.getNetvirtTopology());
172 flowITUtil = new FlowITUtil(dataBroker);
177 private void getProperties() {
178 Properties props = System.getProperties();
179 addressStr = props.getProperty(NetvirtITConstants.SERVER_IPADDRESS);
180 portStr = props.getProperty(NetvirtITConstants.SERVER_PORT, NetvirtITConstants.DEFAULT_SERVER_PORT);
181 connectionType = props.getProperty(NetvirtITConstants.CONNECTION_TYPE, "active");
182 controllerStr = props.getProperty(NetvirtITConstants.CONTROLLER_IPADDRESS, "0.0.0.0");
183 String userSpaceEnabled = props.getProperty(NetvirtITConstants.USERSPACE_ENABLED, "no");
184 LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, controller ip: {}, " +
185 "userspace.enabled: {}",
186 connectionType, addressStr, portStr, controllerStr, userSpaceEnabled);
189 private Boolean getNetvirtTopology() {
190 LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
191 Boolean found = false;
192 TopologyId topologyId = new TopologyId(NETVIRT_TOPOLOGY_ID);
193 InstanceIdentifier<Topology> path =
194 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
195 for(int i = 0; i < 60; ++i) {
196 Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
197 if(topology != null) {
198 LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
199 found = Boolean.valueOf(true);
203 LOG.info("getNetvirtTopology: still looking ({})...", i);
207 } catch (InterruptedException var7) {
208 LOG.warn("Interrupted while waiting for {}", "netvirt:1", var7);
215 private void validateDefaultFlows(long datapathId, int timeout){
216 LOG.info("Validating default flows");
217 for (DefaultFlow defaultFlow : DefaultFlow.values()){
219 flowITUtil.verifyFlowByFields(datapathId, defaultFlow.getFlowId(), defaultFlow.getTableId(), timeout);
220 } catch (Exception e){
221 LOG.error("Failed to verify flow id : {}", defaultFlow.getFlowId());
228 * Test for basic southbound events to netvirt.
229 * <pre>The test will:
230 * - connect to an OVSDB node and verify it is added to operational
231 * - then verify that br-int was created on the node and stored in operational
232 * - a port is then added to the bridge to verify that it is ignored by netvirt
233 * - remove the bridge
234 * - remove the node and verify it is not in operational
236 * @throws InterruptedException
239 public void testNetVirt() throws InterruptedException {
240 try(DockerOvs ovs = new DockerOvs()) {
241 ConnectionInfo connectionInfo = SouthboundUtils.
242 getConnectionInfo(ovs.getOvsdbAddress(0), ovs.getOvsdbPort(0));
243 NodeInfo nodeInfo = itUtils.createNodeInfo(connectionInfo, null);
246 //validate default flows
247 validateDefaultFlows(nodeInfo.datapathId, 60*1000);
249 LOG.info("testNetVirt: should be connected: {}", nodeInfo.ovsdbNode.getNodeId());
251 southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, NetvirtITConstants.PORT_NAME,
252 "internal", null, null, 0L);
255 OvsdbTerminationPointAugmentation terminationPointOfBridge = southboundUtils.
256 getTerminationPointOfBridge(nodeInfo.bridgeNode, NetvirtITConstants.PORT_NAME);
257 assertNotNull("Did not find " + NetvirtITConstants.PORT_NAME, terminationPointOfBridge);
259 nodeInfo.disconnect();
260 } catch (Exception e) {
261 LOG.error("testNetVirt: Exception thrown by OvsDocker.OvsDocker()", e);
268 * Test a basic neutron use case. This test constructs a Neutron network, subnet, and two "vm" ports
269 * and validates that the correct flows are installed on OVS. Then it pings from one VM port to the other.
270 * @throws InterruptedException if we're interrupted while waiting for some mdsal operation to complete
273 public void testNeutronNet() throws InterruptedException {
274 LOG.warn("testNeutronNet: starting test");
275 try(DockerOvs ovs = new DockerOvs()) {
276 ConnectionInfo connectionInfo = SouthboundUtils.
277 getConnectionInfo(ovs.getOvsdbAddress(0), ovs.getOvsdbPort(0));
278 NodeInfo nodeInfo = itUtils.createNodeInfo(connectionInfo, null);
281 //validate default flows
282 validateDefaultFlows(nodeInfo.datapathId, 60*1000);
284 //create the neutron objects
285 NetITUtil net = new NetITUtil(ovs, southboundUtils, mdsalUtils);
286 net.createNetworkAndSubnet();
287 String port1 = net.createPort(nodeInfo.bridgeNode);
288 String port2 = net.createPort(nodeInfo.bridgeNode);
292 //ovs interface configuration for running the ping test
293 net.preparePortForPing(port1);
294 net.preparePortForPing(port2);
297 net.ping(port1, port2);
299 //clean the neutron object and disconnect from odl
301 nodeInfo.disconnect();
302 } catch (Exception e) {
303 LOG.error("testNeutronNet: Exception thrown by OvsDocker.OvsDocker()", e);