Bug fixing and ordering openvswitch code
[nepi.git] / src / nepi / resources / planetlab / tap.py
index 1785f43..5df36c4 100644 (file)
 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
 
 from nepi.execution.attribute import Attribute, Flags, Types
 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
 
 from nepi.execution.attribute import Attribute, Flags, Types
-from nepi.execution.resource import clsinit_copy, ResourceState, \
-        reschedule_delay
+from nepi.execution.resource import clsinit_copy, ResourceState 
 from nepi.resources.linux.application import LinuxApplication
 from nepi.resources.planetlab.node import PlanetlabNode
 from nepi.util.timefuncs import tnow, tdiffsec
 
 import os
 from nepi.resources.linux.application import LinuxApplication
 from nepi.resources.planetlab.node import PlanetlabNode
 from nepi.util.timefuncs import tnow, tdiffsec
 
 import os
-import socket
 import time
 
 PYTHON_VSYS_VERSION = "1.0"
 
 @clsinit_copy
 class PlanetlabTap(LinuxApplication):
 import time
 
 PYTHON_VSYS_VERSION = "1.0"
 
 @clsinit_copy
 class PlanetlabTap(LinuxApplication):
-    _rtype = "PlanetlabTap"
+    _rtype = "planetlab::Tap"
     _help = "Creates a TAP device on a PlanetLab host"
     _help = "Creates a TAP device on a PlanetLab host"
-    _backend = "planetlab"
+    _platform = "planetlab"
 
     @classmethod
     def _register_attributes(cls):
 
     @classmethod
     def _register_attributes(cls):
-        ip4 = Attribute("ip4", "IPv4 Address",
+        ip = Attribute("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)
 
               flags = Flags.Design)
 
         mac = Attribute("mac", "MAC Address",
                 flags = Flags.Design)
 
-        prefix4 = Attribute("prefix4", "IPv4 network prefix",
-                type = Types.Integer,
+        prefix = Attribute("prefix", "IPv4 network prefix of the endpoint",
                 flags = Flags.Design)
 
         mtu = Attribute("mtu", "Maximum transmition unit for device",
                 flags = Flags.Design)
 
         mtu = Attribute("mtu", "Maximum transmition unit for device",
@@ -55,7 +54,7 @@ class PlanetlabTap(LinuxApplication):
                 "Name of the network interface (e.g. eth0, wlan0, etc)",
                 flags = Flags.NoWrite)
 
                 "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", 
                 type = Types.Bool)
         
         snat = Attribute("snat", "Set SNAT=1", 
@@ -84,9 +83,9 @@ class PlanetlabTap(LinuxApplication):
                 "Bash script to be executed before releasing the resource",
                 flags = Flags.Design)
 
                 "Bash script to be executed before releasing the resource",
                 flags = Flags.Design)
 
-        cls._register_attribute(ip4)
+        cls._register_attribute(ip)
         cls._register_attribute(mac)
         cls._register_attribute(mac)
-        cls._register_attribute(prefix4)
+        cls._register_attribute(prefix)
         cls._register_attribute(mtu)
         cls._register_attribute(devname)
         cls._register_attribute(up)
         cls._register_attribute(mtu)
         cls._register_attribute(devname)
         cls._register_attribute(up)
@@ -192,7 +191,7 @@ class PlanetlabTap(LinuxApplication):
 
     def do_deploy(self):
         if not self.node or self.node.state < ResourceState.PROVISIONED:
 
     def do_deploy(self):
         if not self.node or self.node.state < ResourceState.PROVISIONED:
-            self.ec.schedule(reschedule_delay, self.deploy)
+            self.ec.schedule(self.reschedule_delay, self.deploy)
         else:
             if not self.get("command"):
                 self.set("command", self._start_command)
         else:
             if not self.get("command"):
                 self.set("command", self._start_command)
@@ -260,7 +259,7 @@ class PlanetlabTap(LinuxApplication):
 
         for rm in rms:
             if rm.state < ResourceState.STOPPED:
 
         for rm in rms:
             if rm.state < ResourceState.STOPPED:
-                self.ec.schedule(reschedule_delay, self.release)
+                self.ec.schedule(self.reschedule_delay, self.release)
                 return 
 
         super(PlanetlabTap, self).do_release()
                 return 
 
         super(PlanetlabTap, self).do_release()
@@ -342,6 +341,12 @@ class PlanetlabTap(LinuxApplication):
 
         return True
 
 
         return True
 
+    def initiate_udp_connection(self, remote_endpoint, connection_app_home, 
+            connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
+        port = self.udp_connect(remote_endpoint, connection_app_home, 
+            connection_run_home, cipher, cipher_key, bwlimit, txqueuelen)
+        return port
+
     def udp_connect(self, remote_endpoint, connection_app_home, 
             connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
         udp_connect_command = self._udp_connect_command(
     def udp_connect(self, remote_endpoint, connection_app_home, 
             connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
         udp_connect_command = self._udp_connect_command(
@@ -349,14 +354,14 @@ class PlanetlabTap(LinuxApplication):
                 cipher, cipher_key, bwlimit, txqueuelen)
 
         # upload command to connect.sh script
                 cipher, cipher_key, bwlimit, txqueuelen)
 
         # upload command to connect.sh script
-        shfile = os.path.join(connection_app_home, "udp-connect.sh")
+        shfile = os.path.join(self.app_home, "udp-connect.sh")
         self.node.upload_command(udp_connect_command,
                 shfile = shfile,
                 overwrite = False)
 
         # invoke connect script
         cmd = "bash %s" % shfile
         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) 
+        (out, err), proc = self.node.run(cmd, self.run_home) 
              
         # check if execution errors occurred
         msg = "Failed to connect endpoints "
              
         # check if execution errors occurred
         msg = "Failed to connect endpoints "
@@ -366,36 +371,38 @@ class PlanetlabTap(LinuxApplication):
             raise RuntimeError, msg
     
         # Wait for pid file to be generated
             raise RuntimeError, msg
     
         # Wait for pid file to be generated
-        pid, ppid = self.node.wait_pid(connection_run_home)
+        self._pid, self._ppid = self.node.wait_pid(self.run_home)
         
         # If the process is not running, check for error information
         # on the remote machine
         
         # 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)
+        if not self._pid or not self._ppid:
+            (out, err), proc = self.node.check_errors(self.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
 
             # 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
+        port = self.wait_local_port()
+
+        return port
 
     def _udp_connect_command(self, remote_endpoint, connection_run_home, 
             cipher, cipher_key, bwlimit, txqueuelen):
 
 
     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"))
+        # Set the remote endpoint, (private) IP of the device
+        self.set("pointopoint", remote_endpoint.get("ip"))
 
 
-        remote_ip = socket.gethostbyname(
-                remote_endpoint.node.get("ip"))
+        # Public IP of the node
+        remote_ip = remote_endpoint.node.get("ip")
 
 
-        local_port_file = os.path.join(connection_run_home, 
+        local_port_file = os.path.join(self.run_home, 
                 "local_port")
 
                 "local_port")
 
-        remote_port_file = os.path.join(connection_run_home, 
+        remote_port_file = os.path.join(self.run_home, 
                 "remote_port")
 
                 "remote_port")
 
-        ret_file = os.path.join(connection_run_home, 
+        ret_file = os.path.join(self.run_home, 
                 "ret_file")
 
         # Generate UDP connect command
                 "ret_file")
 
         # Generate UDP connect command
@@ -432,11 +439,73 @@ class PlanetlabTap(LinuxApplication):
 
         return command
 
 
         return command
 
+    def establish_udp_connection(self, remote_endpoint, 
+            connection_app_home,
+            connection_run_home, 
+            port):
+        # upload remote port number to file
+        rem_port = "%s\n" % port
+        self.node.upload(rem_port,
+                os.path.join(self.run_home, "remote_port"),
+                text = True, 
+                overwrite = False)
+
+    def verify_connection(self):
+        self.wait_result()
+
+    def terminate_connection(self):
+        if  self._pid and self._ppid:
+            (out, err), proc = self.node.kill(self._pid, self._ppid, 
+                    sudo = True) 
+
+            # check if execution errors occurred
+            if proc.poll() and err:
+                msg = " Failed to Kill the Tap"
+                self.error(msg, out, err)
+                raise RuntimeError, msg
+
+    def check_status(self):
+        return self.node.status(self._pid, self._ppid)
+
+    def wait_local_port(self):
+        """ Waits until the local_port file for the endpoint is generated, 
+        and returns the port number 
+        
+        """
+        return self.wait_file("local_port")
+
+    def wait_result(self):
+        """ Waits until the return code file for the endpoint is generated 
+        
+        """ 
+        return self.wait_file("ret_file")
+    def wait_file(self, filename):
+        """ Waits until file on endpoint is generated """
+        result = None
+        delay = 1.0
+
+        for i in xrange(20):
+            (out, err), proc = self.node.check_output(
+                    self.run_home, filename)
+            if out:
+                result = out.strip()
+                break
+            else:
+                time.sleep(delay)
+                delay = delay * 1.5
+        else:
+            msg = "Couldn't retrieve %s" % filename
+            self.error(msg, out, err)
+            raise RuntimeError, msg
+
+        return result
+
     def _gre_connect_command(self, remote_endpoint, connection_run_home): 
     def _gre_connect_command(self, remote_endpoint, connection_run_home): 
-        # Set the remote endpoint
-        self.set("pointopoint", remote_endpoint.get("ip4"))
-        self.set("greRemote", socket.gethostbyname(
-            remote_endpoint.node.get("ip")))
+        # 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
 
 
         # Generate GRE connect command
 
@@ -465,8 +534,8 @@ class PlanetlabTap(LinuxApplication):
             command = ["sudo -S python ${SRC}/pl-vif-create.py"]
             
             command.append("-t %s" % self.vif_type)
             command = ["sudo -S python ${SRC}/pl-vif-create.py"]
             
             command.append("-t %s" % self.vif_type)
-            command.append("-a %s" % self.get("ip4"))
-            command.append("-n %d" % self.get("prefix4"))
+            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)
 
             command.append("-f %s " % self.vif_name_file)
             command.append("-S %s " % self.sock_name)
 
@@ -508,8 +577,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("-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("ip4"))
-        command.append("-n %d" % self.get("prefix4"))
+        command.append("-a %s" % self.get("ip"))
+        command.append("-n %s" % self.get("prefix"))
 
         if self.get("snat") == True:
             command.append("-s")
 
         if self.get("snat") == True:
             command.append("-s")