"nepi.util.parser",
"nepi.util" ],
package_dir = {"": "src"},
- package_data = {"nepi.testbeds.planetlab" : ["scripts/*.py", "scripts/consts.c"] },
+ package_data = {"nepi.testbeds.planetlab" : ["scripts/*.py", "scripts/*.c"] },
)
import os
import os.path
+import tunproto
+
class NodeIface(object):
def __init__(self, api=None):
if not api:
self.device_name = None
self.mtu = None
self.snat = False
+ self.txqueuelen = None
+
+ # Enabled traces
+ self.capture = False
# These get initialized when the iface is connected to its node
self.node = None
+
+ # These get initialized when the iface is configured
+ self.external_iface = None
+
+ # These get initialized when the iface is configured
+ # They're part of the TUN standard attribute set
+ self.tun_port = None
+ self.tun_addr = None
+
+ # These get initialized when the iface is connected to its peer
+ self.peer_iface = None
+ self.peer_proto = None
+ self.peer_proto_impl = None
+
+ # same as peer proto, but for execute-time standard attribute lookups
+ self.tun_proto = None
def __str__(self):
return "%s<ip:%s/%s %s%s>" % (
self.__class__.__name__,
- self.address, self.netmask,
+ self.address, self.netprefix,
" up" if self.up else " down",
" snat" if self.snat else "",
)
self.address = address
self.netprefix = netprefix
- self.netmask = ipaddr2.ipv4_dot2mask(netprefix)
-
+ self.netmask = ipaddr2.ipv4_mask2dot(netprefix)
+
def validate(self):
- pass
+ if not self.node:
+ raise RuntimeError, "Unconnected TUN iface - missing node"
+ if self.peer_iface and self.peer_proto not in tunproto.PROTO_MAP:
+ raise RuntimeError, "Unsupported tunnelling protocol: %s" % (self.peer_proto,)
+ if not self.address or not self.netprefix or not self.netmask:
+ raise RuntimeError, "Misconfigured TUN iface - missing address"
+
+ def prepare(self, home_path, listening):
+ if self.peer_iface:
+ if not self.peer_proto_impl:
+ self.peer_proto_impl = tunproto.PROTO_MAP[self.peer_proto](
+ self, self.peer_iface, home_path, listening)
+ self.peer_proto_impl.port = self.tun_port
+ self.peer_proto_impl.prepare()
+
+ def setup(self):
+ if self.peer_iface:
+ self.peer_proto_impl.setup()
+ def destroy(self):
+ if self.peer_proto_impl:
+ self.peer_proto_impl.shutdown()
+ self.peer_proto_impl = None
+
+ def sync_trace(self, local_dir, whichtrace):
+ if self.peer_proto_impl:
+ return self.peer_proto_impl.sync_trace(local_dir, whichtrace)
+ else:
+ return None
# Yep, it does nothing - yet
class Internet(object):
from nepi.util.constants import STATUS_NOT_STARTED, STATUS_RUNNING, \
STATUS_FINISHED
+import functools
+import os
+import os.path
+
NODE = "Node"
NODEIFACE = "NodeInterface"
TUNIFACE = "TunInterface"
iface.node = node
node.required_vsys.update(('fd_tuntap', 'vif_up'))
+def connect_tun_iface_peer(proto, testbed_instance, iface, peer_iface):
+ iface.peer_iface = peer_iface
+ iface.peer_proto = \
+ iface.tun_proto = proto
+
def connect_app(testbed_instance, node, app):
app.node = node
# by counting connected devices
dev_guids = testbed_instance.get_connected(guid, "node", "devs")
num_open_ifaces = sum( # count True values
- TUNEIFACE == testbed_instance._get_factory_id(guid)
+ NODEIFACE == testbed_instance._get_factory_id(guid)
for guid in dev_guids )
element.min_num_external_ifaces = num_open_ifaces
# Do some validations
element.validate()
-def configure_tuniface(testbed_instance, guid):
+def preconfigure_tuniface(testbed_instance, guid):
element = testbed_instance._elements[guid]
- if not guid in testbed_instance._add_address:
- return
- addresses = testbed_instance._add_address[guid]
- for address in addresses:
- (address, netprefix, broadcast) = address
- element.add_address(address, netprefix, broadcast)
+ # Set custom addresses if any
+ if guid in testbed_instance._add_address:
+ addresses = testbed_instance._add_address[guid]
+ for address in addresses:
+ (address, netprefix, broadcast) = address
+ element.add_address(address, netprefix, broadcast)
+
+ # Link to external interface, if any
+ for iface in testbed_instance._elements.itervalues():
+ if isinstance(iface, testbed_instance._interfaces.NodeIface) and iface.node is element.node and iface.has_internet:
+ element.external_iface = iface
+ break
+
+ # Set standard TUN attributes
+ element.tun_addr = element.external_iface.address
+ element.tun_port = 15000 + int(guid)
+
+ # Set enabled traces
+ traces = testbed_instance._get_traces(guid)
+ element.capture = 'packets' in traces
# Do some validations
element.validate()
+
+ # First-phase setup
+ element.prepare(
+ 'tun-%s' % (guid,),
+ id(element) < id(element.peer_iface) )
+
+def postconfigure_tuniface(testbed_instance, guid):
+ element = testbed_instance._elements[guid]
+
+ # Second-phase setup
+ element.setup()
+
def configure_node(testbed_instance, guid):
node = testbed_instance._elements[guid]
"max": 2,
"min": 0
}),
+
+ "tcp": dict({
+ "help": "ip-ip tunneling over TCP link",
+ "name": "tcp",
+ "max": 1,
+ "min": 0
+ }),
+ "udp": dict({
+ "help": "ip-ip tunneling over UDP datagrams",
+ "name": "udp",
+ "max": 1,
+ "min": 0
+ }),
})
connections = [
"code": connect_node_netpipe,
"can_cross": False
}),
+ dict({
+ "from": (TESTBED_ID, TUNIFACE, "tcp"),
+ "to": (TESTBED_ID, TUNIFACE, "tcp"),
+ "code": functools.partial(connect_tun_iface_peer,"tcp"),
+ "can_cross": False
+ }),
+ dict({
+ "from": (TESTBED_ID, TUNIFACE, "udp"),
+ "to": (TESTBED_ID, TUNIFACE, "udp"),
+ "code": functools.partial(connect_tun_iface_peer,"udp"),
+ "can_cross": False
+ }),
]
attributes = dict({
"value": False,
"validation_function": validation.is_bool
}),
+ "txqueuelen": dict({
+ "name": "mask",
+ "help": "Transmission queue length (in packets)",
+ "type": Attribute.INTEGER,
+ "flags": Attribute.DesignOnly,
+ "range" : (1,10000),
+ "validation_function": validation.is_integer
+ }),
"command": dict({
"name": "command",
"name": "netpipeStats",
"help": "Information about rule match counters, packets dropped, etc.",
}),
+
+ "packets": dict({
+ "name": "packets",
+ "help": "Detailled log of all packets going through the interface",
+ }),
})
create_order = [ INTERNET, NODE, NODEIFACE, TUNIFACE, NETPIPE, APPLICATION ]
"help": "Virtual TUN network interface",
"category": "devices",
"create_function": create_tuniface,
- "preconfigure_function": configure_tuniface,
+ "preconfigure_function": preconfigure_tuniface,
+ "configure_function": postconfigure_tuniface,
"box_attributes": [
"up", "device_name", "mtu", "snat",
+ "txqueuelen"
],
- "connector_types": ["node"]
+ "traces": ["packets"],
+ "connector_types": ["node","udp","tcp"]
}),
APPLICATION: dict({
"help": "Generic executable command line application",
stderr = '&1'
else:
stderr = ' ' + stderr
- (out,err),proc = server.popen_ssh_command(
- "%(create)s%(gohome)s rm -f %(pidfile)s ; ( echo $$ $PPID > %(pidfile)s ; %(sudo)s nohup %(command)s > %(stdout)s 2>%(stderr)s < %(stdin)s ) &" % {
- 'command' : command,
-
- 'stdout' : stdout,
- 'stderr' : stderr,
- 'stdin' : stdin,
+
+ daemon_command = '{ { %(command)s > %(stdout)s 2>%(stderr)s < %(stdin)s & } ; echo $! 1 > %(pidfile)s ; }' % {
+ 'command' : command,
+ 'pidfile' : server.shell_escape(pidfile),
+
+ 'stdout' : stdout,
+ 'stderr' : stderr,
+ 'stdin' : stdin,
+ }
+
+ cmd = "%(create)s%(gohome)s rm -f %(pidfile)s ; %(sudo)s nohup bash -c %(command)s " % {
+ 'command' : server.shell_escape(daemon_command),
'sudo' : 'sudo -S' if sudo else '',
'pidfile' : server.shell_escape(pidfile),
'gohome' : 'cd %s ; ' % (server.shell_escape(home),) if home else '',
'create' : 'mkdir -p %s ; ' % (server.shell_escape,) if create_home else '',
- },
+ }
+ (out,err),proc = server.popen_ssh_command(
+ cmd,
host = host,
port = port,
user = user,
(out,err),proc = server.popen_ssh_command(
"""
-%(sudo)s kill %(pid)d %(ppid)d
+%(sudo)s kill %(pid)d
for x in 1 2 3 4 5 6 7 8 9 0 ; do
sleep 0.1
if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` == `0` ]; then
def pl_tuntap_alloc(kind, tun_path, tun_name):
- tunalloc_so = ctypes.cdll.LoadLibrary("./vsys-scripts/support/tunalloc.so")
+ tunalloc_so = ctypes.cdll.LoadLibrary("./tunalloc.so")
c_tun_name = ctypes.c_char_p("\x00"*IFNAMSIZ) # the string will be mutated!
kind = {"tun":IFF_TUN,
"tap":IFF_TAP}[kind]
--- /dev/null
+/* Slice-side code to allocate tuntap interface in root slice
+ * Based on bmsocket.c
+ * Thom Haddow - 08/10/09
+ *
+ * Call tun_alloc() with IFFTUN or IFFTAP as an argument to get back fd to
+ * new tuntap interface. Interface name can be acquired via TUNGETIFF ioctl.
+ */
+
+#include <sys/un.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#define VSYS_TUNTAP "/vsys/fd_tuntap.control"
+
+/* Reads vif FD from "fd", writes interface name to vif_name, and returns vif FD.
+ * vif_name should be IFNAMSIZ chars long. */
+int receive_vif_fd(int fd, char *vif_name)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ int rv;
+ size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
+ struct cmsghdr *cmsg;
+
+ /* Use IOV to read interface name */
+ iov.iov_base = vif_name;
+ iov.iov_len = IFNAMSIZ;
+
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ /* old BSD implementations should use msg_accrights instead of
+ * msg_control; the interface is different. */
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof(ccmsg);
+
+ while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
+ if (rv == -1) {
+ perror("recvmsg");
+ return -1;
+ }
+ if(!rv) {
+ /* EOF */
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ fprintf(stderr, "got control message of unknown type %d\n",
+ cmsg->cmsg_type);
+ return -1;
+ }
+ return *(int*)CMSG_DATA(cmsg);
+}
+
+
+int tun_alloc(int iftype, char *if_name)
+{
+ int control_fd;
+ struct sockaddr_un addr;
+ int remotefd;
+
+ control_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (control_fd == -1) {
+ perror("Could not create UNIX socket\n");
+ exit(-1);
+ }
+
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+ /* Clear structure */
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, VSYS_TUNTAP,
+ sizeof(addr.sun_path) - 1);
+
+ if (connect(control_fd, (struct sockaddr *) &addr,
+ sizeof(struct sockaddr_un)) == -1) {
+ perror("Could not connect to Vsys control socket");
+ exit(-1);
+ }
+
+ /* passing type param */
+ if (send(control_fd, &iftype, sizeof(iftype), 0) != sizeof(iftype)) {
+ perror("Could not send paramater to Vsys control socket");
+ exit(-1);
+ }
+
+ remotefd = receive_vif_fd(control_fd, if_name);
+ return remotefd;
+}
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import weakref
+import os
+import os.path
+import rspawn
+import subprocess
+
+from nepi.util import server
+
+class TunProtoBase(object):
+ def __init__(self, local, peer, home_path):
+ # Weak references, since ifaces do have a reference to the
+ # tunneling protocol implementation - we don't want strong
+ # circular references.
+ self.peer = weakref.ref(peer)
+ self.local = weakref.ref(local)
+
+ self.port = 15000
+ self.mode = 'pl-tun'
+
+ self.home_path = home_path
+
+ self._started = False
+ self._pid = None
+ self._ppid = None
+
+ def _make_home(self):
+ local = self.local()
+
+ if not local:
+ raise RuntimeError, "Lost reference to peering interfaces before launching"
+ if not local.node:
+ raise RuntimeError, "Unconnected TUN - missing node"
+
+ # Make sure all the paths are created where
+ # they have to be created for deployment
+ cmd = "mkdir -p %s" % (server.shell_escape(self.home_path),)
+ (out,err),proc = server.popen_ssh_command(
+ cmd,
+ host = local.node.hostname,
+ port = None,
+ user = local.node.slicename,
+ agent = None,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if proc.wait():
+ raise RuntimeError, "Failed to set up TUN forwarder: %s %s" % (out,err,)
+
+
+ def _install_scripts(self):
+ local = self.local()
+
+ if not local:
+ raise RuntimeError, "Lost reference to peering interfaces before launching"
+ if not local.node:
+ raise RuntimeError, "Unconnected TUN - missing node"
+
+ # Install the tun_connect script and tunalloc utility
+ source = os.path.join(os.path.dirname(__file__), 'scripts', 'tun_connect.py')
+ dest = "%s@%s:%s" % (
+ local.node.slicename, local.node.hostname,
+ os.path.join(self.home_path,'.'),)
+ (out,err),proc = server.popen_scp(
+ source,
+ dest,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if proc.wait():
+ raise RuntimeError, "Failed upload TUN connect script %r: %s %s" % (source, out,err,)
+
+ source = os.path.join(os.path.dirname(__file__), 'scripts', 'tunalloc.c')
+ (out,err),proc = server.popen_scp(
+ source,
+ dest,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if proc.wait():
+ raise RuntimeError, "Failed upload TUN connect script %r: %s %s" % (source, out,err,)
+
+ cmd = "cd %s && gcc -shared tunalloc.c -o tunalloc.so" % (server.shell_escape(self.home_path),)
+ (out,err),proc = server.popen_ssh_command(
+ cmd,
+ host = local.node.hostname,
+ port = None,
+ user = local.node.slicename,
+ agent = None,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if proc.wait():
+ raise RuntimeError, "Failed to set up TUN forwarder: %s %s" % (out,err,)
+
+
+ def launch(self, check_proto, listen, extra_args=[]):
+ peer = self.peer()
+ local = self.local()
+
+ if not peer or not local:
+ raise RuntimeError, "Lost reference to peering interfaces before launching"
+
+ peer_port = peer.tun_port
+ peer_addr = peer.tun_addr
+ peer_proto= peer.tun_proto
+
+ local_port = self.port
+ local_cap = local.capture
+ local_addr = local.address
+ local_mask = local.netprefix
+ local_snat = local.snat
+ local_txq = local.txqueuelen
+
+ if check_proto != peer_proto:
+ raise RuntimeError, "Peering protocol mismatch: %s != %s" % (check_proto, peer_proto)
+
+ if not listen and (not peer_port or not peer_addr):
+ raise RuntimeError, "Misconfigured peer: %s" % (peer,)
+
+ if listen and (not local_port or not local_addr or not local_mask):
+ raise RuntimeError, "Misconfigured TUN: %s" % (local,)
+
+ args = ["python", "tun_connect.py",
+ "-m", str(self.mode),
+ "-p", str(local_port if listen else peer_port),
+ "-A", str(local_addr),
+ "-M", str(local_mask)]
+
+ if local_snat:
+ args.append("-S")
+ if local_txq:
+ args.extend(("-Q",str(local_txq)))
+ if extra_args:
+ args.extend(map(str,extra_args))
+ if not listen:
+ args.append(str(peer_addr))
+
+ self._make_home()
+ self._install_scripts()
+
+ # Start process in a "daemonized" way, using nohup and heavy
+ # stdin/out redirection to avoid connection issues
+ (out,err),proc = rspawn.remote_spawn(
+ " ".join(args),
+
+ pidfile = './pid',
+ home = self.home_path,
+ stdin = '/dev/null',
+ stdout = 'capture' if local_cap else '/dev/null',
+ stderr = rspawn.STDOUT,
+ sudo = True,
+
+ host = local.node.hostname,
+ port = None,
+ user = local.node.slicename,
+ agent = None,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if proc.wait():
+ raise RuntimeError, "Failed to set up application: %s %s" % (out,err,)
+
+ self._started = True
+
+ def checkpid(self):
+ local = self.local()
+
+ if not local:
+ raise RuntimeError, "Lost reference to local interface"
+
+ # Get PID/PPID
+ # NOTE: wait a bit for the pidfile to be created
+ if self._started and not self._pid or not self._ppid:
+ pidtuple = rspawn.remote_check_pid(
+ os.path.join(self.home_path,'pid'),
+ host = local.node.hostname,
+ port = None,
+ user = local.node.slicename,
+ agent = None,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if pidtuple:
+ self._pid, self._ppid = pidtuple
+
+ def status(self):
+ local = self.local()
+
+ if not local:
+ raise RuntimeError, "Lost reference to local interface"
+
+ self.checkpid()
+ if not self._started:
+ return rspawn.NOT_STARTED
+ elif not self._pid or not self._ppid:
+ return rspawn.NOT_STARTED
+ else:
+ status = rspawn.remote_status(
+ self._pid, self._ppid,
+ host = local.node.hostname,
+ port = None,
+ user = local.node.slicename,
+ agent = None,
+ ident_key = local.node.ident_path
+ )
+ return status
+
+ def kill(self):
+ local = self.local()
+
+ if not local:
+ raise RuntimeError, "Lost reference to local interface"
+
+ status = self.status()
+ if status == rspawn.RUNNING:
+ # kill by ppid+pid - SIGTERM first, then try SIGKILL
+ rspawn.remote_kill(
+ self._pid, self._ppid,
+ host = local.node.hostname,
+ port = None,
+ user = local.node.slicename,
+ agent = None,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key,
+ sudo = True
+ )
+
+ def sync_trace(self, local_dir, whichtrace):
+ if whichtrace != 'packets':
+ return None
+
+ local = self.local()
+
+ if not local:
+ return None
+
+ local_path = os.path.join(local_dir, 'capture')
+
+ # create parent local folders
+ proc = subprocess.Popen(
+ ["mkdir", "-p", os.path.dirname(local_path)],
+ stdout = open("/dev/null","w"),
+ stdin = open("/dev/null","r"))
+
+ if proc.wait():
+ raise RuntimeError, "Failed to synchronize trace: %s %s" % (out,err,)
+
+ # sync files
+ (out,err),proc = server.popen_scp(
+ '%s@%s:%s' % (local.node.slicename, local.node.hostname,
+ os.path.join(self.home_path, 'capture')),
+ local_path,
+ port = None,
+ agent = None,
+ ident_key = local.node.ident_path,
+ server_key = local.node.server_key
+ )
+
+ if proc.wait():
+ raise RuntimeError, "Failed to synchronize trace: %s %s" % (out,err,)
+
+ return local_path
+
+
+ def prepare(self):
+ """
+ First-phase setup
+
+ eg: set up listening ports
+ """
+ raise NotImplementedError
+
+ def setup(self):
+ """
+ Second-phase setup
+
+ eg: connect to peer
+ """
+ raise NotImplementedError
+
+ def shutdown(self):
+ """
+ Cleanup
+ """
+ raise NotImplementedError
+
+
+class TunProtoUDP(TunProtoBase):
+ def __init__(self, local, peer, home_path, listening):
+ super(TunProtoTCP, self).__init__(local, peer, home_path)
+ self.listening = listening
+
+ def prepare(self):
+ pass
+
+ def setup(self):
+ self.launch('udp', False, ("-U",))
+
+ def shutdown(self):
+ self.kill()
+
+class TunProtoTCP(TunProtoBase):
+ def __init__(self, local, peer, home_path, listening):
+ super(TunProtoTCP, self).__init__(local, peer, home_path)
+ self.listening = listening
+
+ def prepare(self):
+ if self.listening:
+ self.launch('tcp', True)
+
+ def setup(self):
+ if not self.listening:
+ self.launch('tcp', False)
+
+ self.checkpid()
+
+ def shutdown(self):
+ self.kill()
+
+PROTO_MAP = {
+ 'tcp' : TunProtoTCP,
+ 'udp' : TunProtoUDP,
+}
+
+
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+import struct
def ipv4_dot2mask(mask):
mask = mask.split('.',4) # a.b.c.d -> [a,b,c,d]
return n
+def ipv4_mask2dot(mask):
+ mask = ((1L << mask)-1) << (32 - mask)
+ mask = struct.pack(">I",mask)
+ mask = '.'.join(map(str,map(ord,mask)))
+ return mask
+
-SHELL_SAFE = re.compile('[-a-zA-Z0-9_=+:.,/]*')
+SHELL_SAFE = re.compile('^[-a-zA-Z0-9_=+:.,/]*$')
def shell_escape(s):
""" Escapes strings so that they are safe to use as command-line arguments """
instance.defer_create(7, "Application")
instance.defer_create_set(7, "command", "ping -qc1 {#[GUID-5].addr[0].[Address]#}")
instance.defer_add_trace(7, "stdout")
+ instance.defer_add_trace(7, "stderr")
instance.defer_connect(7, "node", 2, "apps")
instance.do_setup()
instance.defer_create_set(5, "command", "gfortran --version")
instance.defer_create_set(5, "depends", "gcc-gfortran")
instance.defer_add_trace(5, "stdout")
+ instance.defer_add_trace(5, "stderr")
instance.defer_connect(5, "node", 2, "apps")
instance.do_setup()
instance.defer_create_set(10, "install", "cp consts ${SOURCES}/consts")
instance.defer_create_set(10, "sources", os.path.join(os.path.dirname(planetlab.__file__),'scripts','consts.c'))
instance.defer_add_trace(10, "stdout")
+ instance.defer_add_trace(10, "stderr")
instance.defer_connect(10, "node", 2, "apps")
instance.do_setup()
instance.defer_create(4, "Internet")
instance.defer_connect(3, "inet", 4, "devs")
instance.defer_create(5, "TunInterface")
+ instance.defer_add_address(5, "192.168.2.2", 24, False)
instance.defer_connect(2, "devs", 5, "node")
instance.defer_create(6, "Application")
instance.defer_create_set(6, "command", """
""")
instance.defer_create_set(6, "sudo", True) # only sudo has access to /vsys
instance.defer_add_trace(6, "stdout")
+ instance.defer_add_trace(6, "stderr")
instance.defer_connect(6, "node", 2, "apps")
instance.do_setup()
instance.defer_connect(2, "pipes", 7, "node")
instance.defer_create(8, "Application")
instance.defer_create_set(8, "command", "time wget -q -O /dev/null http://www.google.com/") # Fetch ~10kb
+ instance.defer_add_trace(8, "stdout")
instance.defer_add_trace(8, "stderr")
instance.defer_connect(8, "node", 2, "apps")
time.sleep(0.5)
test_result = (instance.trace(8, "stderr") or "").strip()
comp_result = r".*real\s*(?P<min>[0-9]+)m(?P<sec>[0-9]+[.][0-9]+)s.*"
+ netpipe_stats = instance.trace(7, "netpipeStats")
+ instance.stop()
+ instance.shutdown()
+
+ # asserts at the end, to make sure there's proper cleanup
match = re.match(comp_result, test_result, re.MULTILINE)
self.assertTrue(match, "Unexpected output: %s" % (test_result,))
minutes = int(match.group("min"))
seconds = float(match.group("sec"))
self.assertTrue((minutes * 60 + seconds) > 1.0, "Emulation not effective: %s" % (test_result,))
-
- netpipe_stats = instance.trace(7, "netpipeStats")
+
self.assertTrue(netpipe_stats, "Unavailable netpipe stats")
-
- instance.stop()
- instance.shutdown()
@test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
def test_tun_emulation_requirement(self):
instance.defer_create(4, "Internet")
instance.defer_connect(3, "inet", 4, "devs")
instance.defer_create(5, "TunInterface")
+ instance.defer_add_address(5, "192.168.2.2", 24, False)
instance.defer_connect(2, "devs", 5, "node")
instance.defer_create(6, "Application")
instance.defer_create_set(6, "command", "false")
instance.defer_add_trace(6, "stdout")
+ instance.defer_add_trace(6, "stderr")
instance.defer_connect(6, "node", 2, "apps")
try:
self.fail("Usage of TUN without emulation should fail")
except Exception,e:
pass
+
+ @test_util.skipUnless(test_util.pl_auth() is not None, "Test requires PlanetLab authentication info (PL_USER and PL_PASS environment variables)")
+ def test_tun_ping(self):
+ instance = self.make_instance()
+
+ instance.defer_create(2, "Node")
+ instance.defer_create_set(2, "hostname", "onelab11.pl.sophia.inria.fr")
+ instance.defer_create_set(2, "emulation", True) # require emulation
+ instance.defer_create(3, "Node")
+ instance.defer_create_set(3, "hostname", "onelab10.pl.sophia.inria.fr")
+ instance.defer_create_set(3, "emulation", True) # require emulation
+ instance.defer_create(4, "NodeInterface")
+ instance.defer_connect(2, "devs", 4, "node")
+ instance.defer_create(5, "Internet")
+ instance.defer_connect(4, "inet", 5, "devs")
+ instance.defer_create(6, "NodeInterface")
+ instance.defer_connect(3, "devs", 6, "node")
+ instance.defer_connect(6, "inet", 5, "devs")
+ instance.defer_create(7, "TunInterface")
+ instance.defer_add_address(7, "192.168.2.2", 24, False)
+ instance.defer_connect(2, "devs", 7, "node")
+ instance.defer_create(8, "TunInterface")
+ instance.defer_add_address(8, "192.168.2.3", 24, False)
+ instance.defer_connect(3, "devs", 8, "node")
+ instance.defer_connect(7, "tcp", 8, "tcp")
+ instance.defer_create(9, "Application")
+ instance.defer_create_set(9, "command", "ping -qc1 {#[GUID-8].addr[0].[Address]#}")
+ instance.defer_add_trace(9, "stdout")
+ instance.defer_add_trace(9, "stderr")
+ instance.defer_connect(9, "node", 2, "apps")
+
+ instance.do_setup()
+ instance.do_create()
+ instance.do_connect()
+ instance.do_preconfigure()
+
+ # Manually replace netref
+ instance.set(TIME_NOW, 9, "command",
+ instance.get(TIME_NOW, 9, "command")
+ .replace("{#[GUID-8].addr[0].[Address]#}",
+ instance.get_address(8, 0, "Address") )
+ )
+
+ instance.do_configure()
+
+ instance.start()
+ while instance.status(9) != STATUS_FINISHED:
+ time.sleep(0.5)
+ ping_result = instance.trace(9, "stdout") or ""
+ comp_result = r"""PING .* \(.*\) \d*\(\d*\) bytes of data.
+
+--- .* ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
+"""
+ instance.stop()
+ instance.shutdown()
+
+ # asserts at the end, to make sure there's proper cleanup
+ self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE),
+ "Unexpected trace:\n" + ping_result)
if __name__ == '__main__':