From: Alina Quereilhac Date: Tue, 20 Jan 2015 03:40:38 +0000 (+0100) Subject: FdNetDevice working with PlanetLab TAPs X-Git-Tag: nepi-3.2.0~17 X-Git-Url: http://git.onelab.eu/?p=nepi.git;a=commitdiff_plain;h=9f095b0a5b3f063dbbec097278fad8ba3cb4f37c FdNetDevice working with PlanetLab TAPs --- diff --git a/examples/openvswitch/ping_over_udpTapTunnel_performance_test_triangleTopo.py b/examples/openvswitch/ping_over_udpTapTunnel_performance_test_triangleTopo.py index 50328226..0f347e9c 100644 --- a/examples/openvswitch/ping_over_udpTapTunnel_performance_test_triangleTopo.py +++ b/examples/openvswitch/ping_over_udpTapTunnel_performance_test_triangleTopo.py @@ -65,10 +65,11 @@ def add_udptun(ec, tap1, tap2): ec.register_connection(tap2, udptun) return udptun -def add_vroute(ec, network, tap): +def add_vroute(ec, network, prefix, tap): vroute = ec.register_resource("planetlab::Vroute") - ec.set(vroute, "action", "add") ec.set(vroute, "network", network) + ec.set(vroute, "prefix", prefix) + ec.set(vroute, "nexthop", ec.get(tap, "pointopoint")) ec.register_connection(vroute, tap) return vroute @@ -127,16 +128,16 @@ udptun5 = add_udptun(ec, tap152, tap156) udptun6 = add_udptun(ec, tap204, tap206) ## Create the PlanetLab Route ## -vroute1 = add_vroute(ec, "192.168.3.0", tap1) -vroute2 = add_vroute(ec, "192.168.3.0", tap13) -vroute3 = add_vroute(ec, "192.168.3.0", tap25) - -vroute7 = add_vroute(ec, "192.168.3.8", tap102) -vroute8 = add_vroute(ec, "192.168.3.0", tap104) -vroute9 = add_vroute(ec, "192.168.3.24", tap152) -vroute10 = add_vroute(ec, "192.168.3.0", tap156) -vroute11 = add_vroute(ec, "192.168.3.24", tap204) -vroute12 = add_vroute(ec, "192.168.3.8", tap206) +vroute1 = add_vroute(ec, "192.168.3.0", "24", tap1) +vroute2 = add_vroute(ec, "192.168.3.0", "24", tap13) +vroute3 = add_vroute(ec, "192.168.3.0", "24", tap25) + +vroute7 = add_vroute(ec, "192.168.3.8", "29", tap102) +vroute8 = add_vroute(ec, "192.168.3.0", "29", tap104) +vroute9 = add_vroute(ec, "192.168.3.24", "29", tap152) +vroute10 = add_vroute(ec, "192.168.3.0", "29", tap156) +vroute11 = add_vroute(ec, "192.168.3.24", "29", tap204) +vroute12 = add_vroute(ec, "192.168.3.8", "29", tap206) ## Create all the Ping ## diff --git a/examples/planetlab/update_fedora_repo.py b/examples/planetlab/update_fedora_repo.py index 8d4b6047..7b5d88c6 100644 --- a/examples/planetlab/update_fedora_repo.py +++ b/examples/planetlab/update_fedora_repo.py @@ -77,7 +77,9 @@ for hostname in hosts: node = ec.register_resource("planetlab::Node") # The username in this case is the slice name, the one to use for login in # via ssh into PlanetLab nodes. Replace with your own slice name. - ec.set(node, "hostname", hostname) + if hostname != "any": + ec.set(node, "hostname", hostname) + ec.set(node, "username", pl_slice) ec.set(node, "identity", pl_ssh_key) # The pluser and plpassword are the ones used to login in the PlanetLab web @@ -94,11 +96,11 @@ for hostname in hosts: "fedora.repo") app = ec.register_resource("linux::Application") - ec.set(app, "sources", path_to_repo) + ec.set(app, "files", path_to_repo) ec.set(app, "sudo", True) ec.set(app, "command", "cp /etc/yum.repos.d/fedora.repo /etc/yum.repos.d/fedora.repo.old; " - "cp ${SRC}/fedora.repo /etc/yum.repos.d/fedora.repo") + "cp ${SHARE}/fedora.repo /etc/yum.repos.d/fedora.repo") ec.register_connection(node, app) apps.append(app) @@ -109,11 +111,11 @@ for hostname in hosts: "fedora-updates.repo") app = ec.register_resource("linux::Application") - ec.set(app, "sources", path_to_repo) + ec.set(app, "files", path_to_repo) ec.set(app, "sudo", True) ec.set(app, "command", "cp /etc/yum.repos.d/fedora-updates.repo /etc/yum.repos.d/fedora-updates.repo.old; " - "cp ${SRC}/fedora-updates.repo /etc/yum.repos.d/fedora-updates.repo") + "cp ${SHARE}/fedora-updates.repo /etc/yum.repos.d/fedora-updates.repo") ec.register_connection(node, app) apps.append(app) diff --git a/src/nepi/resources/linux/node.py b/src/nepi/resources/linux/node.py index ff19bbb6..14aab1ad 100644 --- a/src/nepi/resources/linux/node.py +++ b/src/nepi/resources/linux/node.py @@ -28,7 +28,6 @@ import collections import os import random import re -import socket import tempfile import time import threading @@ -51,12 +50,12 @@ class OSType: """ Supported flavors of Linux OS """ - FEDORA_8 = "f8" - FEDORA_12 = "f12" - FEDORA_14 = "f14" - FEDORA = "fedora" - UBUNTU = "ubuntu" - DEBIAN = "debian" + DEBIAN = 1 + UBUNTU = 1 << 1 + FEDORA = 1 << 2 + FEDORA_8 = 1 << 3 | FEDORA + FEDORA_12 = 1 << 4 | FEDORA + FEDORA_14 = 1 << 5 | FEDORA @clsinit_copy class LinuxNode(ResourceManager): @@ -291,18 +290,18 @@ class LinuxNode(ResourceManager): out = self.get_os() - if out.find("Fedora release 8") == 0: - self._os = OSType.FEDORA_8 - elif out.find("Fedora release 12") == 0: - self._os = OSType.FEDORA_12 - elif out.find("Fedora release 14") == 0: - self._os = OSType.FEDORA_14 - elif out.find("Fedora release") == 0: - self._os = OSType.FEDORA - elif out.find("Debian") == 0: + if out.find("Debian") == 0: self._os = OSType.DEBIAN elif out.find("Ubuntu") ==0: self._os = OSType.UBUNTU + elif out.find("Fedora release") == 0: + self._os = OSType.FEDORA + if out.find("Fedora release 8") == 0: + self._os = OSType.FEDORA_8 + elif out.find("Fedora release 12") == 0: + self._os = OSType.FEDORA_12 + elif out.find("Fedora release 14") == 0: + self._os = OSType.FEDORA_14 else: msg = "Unsupported OS" self.error(msg, out) @@ -329,12 +328,11 @@ class LinuxNode(ResourceManager): @property def use_deb(self): - return self.os in [OSType.DEBIAN, OSType.UBUNTU] + return (self.os & (OSType.DEBIAN|OSType.UBUNTU)) @property def use_rpm(self): - return self.os in [OSType.FEDORA_12, OSType.FEDORA_14, OSType.FEDORA_8, - OSType.FEDORA] + return (self.os & OSType.FEDORA) @property def localhost(self): @@ -369,16 +367,11 @@ class LinuxNode(ResourceManager): # Get Public IP address if possible if not self.get("ip"): - ip = None - - if self.localhost: - ip = socket.gethostbyname(socket.gethostname()) - else: - try: - ip = socket.gethostbyname(self.get("hostname")) - except: - msg = "DNS can not resolve hostname %s" % self.get("hostname") - self.debug(msg) + try: + ip = sshfuncs.gethostbyname(self.get("hostname")) + except: + msg = "DNS can not resolve hostname %s" % self.get("hostname") + self.debug(msg) self.set("ip", ip) diff --git a/src/nepi/resources/linux/ns3/fdtunnel.py b/src/nepi/resources/linux/ns3/fdtunnel.py index a934e8d7..e968ea30 100644 --- a/src/nepi/resources/linux/ns3/fdtunnel.py +++ b/src/nepi/resources/linux/ns3/fdtunnel.py @@ -185,17 +185,16 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel): # execute the tunnel creation script node = self.endpoint_node(remote_endpoint) - remote_ip = node.get("ip") - port = self.initiate(endpoint, address, remote_ip, cipher, + port = self.initiate(endpoint, remote_endpoint, address, cipher, cipher_key, bwlimit, txqueuelen) return port def establish_connection(self, endpoint, remote_endpoint, port): - self.establish(remote_endpoint, port) + self.establish(endpoint, remote_endpoint, port) def verify_connection(self, endpoint, remote_endpoint): - self.verify() + self.verify(endpoint) def terminate_connection(self, endpoint, remote_endpoint): # Nothing to do @@ -267,10 +266,11 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel): return result - def initiate(self, endpoint, address, remote_ip, cipher, cipher_key, + def initiate(self, endpoint, remote_endpoint, address, cipher, cipher_key, bwlimit, txqueuelen): - command = self._initiate_command(endpoint, address, remote_ip, - cipher, cipher_key, bwlimit, txqueuelen) + + command = self._initiate_command(endpoint, remote_endpoint, + address, cipher, cipher_key, bwlimit, txqueuelen) node = self.endpoint_node(endpoint) run_home = self.run_home(endpoint) @@ -310,15 +310,19 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel): return port - def _initiate_command(self, endpoint, address, remote_ip, + def _initiate_command(self, endpoint, remote_endpoint, address, cipher, cipher_key, bwlimit, txqueuelen): - node = self.endpoint_node(endpoint) - run_home = self.run_home(endpoint) - app_home = self.app_home(endpoint) + local_node = self.endpoint_node(endpoint) + local_run_home = self.run_home(endpoint) + local_app_home = self.app_home(endpoint) + remote_node = self.endpoint_node(remote_endpoint) + + local_ip = local_node.get("ip") + remote_ip = remote_node.get("ip") - local_port_file = os.path.join(run_home, "local_port") - remote_port_file = os.path.join(run_home, "remote_port") - ret_file = os.path.join(run_home, "ret_file") + local_port_file = os.path.join(local_run_home, "local_port") + remote_port_file = os.path.join(local_run_home, "remote_port") + ret_file = os.path.join(local_run_home, "ret_file") address = base64.b64encode(address) @@ -327,9 +331,10 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel): command.append("PYTHONPATH=$PYTHONPATH:${SRC}") command.append("python ${SRC}/linux-ns3-fd-udp-connect.py") command.append("-a %s" % address) - command.append("-l %s " % local_port_file) - command.append("-r %s " % remote_port_file) - command.append("-H %s " % remote_ip) + command.append("-p %s " % local_port_file) + command.append("-P %s " % remote_port_file) + command.append("-o %s " % local_ip) + command.append("-O %s " % remote_ip) command.append("-R %s " % ret_file) if cipher: command.append("-c %s " % cipher) @@ -341,12 +346,12 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel): command.append("-b %s " % bwlimit) command = " ".join(command) - command = self.replace_paths(command, node=node, app_home=app_home, - run_home=run_home) + command = self.replace_paths(command, node=local_node, + app_home=local_app_home, run_home=local_run_home) return command - def establish(self, remote_endpoint, port): + def establish(self, endpoint, remote_endpoint, port): node = self.endpoint_node(endpoint) run_home = self.run_home(endpoint) @@ -357,6 +362,6 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel): text = True, overwrite = False) - def verify(self): - self.wait_result() + def verify(self, endpoint): + self.wait_result(endpoint) diff --git a/src/nepi/resources/linux/ns3/tun_tap_fd_link.py b/src/nepi/resources/linux/ns3/tun_tap_fd_link.py index cf658fc3..5a3a77b4 100644 --- a/src/nepi/resources/linux/ns3/tun_tap_fd_link.py +++ b/src/nepi/resources/linux/ns3/tun_tap_fd_link.py @@ -16,9 +16,7 @@ # along with this program. If not, see . # # Author: Alina Quereilhac - -from nepi.execution.resource import ResourceState, clsinit_copy, \ - ResourceManager +from nepi.execution.resource import ResourceState, clsinit_copy from nepi.resources.linux.application import LinuxApplication import base64 @@ -37,9 +35,9 @@ class LinuxTunTapFdLink(LinuxApplication): super(LinuxTunTapFdLink, self).__init__(ec, guid) self._tap = None self._fdnetdevice = None - self._fd = None self._fd_node = None self.send_address = None + self._home = "tuntap-link-%s" % self.guid @property def fdnetdevice(self): diff --git a/src/nepi/resources/linux/rpmfuncs.py b/src/nepi/resources/linux/rpmfuncs.py index 35aeb612..5d17b316 100644 --- a/src/nepi/resources/linux/rpmfuncs.py +++ b/src/nepi/resources/linux/rpmfuncs.py @@ -53,18 +53,18 @@ def install_rpmfusion_command(os): cmd = " { rpm -q rpmfusion-free-release || sudo -S rpm -i %(package)s ; } " - if os in [OSType.FEDORA, OSType.FEDORA_12]: + if (os & OSType.FEDORA_8): + # RpmFusion for Fedora 8 is unmaintained + cmd = "" + elif (os & OSType.FEDORA_12): # For f12 cmd = cmd % {'package': RPM_FUSION_URL_F12} - elif os == OSType.FEDORA_14: + elif (os & OSType.FEDORA_14): # For f14 cmd = cmd % {'package': RPM_FUSION_URL_F14} - elif os == OSType.FEDORA: + else: # For f14+ cmd = cmd % {'package': RPM_FUSION_URL} - else: - # Fedora 8 is unmaintained - cmd = "" return cmd diff --git a/src/nepi/resources/linux/scripts/linux-ns3-fd-udp-connect.py b/src/nepi/resources/linux/scripts/linux-ns3-fd-udp-connect.py index 4598868e..c1141221 100644 --- a/src/nepi/resources/linux/scripts/linux-ns3-fd-udp-connect.py +++ b/src/nepi/resources/linux/scripts/linux-ns3-fd-udp-connect.py @@ -1,19 +1,30 @@ import base64 import errno import os -import time +import passfd import signal import socket +import time import tunchannel -import passfd from optparse import OptionParser +IFF_TAP = 0x0002 + # Trak SIGTERM, and set global termination flag instead of dying TERMINATE = [] +STARTED = False + def _finalize(sig,frame): global TERMINATE - TERMINATE.append(None) + global STARTED + + if STARTED: + TERMINATE.append(None) + else: + signal.signal(signal.SIGTERM, signal.SIG_DFL) + os.kill(os.getpid(), signal.SIGTERM) + signal.signal(signal.SIGTERM, _finalize) # SIGUSR1 suspends forwading, SIGUSR2 resumes forwarding @@ -31,10 +42,10 @@ def _resume(sig,frame): signal.signal(signal.SIGUSR2, _resume) def get_options(): - usage = ("usage: %prog -a
" - "-b -c -k -q " - "-l -r -H " - "-R ") + usage = ("usage: %prog -a
-b -c " + "- k -q -p " + "-P -o -O " + "-r ") parser = OptionParser(usage = usage) @@ -57,14 +68,16 @@ def get_options(): "on the system." , default=None, type="str") - parser.add_option("-l", "--local-port-file", dest="local_port_file", + parser.add_option("-p", "--local-port-file", dest="local_port_file", help = "File where to store the local binded UDP port number ", default = "local_port_file", type="str") - parser.add_option("-r", "--remote-port-file", dest="remote_port_file", + parser.add_option("-P", "--remote-port-file", dest="remote_port_file", help = "File where to read the remote UDP port number to connect to", default = "remote_port_file", type="str") - parser.add_option("-H", "--remote-host", dest="remote_host", - help = "Remote host IP", default = "remote_host", type="str") + parser.add_option("-o", "--local-ip", dest="local_ip", + help = "Local host IP", type="str") + parser.add_option("-O", "--remote-ip", dest="remote_ip", + help = "Remote host IP", type="str") parser.add_option("-R", "--ret-file", dest="ret_file", help = "File where to store return code (success of connection) ", default = "ret_file", type="str") @@ -73,20 +86,19 @@ def get_options(): address = base64.b64decode(options.address) - return ( address, - options.local_port_file, options.remote_port_file, - options.remote_host, options.ret_file, options.bwlimit, - options.cipher, options.cipher_key, options.txqueuelen ) + return (address, options.local_port_file, options.remote_port_file, + options.local_ip, options.remote_ip, options.ret_file, + options.bwlimit, options.cipher, options.cipher_key, + options.txqueuelen) if __name__ == '__main__': - (address, local_port_file, remote_port_file, remote_host, ret_file, - bwlimit, cipher, cipher_key, txqueuelen) = get_options() + (address, local_port_file, remote_port_file, local_ip, remote_ip, + ret_file, bwlimit, cipher, cipher_key, txqueuelen) = get_options() # Create a local socket to stablish the tunnel connection - hostaddr = socket.gethostbyname(socket.gethostname()) rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) - rsock.bind((hostaddr, 0)) + rsock.bind((local_ip, 0)) (local_host, local_port) = rsock.getsockname() # Save local port information to file @@ -119,7 +131,7 @@ if __name__ == '__main__': remote_port = int(remote_port) # Connect local socket to remote port - rsock.connect((remote_host, remote_port)) + rsock.connect((remote_ip, remote_port)) remote = os.fdopen(rsock.fileno(), 'r+b', 0) # create local socket to pass to fd-net-device @@ -140,6 +152,8 @@ if __name__ == '__main__': f.write("0") f.close() + STARTED = True + # Establish tunnel tunchannel.tun_fwd(local, remote, with_pi = False, # No PI headers diff --git a/src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py b/src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py index c658fb83..041e6b88 100644 --- a/src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py +++ b/src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py @@ -17,26 +17,23 @@ # # Author: Alina Quereilhac -from nepi.execution.attribute import Attribute, Flags, Types -from nepi.execution.resource import ResourceManager, ResourceState, \ - clsinit_copy +from nepi.execution.resource import ResourceState, clsinit_copy +from nepi.resources.linux.ns3.tun_tap_fd_link import LinuxTunTapFdLink +import base64 +import fcntl import os import socket import struct -import fcntl @clsinit_copy -class PlanetlabTunTapFdLink(ResourceManager): - """ Interconnects a TAP or TUN Linux device to a FdNetDevice +class PlanetlabTunTapFdLink(LinuxTunTapFdLink): + """ Interconnects a TAP or TUN PlanetLab device to a FdNetDevice """ _rtype = "planetlab::ns3::TunTapFdLink" def __init__(self, ec, guid): super(PlanetlabTunTapFdLink, self).__init__(ec, guid) - self._tap = None - self._fdnetdevice = None - self._fd_sock_address = None @property def fdnetdevice(self): @@ -44,11 +41,19 @@ class PlanetlabTunTapFdLink(ResourceManager): from nepi.resources.ns3.ns3fdnetdevice import NS3BaseFdNetDevice devices = self.get_connected(NS3BaseFdNetDevice.get_rtype()) if not devices or len(devices) != 1: - msg = "TapFdLink must be connected to exactly one FdNetDevices" + msg = "planetlab::ns3::TunTapFdLink must be connected to exactly one FdNetDevice" self.error(msg) raise RuntimeError, msg self._fdnetdevice = devices[0] + + # Set PI headers on + self._fdnetdevice.set("EncapsulationMode", "DixPi") + + simu = self._fdnetdevice.simulation + from nepi.resources.planetlab.node import PlanetlabNode + nodes = simu.get_connected(PlanetlabNode.get_rtype()) + self._fd_node = nodes[0] return self._fdnetdevice @@ -59,7 +64,7 @@ class PlanetlabTunTapFdLink(ResourceManager): devices = self.get_connected(PlanetlabTap.get_rtype()) if not devices or len(devices) != 1: - msg = "TapFdLink must be connected to exactly one PlanetlabTap" + msg = "planetlab::ns3::TunTapFdLink must be connected to exactly one PlanetlabTap" self.error(msg) raise RuntimeError, msg @@ -67,19 +72,13 @@ class PlanetlabTunTapFdLink(ResourceManager): return self._tap - @property - def fd_sock_address(self): - return self._fd_sock_address - - @property - def node(self): - return self.tap.node - def upload_sources(self): scripts = [] # vif-passfd python script - pl_vif_passfd = os.path.join(os.path.dirname(__file__), "scripts", + pl_vif_passfd = os.path.join(os.path.dirname(__file__), + "..", + "scripts", "pl-vif-passfd.py") scripts.append(pl_vif_passfd) @@ -91,61 +90,16 @@ class PlanetlabTunTapFdLink(ResourceManager): os.path.join(self.node.src_dir), overwrite = False) - def upload_start_command(self): - if self.tap.node.get("hostname") != \ - self.fdnetdevice.node.get("hostname"): - msg = "Tap and FdNetDevice are not in the same host" - self.error(msg) - raise RuntimeError, msg - - self._fd_sock_address = self.fdnetdevice.recv_fd() - self.set("command", self._start_command) - - command = self.get("command") - env = self.get("env") - - # We want to make sure the ccnd is running - # before the experiment starts. - # Run the command as a bash script in background, - # in the host ( but wait until the command has - # finished to continue ) - env = self.replace_paths(env) - command = self.replace_paths(command) - - shfile = os.path.join(self.app_home, "start.sh") - self.node.run_and_wait(command, self.run_home, - shfile = shfile, - overwrite = True) - - def do_deploy(self): - if self.tap.state < ResourceState.READY or \ - self.fdnetdevice.state < ResourceState.READY: - self.ec.schedule(self.reschedule_delay, self.deploy) - else: - self.do_discover() - self.do_provision() - - super(PlanetlabTunTapFdLink, self).do_deploy() - - def do_start(self): - if self.state == ResourceState.READY: - command = self.get("command") - self.info("Starting command '%s'" % command) - - self.set_started() - else: - msg = " Failed to execute command '%s'" % command - self.error(msg, out, err) - raise RuntimeError, msg - @property def _start_command(self): + address = base64.b64encode(self.send_address) + command = [] # Use pl-vif-passfd.py to send fd from TAP to FdNetDevice command.append("sudo -S") command.append("PYTHONPATH=$PYTHONPATH:${SRC}") - command.append("python ${SRC}/pl-vif-passfd") - command.append("-a %s" % self.fd_sock_address) + command.append("python ${SRC}/pl-vif-passfd.py") + command.append("-a %s" % address) command.append("-S %s " % self.tap.sock_name) command = " ".join(command) diff --git a/src/nepi/resources/planetlab/openvswitch/ovsport.py b/src/nepi/resources/planetlab/openvswitch/ovsport.py index 4d863d51..f80db457 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovsport.py +++ b/src/nepi/resources/planetlab/openvswitch/ovsport.py @@ -186,6 +186,8 @@ class OVSPort(LinuxApplication): if remote_endpoint.is_rm_instance("planetlab::Tap"): self._vroute = self.ec.register_resource("planetlab::Vroute") self.ec.set(self._vroute, "action", "add") + self.ec.set(self._vroute, "prefix", remote_endpoint.get("prefix")) + self.ec.set(self._vroute, "nexthop", remote_endpoint.get("pointopoint")) self.ec.set(self._vroute, "network", self.get("network")) print "Vroute Guid :" + str(self._vroute) diff --git a/src/nepi/resources/planetlab/scripts/pl-vif-passfd.py b/src/nepi/resources/planetlab/scripts/pl-vif-passfd.py index f1f3ce54..63323623 100644 --- a/src/nepi/resources/planetlab/scripts/pl-vif-passfd.py +++ b/src/nepi/resources/planetlab/scripts/pl-vif-passfd.py @@ -21,20 +21,20 @@ def get_options(): (options, args) = parser.parse_args() - return (options.address, options.fd_socket_name) + return (options.address, options.vif_socket) if __name__ == '__main__': - (address, socket_name) = get_options() + (address, vif_socket) = get_options() # This script sends a message (PASSFD_MSG) to the process that created # the TUN/TAP device to request that it sens the file descriptor associated # to the TUN/TAP to another process. The other process is waiting for # the file descriptor on 'address' sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.connect(socket_name) + sock.connect(vif_socket) emsg = base64.b64encode(PASSFD_MSG) - eargs = base64.b64encode(address) + eargs = address encoded = "%s|%s\n" % (emsg, eargs) sock.send(encoded) diff --git a/src/nepi/resources/planetlab/tap.py b/src/nepi/resources/planetlab/tap.py index 0066b90f..26277a27 100644 --- a/src/nepi/resources/planetlab/tap.py +++ b/src/nepi/resources/planetlab/tap.py @@ -54,7 +54,7 @@ class PlanetlabTap(LinuxApplication): "Name of the network interface (e.g. eth0, wlan0, etc)", flags = Flags.NoWrite) - up = Attribute("up", "Link up", + up = Attribute("up", "Link up", default = True, type = Types.Bool) snat = Attribute("snat", "Set SNAT=1", diff --git a/src/nepi/resources/planetlab/vroute.py b/src/nepi/resources/planetlab/vroute.py index 699c6391..fe9c9526 100644 --- a/src/nepi/resources/planetlab/vroute.py +++ b/src/nepi/resources/planetlab/vroute.py @@ -39,12 +39,21 @@ class PlanetlabVroute(LinuxApplication): def _register_attributes(cls): action = Attribute("action", "Either add or del", allowed = ["add", "del"], + default = "add", + flags = Flags.Design) + + prefix = Attribute("prefix", "IPv4 Prefix", + flags = Flags.Design) + + nexthop = Attribute("nexthop", "IPv4 Address of the next hop", flags = Flags.Design) network = Attribute("network", "IPv4 Network Address", flags = Flags.Design) cls._register_attribute(action) + cls._register_attribute(prefix) + cls._register_attribute(nexthop) cls._register_attribute(network) def __init__(self, ec, guid): @@ -65,7 +74,8 @@ class PlanetlabVroute(LinuxApplication): def upload_sources(self): # upload vif-creation python script - pl_vroute = os.path.join(os.path.dirname(__file__), "scripts", + pl_vroute = os.path.join(os.path.dirname(__file__), + "scripts", "pl-vroute.py") self.node.upload(pl_vroute, @@ -86,10 +96,12 @@ class PlanetlabVroute(LinuxApplication): # Overwrite file every time. # The stop.sh has the path to the socket, wich should change # on every experiment run. - super(PlanetlabVroute, self).upload_start_command(overwrite = True) - - (out, err), proc = self.execute_command(self.get("command"), blocking = True) - + command = self.get("command") + shfile = os.path.join(self.app_home, "start.sh") + self.node.run_and_wait(command, self.run_home, + shfile=shfile, + overwrite=True) + def do_deploy(self): if not self.tap or self.tap.state < ResourceState.PROVISIONED: self.ec.schedule(self.reschedule_delay, self.deploy) @@ -147,20 +159,26 @@ class PlanetlabVroute(LinuxApplication): command = ["sudo -S python ${SRC}/pl-vroute.py"] command.append("-a %s" % self.get("action")) command.append("-n %s" % self.get("network")) - command.append("-p %s" % self.tap.get("prefix")) + command.append("-p %s" % self.get("prefix")) command.append("-g %s" % self.tap.get("pointopoint")) command.append("-f %s" % self.tap.get("deviceName")) - return " ".join(command) + command = " ".join(command) + + command = self.replace_paths(command) + return command @property def _stop_command(self): command = ["sudo -S python ${SRC}/pl-vroute.py"] command.append("-a %s" % "del") command.append("-n %s" % self.get("network")) - command.append("-p %s" % self.tap.get("prefix")) - command.append("-g %s" % self.tap.get("pointopoint")) + command.append("-p %s" % self.get("prefix")) + command.append("-g %s" % self.get("nexthop")) command.append("-f %s" % self.tap.get("deviceName")) - return " ".join(command) + command = " ".join(command) + + command = self.replace_paths(command) + return command def valid_connection(self, guid): # TODO: Validate! diff --git a/src/nepi/util/sshfuncs.py b/src/nepi/util/sshfuncs.py index 33e1e108..508d462d 100644 --- a/src/nepi/util/sshfuncs.py +++ b/src/nepi/util/sshfuncs.py @@ -35,6 +35,8 @@ import threading import time import tempfile +_re_inet = re.compile("\d+:\s+(?P[a-z0-9_-]+)\s+inet6?\s+(?P[a-f0-9.:/]+)\s+(brd\s+[0-9.]+)?.*scope\s+global.*") + logger = logging.getLogger("sshfuncs") def log(msg, level, out = None, err = None): @@ -75,6 +77,23 @@ class ProcStatus: hostbyname_cache = dict() hostbyname_cache_lock = threading.Lock() +def resolve_hostname(host): + ip = None + + if host in ["localhost", "127.0.0.1", "::1"]: + try: + ip = socket.gethostbyname(socket.gethostname()) + except socket.gaierror, e: #[Errno -5] No address associated with hostname + p = subprocess.Popen("ip -o addr list", shell=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + m = _re_inet.findall(stdout) + ip = m[0][1].split("/")[0] + else: + ip = socket.gethostbyname(host) + + return ip + def gethostbyname(host): global hostbyname_cache global hostbyname_cache_lock @@ -82,7 +101,7 @@ def gethostbyname(host): hostbyname = hostbyname_cache.get(host) if not hostbyname: with hostbyname_cache_lock: - hostbyname = socket.gethostbyname(host) + hostbyname = resolve_hostname(host) hostbyname_cache[host] = hostbyname msg = " Added hostbyname %s - %s " % (host, hostbyname) diff --git a/test/resources/planetlab/ns3/cross_ns3_linux_ping.py b/test/resources/planetlab/ns3/cross_ns3_linux_ping.py index 4b44e5dc..c73d08a7 100755 --- a/test/resources/planetlab/ns3/cross_ns3_linux_ping.py +++ b/test/resources/planetlab/ns3/cross_ns3_linux_ping.py @@ -43,10 +43,11 @@ def add_fd_device(ec, node, ip, prefix): return dev -def add_tap_device(ec, node, ip, prefix): +def add_tap_device(ec, node, ip, prefix, pointopoint): dev = ec.register_resource("planetlab::Tap") ec.set(dev, "ip", ip) ec.set(dev, "prefix", prefix) + ec.set(dev, "pointopoint", pointopoint) ec.register_connection(node, dev) return dev @@ -65,7 +66,8 @@ def add_point2point_device(ec, node, ip, prefix): class LinuxNS3FdNetDeviceTest(unittest.TestCase): def setUp(self): #self.fedora_host = "nepi2.pl.sophia.inria.fr" - self.fedora_host = "planetlab2.sics.se" + #self.fedora_host = "planetlab2.s3.kth.se" + self.fedora_host = "planet2.servers.ua.pt" # ple2.ipv6.lip6.fr # inriarennes2.irisa.fr # planetlab1.upc.es @@ -76,6 +78,7 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase): @skipIfNotAlive def t_cross_ping(self, host, user, identity): + ec = ExperimentController(exp_id = "test-pl-ns3-tap-fd") node = ec.register_resource("planetlab::Node") @@ -93,17 +96,24 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase): #ec.set(simu, "nsLog", "FdNetDevice") ec.register_connection(simu, node) + net1 = "%s.0" % self.netblock + net2 = "%s.4" % self.netblock + ip1 = "%s.1" % self.netblock + ip2 = "%s.2" % self.netblock + ip3 = "%s.5" % self.netblock + ip4 = "%s.6" % self.netblock + nsnode1 = add_ns3_node(ec, simu) - dev1 = add_point2point_device(ec, nsnode1, "%s.1" % self.netblock, "30") + dev1 = add_point2point_device(ec, nsnode1, ip1, "30") nsnode2 = add_ns3_node(ec, simu) - dev2 = add_point2point_device(ec, nsnode2, "%s.2" % self.netblock, "30") + dev2 = add_point2point_device(ec, nsnode2, ip2, "30") # Add routes on the NS3 side r1 = ec.register_resource("ns3::Route") - ec.set(r1, "network", "%s.4" % self.netblock) + ec.set(r1, "network", net2) ec.set(r1, "prefix", "30") - ec.set(r1, "nexthop", "%s.1" % self.netblock) + ec.set(r1, "nexthop", ip1) ec.register_connection(r1, nsnode2) # Create channel @@ -112,24 +122,25 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase): ec.register_connection(chan, dev1) ec.register_connection(chan, dev2) - fddev = add_fd_device(ec, nsnode1, "%s.5" % self.netblock, "30") + fddev = add_fd_device(ec, nsnode1, ip3, "30") ec.enable_trace(fddev, "pcap") ec.enable_trace(fddev, "promiscPcap") ec.enable_trace(fddev, "ascii") - tap = add_tap_device(ec, node, "%s.6" % self.netblock, "30") + tap = add_tap_device(ec, node, ip4, "30", ip3) crosslink = ec.register_resource("planetlab::ns3::TunTapFdLink") ec.register_connection(crosslink, tap) ec.register_connection(crosslink, fddev) r2 = ec.register_resource("planetlab::Vroute") - ec.set(r2, "action", "add") - ec.set(r2, "network", "%s.0/30" % self.netblock) + ec.set(r2, "network", net1) + ec.set(r2, "prefix", "30") + ec.set(r2, "nexthop", ip3) ec.register_connection(r2, tap) app = ec.register_resource("linux::Application") - ec.set(app, "command", "ping -c3 %s.1" % self.netblock) + ec.set(app, "command", "ping -c3 %s" % ip1) ec.register_connection(app, node) ec.register_condition(app, ResourceAction.START, simu, @@ -147,7 +158,7 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase): ec.release() pcap = ec.trace(fddev, "pcap") - self.assertTrue(len(pcap) > 4000) + self.assertTrue(len(pcap) > 1500) ec.shutdown() def test_cross_ping_fedora(self):