X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fresources%2Flinux%2Ftap.py;h=f2e42a682b643dc88e3a6956d94873a8cb2b9348;hb=f7c6792813947d3707accd690ad7bbe83277798f;hp=ee977ef304947e83197003cbb4c16567e2d25c3a;hpb=7b73c5d0b8d2c03116baef752357a52998f451f0;p=nepi.git diff --git a/src/nepi/resources/linux/tap.py b/src/nepi/resources/linux/tap.py index ee977ef3..f2e42a68 100644 --- a/src/nepi/resources/linux/tap.py +++ b/src/nepi/resources/linux/tap.py @@ -76,6 +76,10 @@ class LinuxTap(LinuxApplication): "Public IP of remote endpoint for GRE tunnel", flags = Flags.Design) + pi = Attribute("pi", "Add PI (protocol information) header", + default = False, + type = Types.Bool) + tear_down = Attribute("tearDown", "Bash script to be executed before releasing the resource", flags = Flags.Design) @@ -90,12 +94,14 @@ class LinuxTap(LinuxApplication): cls._register_attribute(txqueuelen) cls._register_attribute(gre_key) cls._register_attribute(gre_remote) + cls._register_attribute(pi) cls._register_attribute(tear_down) def __init__(self, ec, guid): super(LinuxTap, self).__init__(ec, guid) self._home = "tap-%s" % self.guid self._gre_enabled = False + self._tunnel_mode = False @property def node(self): @@ -112,7 +118,37 @@ class LinuxTap(LinuxApplication): return self._gre_enabled + @property + def tunnel_mode(self): + if not self._tunnel_mode: + from nepi.resources.linux.tunnel import LinuxTunnel + tunnel = self.get_connected(LinuxTunnel.get_rtype()) + if tunnel: self._tunnel_mode = True + + return self._tunnel_mode + def upload_sources(self): + scripts = [] + + # udp-connect python script + udp_connect = os.path.join(os.path.dirname(__file__), "scripts", + "linux-udp-connect.py") + + scripts.append(udp_connect) + + # tunnel creation python script + tunchannel = os.path.join(os.path.dirname(__file__), "scripts", + "tunchannel.py") + + scripts.append(tunchannel) + + # Upload scripts + scripts = ";".join(scripts) + + self.node.upload(scripts, + os.path.join(self.node.src_dir), + overwrite = False) + # upload stop.sh script stop_command = self.replace_paths(self._stop_command) @@ -127,7 +163,7 @@ class LinuxTap(LinuxApplication): def upload_start_command(self): # If GRE mode is enabled, TAP creation is delayed until the # tunnel is established - if not self.gre_enabled: + if not self.tunnel_mode: # We want to make sure the device is up and running # before the deploy is over, so we execute the # start script now and wait until it finishes. @@ -225,7 +261,7 @@ class LinuxTap(LinuxApplication): # invoke connect script cmd = "bash %s" % shfile - (out, err), proc = self.node.run(cmd, connection_run_home) + (out, err), proc = self.node.run(cmd, connection_run_home) # check if execution errors occurred msg = " Failed to connect endpoints " @@ -249,6 +285,105 @@ class LinuxTap(LinuxApplication): return True + ## XXX: NOT REALLY WORKING YET! + 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(udp_connect_command, + shfile, + text = True, + 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("ip4")) + + # Planetlab TAPs always use PI headers + from nepi.resources.planetlab.tap import PlanetlabTap + if self.is_rm_instance(PlanetlabTap.get_rtype()): + self.set("pi", True) + + remote_ip = socket.gethostbyname( + remote_endpoint.node.get("hostname")) + + 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 the start command to configure TAP with peer info + start_command = self._start_command + + command = ["( "] + command.append(start_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}/linux-udp-connect.py") + command.append("-N %s" % self.get("deviceName")) + command.append("-t %s" % self.vif_type) + if self.get("pi"): + command.append("-p") + 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("ip4")) @@ -270,14 +405,31 @@ class LinuxTap(LinuxApplication): @property def _start_command(self): command = [] - command.append("sudo -S ip tuntap add %s mode tap" % self.get("deviceName")) - command.append("sudo -S ip link set %s up" % self.get("deviceName")) - command.append("sudo -S ip addr add %s/%d dev %s" % ( - self.get("ip4"), - self.get("prefix4"), - self.get("deviceName"), - )) - return ";".join(command) + if not self.gre_enabled: + # Make sure to clean TAP if it existed + stop_command = self._stop_command + + start_command = [] + start_command.append("sudo -S ip tuntap add %s mode %s %s" % ( + self.get("deviceName"), + self.vif_prefix, + "pi" if self.get("pi") else "")) + start_command.append("sudo -S ip link set %s up" % self.get("deviceName")) + start_command.append("sudo -S ip addr add %s/%d dev %s" % ( + self.get("ip4"), + self.get("prefix4"), + self.get("deviceName"), + )) + + start_command = ";".join(start_command) + + command.append("(") + command.append(stop_command) + command.append(") ; (") + command.append(start_command) + command.append(")") + + return " ".join(command) @property def _stop_command(self):