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
9 package org.opendaylight.netvirt.utils.netvirt.it.utils;
11 import org.junit.Assert;
12 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
13 import org.opendaylight.ovsdb.utils.ovsdb.it.utils.DockerOvs;
14 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
15 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
17 import java.io.IOException;
20 * This class adds the ability to issue pings from one port to another to its base class, NeutronNetItUtil.
21 * Please see NetvirtIT#testNeutronNet for an example of how this class is used
22 * N.B. At this point this class only supports DockerOvs runs where the docker-compose file runs a single
23 * docker container with OVS. A little work will need to be invested to extend this functionality to support
24 * configuring "ping-ability" on multiple docker containers.
26 public class PingableNeutronNetItUtil extends NeutronNetItUtil {
28 private static final int DEFAULT_WAIT = 30 * 1000;
29 private DockerOvs dockerOvs;
30 private final Boolean isUserSpace;
32 public PingableNeutronNetItUtil(DockerOvs dockerOvs, SouthboundUtils southboundUtils, String tenantId,
33 Boolean isUserSpace) {
34 super(southboundUtils, tenantId);
35 this.dockerOvs = dockerOvs;
36 this.isUserSpace = isUserSpace;
39 public PingableNeutronNetItUtil(DockerOvs dockerOvs, SouthboundUtils southboundUtils, String tenantId,
40 String segId, String macPfx, String ipPfx, String cidr, Boolean isUserSpace) {
41 super(southboundUtils, tenantId, segId, macPfx, ipPfx, cidr);
42 this.dockerOvs = dockerOvs;
43 this.isUserSpace = isUserSpace;
47 * Create a port on the network. The deviceOwner will be set to "compute:None".
48 * @param bridge bridge where the port will be created on OVS
49 * @param portName name for this port
50 * @param owner deviceOwner, e.g., "network:dhcp"
51 * @param secGroups Optional NeutronSecurityGroup objects see NeutronUtils.createNeutronSecurityGroup()
52 * @throws InterruptedException if we're interrupted while waiting for objects to be created
54 public void createPort(Node bridge, String portName, String owner, NeutronSecurityGroup... secGroups)
55 throws InterruptedException, IOException {
56 if (dockerOvs.usingExternalDocker()) {
57 super.createPort(bridge, portName, owner, secGroups);
61 PortInfo portInfo = buildPortInfo(portName);
64 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "tuntap", "add", portInfo.name, "mode", "tap");
65 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "link", "set", "dev",
66 portInfo.name, "address", portInfo.mac);
68 doCreatePort(bridge, portInfo, owner, "tap", secGroups);
70 doCreatePort(bridge, portInfo, owner, "internal", secGroups);
71 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "link", "set", "dev",
72 portInfo.name, "address", portInfo.mac);
77 * This method must be run on a port before calling ping() or pingIp()
78 * @param portName The name of the port used when it was created using createPort()
79 * @throws IOException if an IO error occurs with one of the spawned procs
80 * @throws InterruptedException because we sleep
82 public void preparePortForPing(String portName) throws IOException, InterruptedException {
83 if (dockerOvs.usingExternalDocker()) {
87 String nsName = "ns-" + portName;
89 PortInfo portInfo = portInfoByName.get(portName);
90 Assert.assertNotNull(portInfo);
91 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "netns", "add", nsName);
92 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "link", "set", portName, "netns", nsName);
93 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "netns", "exec", nsName, "ip", "addr",
94 "add", "dev", portName, portInfo.ip + "/24");
95 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "netns", "exec", nsName, "ip", "link",
96 "set", "dev", "lo", "up");
97 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "netns", "exec", nsName, "ip", "link",
98 "set", "dev", portName, "up");
99 dockerOvs.runInContainer(DEFAULT_WAIT, 0, "ip", "netns", "exec", nsName, "ip", "route",
100 "add", "default", "via", portInfo.ip);
104 * Ping from one port to the other
105 * @param fromPort name of the port to ping from. This is the name you used for createPort.
106 * @param toPort name of the port to ping to. This is the name you used for createPort.
107 * @throws IOException if an IO error occurs with one of the spawned procs
108 * @throws InterruptedException because we sleep
110 public void ping(String fromPort, String toPort) throws IOException, InterruptedException {
111 if (dockerOvs.usingExternalDocker()) {
115 PortInfo portInfo = portInfoByName.get(toPort);
116 Assert.assertNotNull(portInfo);
117 pingIp(fromPort, portInfo.ip);
121 * Ping from one port to an IP address
122 * @param fromPort name of the port to ping from. This is the name you used for createPort.
123 * @param ip The IP address to ping
124 * @throws IOException if an IO error occurs with one of the spawned procs
125 * @throws InterruptedException because we sleep
127 public void pingIp(String fromPort, String ip) throws IOException, InterruptedException {
128 if (dockerOvs.usingExternalDocker()) {
132 String fromNs = "ns-" + fromPort;
133 dockerOvs.runInContainer(0, DEFAULT_WAIT, 0, "ip", "netns", "exec", fromNs, "ping", "-c", "4", ip);