X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fresources%2Fplanetlab%2Ftap.py;h=61ff3d69574a8b1f4baff2e33b86355b9ac8983f;hb=00be6a6a023debb382d6d351cf005b233da20623;hp=5a47663cf2b7c13b109dce252af82ffa339ec71f;hpb=38575a0f27f26511965771dde8320060b10252dd;p=nepi.git diff --git a/src/nepi/resources/planetlab/tap.py b/src/nepi/resources/planetlab/tap.py index 5a47663c..61ff3d69 100644 --- a/src/nepi/resources/planetlab/tap.py +++ b/src/nepi/resources/planetlab/tap.py @@ -18,9 +18,8 @@ # Author: Alina Quereilhac from nepi.execution.attribute import Attribute, Flags, Types -from nepi.execution.resource import clsinit_copy, ResourceState, \ - reschedule_delay -from nepi.resources.linux.application import LinuxApplication +from nepi.execution.resource import clsinit_copy, ResourceState +from nepi.resources.linux.tap import LinuxTap from nepi.resources.planetlab.node import PlanetlabNode from nepi.util.timefuncs import tnow, tdiffsec @@ -30,73 +29,18 @@ import time PYTHON_VSYS_VERSION = "1.0" @clsinit_copy -class PlanetlabTap(LinuxApplication): - _rtype = "PlanetlabTap" +class PlanetlabTap(LinuxTap): + _rtype = "planetlab::Tap" _help = "Creates a TAP device on a PlanetLab host" - _backend = "planetlab" + _platform = "planetlab" @classmethod def _register_attributes(cls): - endpoint_ip = Attribute("endpoint_ip", "IP of the endpoint. This is the attribute " - "you should use to establish a tunnel or a remote " - "connection between endpoint", - flags = Flags.Design) - - mac = Attribute("mac", "MAC Address", - flags = Flags.Design) - - endpoint_prefix = Attribute("endpoint_prefix", "IPv4 network prefix of the endpoint", - type = Types.Integer, - flags = Flags.Design) - - mtu = Attribute("mtu", "Maximum transmition unit for device", - type = Types.Integer) - - devname = Attribute("deviceName", - "Name of the network interface (e.g. eth0, wlan0, etc)", - flags = Flags.NoWrite) - - up = Attribute("up", "Link up", - type = Types.Bool) - snat = Attribute("snat", "Set SNAT=1", type = Types.Bool, flags = Flags.Design) - pointopoint = Attribute("pointopoint", "Peer IP address", - flags = Flags.Design) - - txqueuelen = Attribute("txqueuelen", "Length of transmission queue", - flags = Flags.Design) - - txqueuelen = Attribute("txqueuelen", "Length of transmission queue", - flags = Flags.Design) - - gre_key = Attribute("greKey", - "GRE key to be used to configure GRE tunnel", - default = "1", - flags = Flags.Design) - - gre_remote = Attribute("greRemote", - "Public IP of remote endpoint for GRE tunnel", - flags = Flags.Design) - - tear_down = Attribute("tearDown", - "Bash script to be executed before releasing the resource", - flags = Flags.Design) - - cls._register_attribute(endpoint_ip) - cls._register_attribute(mac) - cls._register_attribute(endpoint_prefix) - cls._register_attribute(mtu) - cls._register_attribute(devname) - cls._register_attribute(up) cls._register_attribute(snat) - cls._register_attribute(pointopoint) - cls._register_attribute(txqueuelen) - cls._register_attribute(gre_key) - cls._register_attribute(gre_remote) - cls._register_attribute(tear_down) def __init__(self, ec, guid): super(PlanetlabTap, self).__init__(ec, guid) @@ -109,15 +53,6 @@ class PlanetlabTap(LinuxApplication): if node: return node[0] raise RuntimeError, "TAP/TUN devices must be connected to Node" - @property - def gre_enabled(self): - if not self._gre_enabled: - from nepi.resources.linux.gretunnel import LinuxGRETunnel - gre = self.get_connected(LinuxGRETunnel.get_rtype()) - if gre: self._gre_enabled = True - - return self._gre_enabled - def upload_sources(self): scripts = [] @@ -140,14 +75,20 @@ class PlanetlabTap(LinuxApplication): scripts.append(pl_vif_down) # udp-connect python script - pl_vif_connect = os.path.join(os.path.dirname(__file__), "scripts", - "pl-vif-udp-connect.py") + udp_connect = os.path.join(os.path.dirname(__file__), + "..", + "linux", + "scripts", + "linux-udp-connect.py") - scripts.append(pl_vif_connect) + scripts.append(udp_connect) # tunnel creation python script - tunchannel = os.path.join(os.path.dirname(__file__), "..", "linux", - "scripts", "tunchannel.py") + tunchannel = os.path.join(os.path.dirname(__file__), + "..", + "linux", + "scripts", + "tunchannel.py") scripts.append(tunchannel) @@ -169,103 +110,18 @@ class PlanetlabTap(LinuxApplication): overwrite = True) def upload_start_command(self): - # If GRE mode is enabled, TAP creation is delayed until the - # tunnel is established + super(PlanetlabTap, self).upload_start_command() + + # Planetlab TAPs always add a PI header + self.set("pi", True) + if not self.gre_enabled: - # Overwrite file every time. - # The start.sh has the path to the socket, wich should change - # on every experiment run. - super(PlanetlabTap, self).upload_start_command(overwrite = True) - - # We want to make sure the device is up and running - # before the deploy finishes, so we execute now the - # start script. We run it in background, because the - # TAP will live for as long as the process that - # created it is running, and wait until the TAP - # is created. - self._run_in_background() - # After creating the TAP, the pl-vif-create.py script # will write the name of the TAP to a file. We wait until # we can read the interface name from the file. vif_name = self.wait_vif_name() self.set("deviceName", vif_name) - def do_deploy(self): - if not self.node or self.node.state < ResourceState.PROVISIONED: - self.ec.schedule(reschedule_delay, self.deploy) - else: - if not self.get("command"): - self.set("command", self._start_command) - - if not self.get("depends"): - self.set("depends", self._dependencies) - - if not self.get("install"): - self.set("install", self._install) - - self.do_discover() - self.do_provision() - - self.set_ready() - - 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 - - def do_stop(self): - command = self.get('command') or '' - - if self.state == ResourceState.STARTED: - self.info("Stopping command '%s'" % command) - - command = "bash %s" % os.path.join(self.app_home, "stop.sh") - (out, err), proc = self.execute_command(command, - blocking = True) - - if err: - msg = " Failed to stop command '%s' " % command - self.error(msg, out, err) - - self.set_stopped() - - @property - def state(self): - state_check_delay = 0.5 - if self._state == ResourceState.STARTED and \ - tdiffsec(tnow(), self._last_state_check) > state_check_delay: - - if self.get("deviceName"): - (out, err), proc = self.node.execute("ifconfig") - - if out.strip().find(self.get("deviceName")) == -1: - # tap is not running is not running (socket not found) - self.set_stopped() - - self._last_state_check = tnow() - - return self._state - - def do_release(self): - # Node needs to wait until all associated RMs are released - # to be released - from nepi.resources.linux.tunnel import LinuxTunnel - rms = self.get_connected(LinuxTunnel.get_rtype()) - - for rm in rms: - if rm.state < ResourceState.STOPPED: - self.ec.schedule(reschedule_delay, self.release) - return - - super(PlanetlabTap, self).do_release() - def wait_vif_name(self, exec_run_home = None): """ Waits until the vif_name file for the command is generated, and returns the vif_name for the device """ @@ -302,40 +158,9 @@ class PlanetlabTap(LinuxApplication): def gre_connect(self, remote_endpoint, connection_app_home, connection_run_home): - gre_connect_command = self._gre_connect_command( - remote_endpoint, connection_run_home) - - # upload command to connect.sh script - shfile = os.path.join(connection_app_home, "gre-connect.sh") - self.node.upload_command(gre_connect_command, - shfile = shfile, - overwrite = False) - - # invoke connect script - cmd = "bash %s" % shfile - (out, err), proc = self.node.run(cmd, connection_run_home) - - # check if execution errors occurred - msg = " Failed to connect endpoints " - - if proc.poll() or err: - self.error(msg, out, err) - raise RuntimeError, msg - - # Wait for pid file to be generated - pid, ppid = self.node.wait_pid(connection_run_home) - - # If the process is not running, check for error information - # on the remote machine - if not pid or not ppid: - (out, err), proc = self.node.check_errors(connection_run_home) - # Out is what was written in the stderr file - if err: - msg = " Failed to start command '%s' " % command - self.error(msg, out, err) - raise RuntimeError, msg - - # After creating the TAP, the pl-vif-create.py script + super(PlanetlabTap, self).gre_connect(remote_endpoint, + connection_app_home, connection_run_home) + # After creating the TAP, the pl-vif-create.py script # will write the name of the TAP to a file. We wait until # we can read the interface name from the file. vif_name = self.wait_vif_name(exec_run_home = connection_run_home) @@ -343,98 +168,11 @@ class PlanetlabTap(LinuxApplication): return True - def udp_connect(self, remote_endpoint, connection_app_home, - connection_run_home, cipher, cipher_key, bwlimit, txqueuelen): - udp_connect_command = self._udp_connect_command( - remote_endpoint, connection_run_home, - cipher, cipher_key, bwlimit, txqueuelen) - - # upload command to connect.sh script - shfile = os.path.join(connection_app_home, "udp-connect.sh") - self.node.upload_command(udp_connect_command, - shfile = shfile, - overwrite = False) - - # invoke connect script - cmd = "bash %s" % shfile - (out, err), proc = self.node.run(cmd, connection_run_home) - - # check if execution errors occurred - msg = "Failed to connect endpoints " - - if proc.poll(): - self.error(msg, out, err) - raise RuntimeError, msg - - # Wait for pid file to be generated - pid, ppid = self.node.wait_pid(connection_run_home) - - # If the process is not running, check for error information - # on the remote machine - if not pid or not ppid: - (out, err), proc = self.node.check_errors(connection_run_home) - # Out is what was written in the stderr file - if err: - msg = " Failed to start command '%s' " % command - self.error(msg, out, err) - raise RuntimeError, msg - - return pid, ppid - - def _udp_connect_command(self, remote_endpoint, connection_run_home, - cipher, cipher_key, bwlimit, txqueuelen): - - # Set the remote endpoint - self.set("pointopoint", remote_endpoint.get("endpoint_ip")) - - remote_ip = remote_endpoint.node.get("ip") - - local_port_file = os.path.join(connection_run_home, - "local_port") - - remote_port_file = os.path.join(connection_run_home, - "remote_port") - - ret_file = os.path.join(connection_run_home, - "ret_file") - - # Generate UDP connect command - # Use pl-vif-up.py script to configure TAP with peer info - vif_up_command = self._vif_up_command - - command = ["( "] - command.append(vif_up_command) - - # Use pl-vid-udp-connect.py to stablish the tunnel between endpoints - command.append(") & (") - command.append("sudo -S") - command.append("PYTHONPATH=$PYTHONPATH:${SRC}") - command.append("python ${SRC}/pl-vif-udp-connect.py") - command.append("-t %s" % self.vif_type) - command.append("-S %s " % self.sock_name) - command.append("-l %s " % local_port_file) - command.append("-r %s " % remote_port_file) - command.append("-H %s " % remote_ip) - command.append("-R %s " % ret_file) - if cipher: - command.append("-c %s " % cipher) - if cipher_key: - command.append("-k %s " % cipher_key) - if txqueuelen: - command.append("-q %s " % txqueuelen) - if bwlimit: - command.append("-b %s " % bwlimit) - - command.append(")") - - command = " ".join(command) - command = self.replace_paths(command) - - return command - - def _gre_connect_command(self, remote_endpoint, connection_run_home): - # Set the remote endpoint - self.set("pointopoint", remote_endpoint.get("endpoint_ip")) + def _gre_connect_command(self, remote_endpoint, connection_app_home, + connection_run_home): + # Set the remote endpoint, (private) IP of the device + self.set("pointopoint", remote_endpoint.get("ip")) + # Public IP of the node self.set("greRemote", remote_endpoint.node.get("ip")) # Generate GRE connect command @@ -464,8 +202,8 @@ class PlanetlabTap(LinuxApplication): command = ["sudo -S python ${SRC}/pl-vif-create.py"] command.append("-t %s" % self.vif_type) - command.append("-a %s" % self.get("endpoint_ip")) - command.append("-n %d" % self.get("endpoint_prefix")) + command.append("-a %s" % self.get("ip")) + command.append("-n %s" % self.get("prefix")) command.append("-f %s " % self.vif_name_file) command.append("-S %s " % self.sock_name) @@ -507,8 +245,8 @@ class PlanetlabTap(LinuxApplication): command.append("-u %s" % self.node.get("username")) command.append("-N %s" % device_name) command.append("-t %s" % self.vif_type) - command.append("-a %s" % self.get("endpoint_ip")) - command.append("-n %d" % self.get("endpoint_prefix")) + command.append("-a %s" % self.get("ip")) + command.append("-n %s" % self.get("prefix")) if self.get("snat") == True: command.append("-s") @@ -546,22 +284,10 @@ class PlanetlabTap(LinuxApplication): return " ".join(command) - @property - def vif_type(self): - return "IFF_TAP" - @property def vif_name_file(self): return os.path.join(self.run_home, "vif_name") - @property - def sock_name(self): - return os.path.join(self.run_home, "tap.sock") - - @property - def _dependencies(self): - return "mercurial make gcc" - @property def _install(self): # Install python-vsys and python-passfd