Delete the OVSTunnel to use the UdpTunnel instead. Just need to fix an issue with...
authorJulien Tribino <julien.tribino@inria.fr>
Thu, 11 Sep 2014 09:14:52 +0000 (11:14 +0200)
committerJulien Tribino <julien.tribino@inria.fr>
Thu, 11 Sep 2014 09:14:52 +0000 (11:14 +0200)
12 files changed:
examples/openvswitch/ovs_ping_2switches.py
examples/openvswitch/ovs_ping_3switches_line.py
examples/openvswitch/ovs_ping_3switches_loop.py
src/nepi/resources/linux/tap.py
src/nepi/resources/linux/tunnel.py
src/nepi/resources/linux/udptunnel.py
src/nepi/resources/planetlab/openvswitch/ovs.py
src/nepi/resources/planetlab/openvswitch/ovsport.py
src/nepi/resources/planetlab/openvswitch/tunnel.py [deleted file]
src/nepi/resources/planetlab/tap.py
test/resources/linux/udptunnel.py
test/resources/planetlab/udptunnel.py

index 5b7a208..4778911 100644 (file)
@@ -55,9 +55,10 @@ def add_ovs(ec, bridge_name, virtual_ip_pref, controller_ip, controller_port, no
     ec.register_connection(ovs, node)
     return ovs
 
-def add_port(ec, port_name, ovs):
+def add_port(ec, port_name, network, ovs):
     port = ec.register_resource("OVSPort")
     ec.set(port, "port_name", port_name)
+    ec.set(port, "network", network)
     ec.register_connection(port, ovs)
     return port
 
@@ -70,9 +71,8 @@ def add_tap(ec, endpoint_ip, endpoint_prefix, pointopoint, node):
     ec.register_connection(tap, node)
     return tap
 
-def add_tunnel(ec, network, port0, tap):
-    tunnel = ec.register_resource("OVSTunnel")
-    ec.set(tunnel, "network", network)
+def add_tunnel(ec, port0, tap):
+    tunnel = ec.register_resource("LinuxUdpTunnel")
     ec.register_connection(port0, tunnel)
     ec.register_connection(tunnel, tap)
     return tunnel
@@ -92,7 +92,7 @@ switch2 = "planetlab2.upc.es"
 host1 = "planetlab2.ionio.gr"
 host2 = "iraplab2.iralab.uni-karlsruhe.de"
 
-ip_controller = "xxx.yyy.zzz.ttt"
+ip_controller = "1.1.1.1"
 
 #XXX : Depends on the Vsys_tag of your slice
 network = "192.168.3.0"
@@ -111,10 +111,10 @@ ovs1 = add_ovs(ec, "nepi_bridge_1", "192.168.3.1/24", ip_controller, "6633", s1_
 ovs2 = add_ovs(ec, "nepi_bridge_2", "192.168.3.2/24", ip_controller, "6633", s2_node)
 
 # Add ports on ovs
-port1 = add_port(ec, "nepi_port1", ovs1)
-port3 = add_port(ec, "nepi_port3", ovs1)
-port2 = add_port(ec, "nepi_port2", ovs2)
-port4 = add_port(ec, "nepi_port4", ovs2)
+port1 = add_port(ec, "nepi_port1", network, ovs1)
+port3 = add_port(ec, "nepi_port3", network, ovs1)
+port2 = add_port(ec, "nepi_port2", network, ovs2)
+port4 = add_port(ec, "nepi_port4", network, ovs2)
 
 h1_node = add_node(ec, host1, slicename, pl_user, pl_password)
 h2_node = add_node(ec, host2, slicename, pl_user, pl_password)
@@ -124,9 +124,9 @@ tap1 = add_tap(ec, "192.168.3.3", 24, "192.168.3.1", h1_node)
 tap2 = add_tap(ec, "192.168.3.4", 24, "192.168.3.2", h2_node)
 
 # Connect the nodes
-tunnel1 = add_tunnel(ec, network, port1, tap1)
-tunnel2 = add_tunnel(ec, network, port2, tap2)
-tunnel3 = add_tunnel(ec, network, port3, port4)
+tunnel1 = add_tunnel(ec, port1, tap1)
+tunnel2 = add_tunnel(ec, port2, tap2)
+tunnel3 = add_tunnel(ec, port3, port4)
 
 # Add ping commands
 app1 = add_app(ec, "ping -c5 192.168.3.2", s1_node)
index 0dd1783..b48485e 100644 (file)
@@ -53,9 +53,10 @@ def add_ovs(ec, bridge_name, virtual_ip_pref, controller_ip, controller_port, no
     ec.register_connection(ovs, node)
     return ovs
 
-def add_port(ec, port_name, ovs):
+def add_port(ec, port_name, network, ovs):
     port = ec.register_resource("OVSPort")
     ec.set(port, "port_name", port_name)
+    ec.set(port, "network", network)
     ec.register_connection(port, ovs)
     return port
 
@@ -68,9 +69,8 @@ def add_tap(ec, endpoint_ip, endpoint_prefix, pointopoint, node):
     ec.register_connection(tap, node)
     return tap
 
-def add_tunnel(ec, network, port0, tap):
-    tunnel = ec.register_resource("OVSTunnel")
-    ec.set(tunnel, "network", network)
+def add_tunnel(ec, port0, tap):
+    tunnel = ec.register_resource("LinuxUdpTunnel")
     ec.register_connection(port0, tunnel)
     ec.register_connection(tunnel, tap)
     return tunnel
@@ -87,7 +87,7 @@ ec = ExperimentController(exp_id = "test-tr")
 #XXX : Need to put 6 working nodes or to let Nepi find for you
 switch1 = "planetlab2.virtues.fi"
 switch2 = "planetlab2.upc.es"
-switch3 = "planetlab2.cs.aueb.gr"
+switch3 = "planetlab1.informatik.uni-erlangen.de"
 host1 = "planetlab2.ionio.gr"
 host2 = "iraplab2.iralab.uni-karlsruhe.de"
 host3 = "planetlab2.diku.dk"
@@ -113,13 +113,13 @@ ovs2 = add_ovs(ec, "nepi_bridge_2", "192.168.3.4/24", ip_controller, "6633", s2_
 ovs3 = add_ovs(ec, "nepi_bridge_3", "192.168.3.6/24", ip_controller, "6633", s3_node)
 
 # Add ports on ovs
-port1 = add_port(ec, "nepi_port1", ovs1)
-port4 = add_port(ec, "nepi_port4", ovs1)
-port7 = add_port(ec, "nepi_port7", ovs1)
-port2 = add_port(ec, "nepi_port2", ovs2)
-port5 = add_port(ec, "nepi_port5", ovs2)
-port3 = add_port(ec, "nepi_port3", ovs3)
-port6 = add_port(ec, "nepi_port6", ovs3)
+port1 = add_port(ec, "nepi_port1", network, ovs1)
+port4 = add_port(ec, "nepi_port4", network, ovs1)
+port7 = add_port(ec, "nepi_port7", network, ovs1)
+port2 = add_port(ec, "nepi_port2", network, ovs2)
+port5 = add_port(ec, "nepi_port5", network, ovs2)
+port3 = add_port(ec, "nepi_port3", network, ovs3)
+port6 = add_port(ec, "nepi_port6", network, ovs3)
 
 h1_node = add_node(ec, host1, slicename, pl_user, pl_password)
 h2_node = add_node(ec, host2, slicename, pl_user, pl_password)
@@ -131,11 +131,11 @@ tap2 = add_tap(ec, "192.168.3.3", 24, "192.168.3.4", h2_node)
 tap3 = add_tap(ec, "192.168.3.5", 24, "192.168.3.6", h3_node)
 
 # Connect the nodes
-tunnel1 = add_tunnel(ec, network, port1, tap1)
-tunnel2 = add_tunnel(ec, network, port2, tap2)
-tunnel3 = add_tunnel(ec, network, port3, tap3)
-tunnel4 = add_tunnel(ec, network, port4, port5)
-tunnel5 = add_tunnel(ec, network, port7, port6)
+tunnel1 = add_tunnel(ec, port1, tap1)
+tunnel2 = add_tunnel(ec, port2, tap2)
+tunnel3 = add_tunnel(ec, port3, tap3)
+tunnel4 = add_tunnel(ec, port4, port5)
+tunnel5 = add_tunnel(ec, port7, port6)
 #tunnel6 = add_tunnel(ec, network, port8, port9)
 
 # Add ping commands
index 9544ba0..7dac095 100644 (file)
@@ -63,9 +63,10 @@ def add_ovs(ec, bridge_name, virtual_ip_pref, controller_ip, controller_port, no
     ec.register_connection(ovs, node)
     return ovs
 
-def add_port(ec, port_name, ovs):
+def add_port(ec, port_name, network, ovs):
     port = ec.register_resource("OVSPort")
     ec.set(port, "port_name", port_name)
+    ec.set(port, "network", network)
     ec.register_connection(port, ovs)
     return port
 
@@ -78,9 +79,8 @@ def add_tap(ec, endpoint_ip, endpoint_prefix, pointopoint, node):
     ec.register_connection(tap, node)
     return tap
 
-def add_tunnel(ec, network, port0, tap):
-    tunnel = ec.register_resource("OVSTunnel")
-    ec.set(tunnel, "network", network)
+def add_tunnel(ec, port0, tap):
+    tunnel = ec.register_resource("LinuxUdpTunnel")
     ec.register_connection(port0, tunnel)
     ec.register_connection(tunnel, tap)
     return tunnel
@@ -97,7 +97,7 @@ ec = ExperimentController(exp_id = "test-tr")
 #XXX : Need to put 6 working nodes or to let Nepi find for you
 switch1 = "planetlab2.virtues.fi"
 switch2 = "planetlab2.upc.es"
-switch3 = "planetlab2.cs.aueb.gr"
+switch3 = "planetlab1.informatik.uni-erlangen.de"
 host1 = "planetlab2.ionio.gr"
 host2 = "iraplab2.iralab.uni-karlsruhe.de"
 host3 = "planetlab2.diku.dk"
@@ -124,15 +124,15 @@ ovs2 = add_ovs(ec, "nepi_bridge_2", "192.168.3.4/24", ip_controller, "6633", s2_
 ovs3 = add_ovs(ec, "nepi_bridge_3", "192.168.3.6/24", ip_controller, "6633", s3_node)
 
 # Add ports on ovs
-port1 = add_port(ec, "nepi_port1", ovs1)
-port4 = add_port(ec, "nepi_port4", ovs1)
-port7 = add_port(ec, "nepi_port7", ovs1)
-port2 = add_port(ec, "nepi_port2", ovs2)
-port5 = add_port(ec, "nepi_port5", ovs2)
-port8 = add_port(ec, "nepi_port8", ovs2)
-port3 = add_port(ec, "nepi_port3", ovs3)
-port6 = add_port(ec, "nepi_port6", ovs3)
-port9 = add_port(ec, "nepi_port9", ovs3)
+port1 = add_port(ec, "nepi_port1", network, ovs1)
+port4 = add_port(ec, "nepi_port4", network, ovs1)
+port7 = add_port(ec, "nepi_port7", network, ovs1)
+port2 = add_port(ec, "nepi_port2", network, ovs2)
+port5 = add_port(ec, "nepi_port5", network, ovs2)
+port8 = add_port(ec, "nepi_port8", network, ovs2)
+port3 = add_port(ec, "nepi_port3", network, ovs3)
+port6 = add_port(ec, "nepi_port6", network, ovs3)
+port9 = add_port(ec, "nepi_port9", network, ovs3)
 
 h1_node = add_node(ec, host1, slicename, pl_user, pl_password)
 h2_node = add_node(ec, host2, slicename, pl_user, pl_password)
@@ -144,12 +144,12 @@ tap2 = add_tap(ec, "192.168.3.3", 24, "192.168.3.4", h2_node)
 tap3 = add_tap(ec, "192.168.3.5", 24, "192.168.3.6", h3_node)
 
 # Connect the nodes
-tunnel1 = add_tunnel(ec, network, port1, tap1)
-tunnel2 = add_tunnel(ec, network, port2, tap2)
-tunnel3 = add_tunnel(ec, network, port3, tap3)
-tunnel4 = add_tunnel(ec, network, port4, port5)
-tunnel5 = add_tunnel(ec, network, port7, port6)
-tunnel6 = add_tunnel(ec, network, port8, port9)
+tunnel1 = add_tunnel(ec, port1, tap1)
+tunnel2 = add_tunnel(ec, port2, tap2)
+tunnel3 = add_tunnel(ec, port3, tap3)
+tunnel4 = add_tunnel(ec, port4, port5)
+tunnel5 = add_tunnel(ec, port7, port6)
+tunnel6 = add_tunnel(ec, port8, port9)
 
 # Add ping commands
 app1 = add_app(ec, "ping -c5 192.168.3.4", s1_node)
index 91640df..b93ee80 100644 (file)
@@ -283,7 +283,12 @@ class LinuxTap(LinuxApplication):
         
         return True
 
-    ## XXX: NOT REALLY WORKING YET!
+    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(
@@ -291,14 +296,14 @@ class LinuxTap(LinuxApplication):
                 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
-        (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 "
@@ -308,19 +313,21 @@ class LinuxTap(LinuxApplication):
             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 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
 
-        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):
@@ -335,13 +342,13 @@ class LinuxTap(LinuxApplication):
 
         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")
 
-        remote_port_file = os.path.join(connection_run_home, 
+        remote_port_file = os.path.join(self.run_home, 
                 "remote_port")
 
-        ret_file = os.path.join(connection_run_home, 
+        ret_file = os.path.join(self.run_home, 
                 "ret_file")
 
         # Generate UDP connect command
@@ -397,6 +404,65 @@ class LinuxTap(LinuxApplication):
 
         return command
 
+    def establish_udp_connection(self, remote_endpoint, 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
+
     @property
     def _start_command(self):
         command = []
index 8c7402a..8e0760d 100644 (file)
@@ -86,6 +86,7 @@ class LinuxTunnel(LinuxApplication):
         self.endpoint1.node.mkdir(self.run_home(self.endpoint1))
         self.endpoint2.node.mkdir(self.run_home(self.endpoint2))
 
+        self.debug("Initiate the connection")
         # Start 2 step connection
         # Initiate connection from endpoint 1 to endpoint 2
         data1 = self.initiate_connection(self.endpoint1, self.endpoint2)
@@ -93,12 +94,14 @@ class LinuxTunnel(LinuxApplication):
         # Initiate connection from endpoint 2 to endpoint 1
         data2 = self.initiate_connection(self.endpoint2, self.endpoint1)
 
+        self.debug("Establish the connection")
         # Establish connection from endpoint 1 to endpoint 2
         self.establish_connection(self.endpoint1, self.endpoint2, data2)
         
         # Establish connection from endpoint 2 to endpoint 1
         self.establish_connection(self.endpoint2, self.endpoint1, data1)
 
+        self.debug("Verify the connection")
         # check if connection was successful on both sides
         self.verify_connection(self.endpoint1, self.endpoint2)
         self.verify_connection(self.endpoint2, self.endpoint1)
@@ -131,6 +134,7 @@ class LinuxTunnel(LinuxApplication):
     def do_stop(self):
         """ Stops application execution
         """
+
         if self.state == ResourceState.STARTED:
             self.info("Stopping tunnel")
 
index 63ae086..1643b90 100644 (file)
@@ -84,7 +84,7 @@ class LinuxUdpTunnel(LinuxTunnel):
         connected = []
         for guid in self.connections:
             rm = self.ec.get_resource(guid)
-            if hasattr(rm, "udp_connect"):
+            if hasattr(rm, "initiate_udp_connection"):
                 connected.append(rm)
         return connected
 
@@ -93,51 +93,33 @@ class LinuxUdpTunnel(LinuxTunnel):
         cipher_key = self.get("cipherKey")
         bwlimit = self.get("bwLimit")
         txqueuelen = self.get("txQueueLen")
-       
-        # Return the command to execute to initiate the connection to the
-        # other endpoint
         connection_app_home = self.app_home(endpoint)
         connection_run_home = self.run_home(endpoint)
-        pid, ppid = endpoint.udp_connect(
+
+        port = endpoint.initiate_udp_connection(
                 remote_endpoint, 
                 connection_app_home,
                 connection_run_home, 
                 cipher, cipher_key, bwlimit, txqueuelen)
 
-        port = self.wait_local_port(endpoint)
-
-        self._pids[endpoint] = (pid, ppid)
-
         return port
 
     def establish_connection(self, endpoint, remote_endpoint, port):
-        self.upload_remote_port(endpoint, port)
+        endpoint.establish_udp_connection(remote_endpoint, port)
 
     def verify_connection(self, endpoint, remote_endpoint):
-        self.wait_result(endpoint)
+        endpoint.verify_connection()
 
     def terminate_connection(self, endpoint, remote_endpoint):
-        pid, ppid = self._pids[endpoint]
-
-        if pid and ppid:
-            (out, err), proc = endpoint.node.kill(pid, ppid, 
-                    sudo = True) 
-
-            # check if execution errors occurred
-            if proc.poll() and err:
-                msg = " Failed to STOP tunnel"
-                self.error(msg, out, err)
-                raise RuntimeError, msg
+        endpoint.terminate_connection()
 
     def check_state_connection(self):
         # Make sure the process is still running in background
         # No execution errors occurred. Make sure the background
         # process with the recorded pid is still running.
-        pid1, ppid1 = self._pids[self.endpoint1]
-        pid2, ppid2 = self._pids[self.endpoint2]
 
-        status1 = self.endpoint1.node.status(pid1, ppid1)
-        status2 = self.endpoint2.node.status(pid2, ppid2)
+        status1 = self.endpoint1.check_status()
+        status2 = self.endpoint2.check_status()
 
         if status1 == ProcStatus.FINISHED and \
                 status2 == ProcStatus.FINISHED:
@@ -191,11 +173,3 @@ class LinuxUdpTunnel(LinuxTunnel):
 
         return result
 
-    def upload_remote_port(self, endpoint, port):
-        # upload remote port number to file
-        port = "%s\n" % port
-        endpoint.node.upload(port,
-                os.path.join(self.run_home(endpoint), "remote_port"),
-                text = True, 
-                overwrite = False)
-
index 3594a8c..fb921e9 100644 (file)
@@ -297,11 +297,12 @@ class OVSSwitch(LinuxApplication):
         """
 
         from nepi.resources.planetlab.openvswitch.ovsport import OVSPort
-        rm = self.get_connected(OVSPort.get_rtype())
+        rms = self.get_connected(OVSPort.get_rtype())
 
-        if rm[0].state < ResourceState.RELEASED:
-            self.ec.schedule(reschedule_delay, self.release)
-            return 
+        for rm in rms :
+            if rm.state < ResourceState.RELEASED:
+                self.ec.schedule(reschedule_delay, self.release)
+                return 
             
         cmd = "sliver-ovs del-bridge %s" % self.get('bridge_name')
         (out, err), proc = self.node.run(cmd, self.ovs_checks,
index 6571358..8275249 100644 (file)
@@ -26,6 +26,8 @@ from nepi.resources.planetlab.openvswitch.ovs import OVSSwitch
 from nepi.resources.planetlab.node import PlanetlabNode        
 from nepi.resources.linux.application import LinuxApplication
 
+import os
+
 reschedule_delay = "0.5s"
 
 @clsinit_copy                 
@@ -44,7 +46,7 @@ class OVSPort(LinuxApplication):
     _help = "Runs an OpenVSwitch on a PlanetLab host"
     _backend = "planetlab"
 
-    _authorized_connections = ["OVSSwitch", "OVSTunnel"]      
+    _authorized_connections = ["OVSSwitch", "LinuxUdpTunnel", "LinuxTunnel"]      
 
     @classmethod
     def _register_attributes(cls):
@@ -53,8 +55,16 @@ class OVSPort(LinuxApplication):
         """
         port_name = Attribute("port_name", "Name of the port",
             flags = Flags.Design)                      
+        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)
+        network = Attribute("network", "Network used by the port",
+            flags = Flags.Design)      
 
         cls._register_attribute(port_name)
+        cls._register_attribute(endpoint_ip)
+        cls._register_attribute(network)
 
     def __init__(self, ec, guid):
         """
@@ -65,8 +75,11 @@ class OVSPort(LinuxApplication):
     
         """
         super(OVSPort, self).__init__(ec, guid)
+
+
         self._port_number = None
-        self.port_info = []         
+        # in case of connection by tunnel       
+        self._remote_ip = None    
 
     def log_message(self, msg):
         return " guid %d - OVSPort - %s " % (self.guid, msg)
@@ -90,6 +103,10 @@ class OVSPort(LinuxApplication):
         if ovsswitch: return ovsswitch[0]
         return None
         
+    @property
+    def remote_ip(self):
+        return self._remote_ip
+
     @property
     def port_number(self):
         return self._port_number
@@ -136,12 +153,15 @@ class OVSPort(LinuxApplication):
         self.info("Created the port %s on switch %s" % (self.get('port_name'),
                                              self.ovsswitch.get('bridge_name')))     
            
-    def get_local_end(self):
+    def initiate_udp_connection(self, remote_endpoint, connection_app_home, 
+            connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
         """ Get the local_endpoint of the port
         """
 
+        self._remote_ip = remote_endpoint.node.get("ip")
+
         msg = "Discovering the number of the port %s" % self.get('port_name')
-        self.debug(msg)
+        self.info(msg)
 
         command = "sliver-ovs get-local-endpoint %s" % self.get('port_name')
         out = err = ""
@@ -164,39 +184,88 @@ class OVSPort(LinuxApplication):
 
         self.info("The number of the %s is %s" % (self.get('port_name'), 
            self.port_number))
-   
-    def set_port_info(self):
-        """ Set all the information about the port inside a list
-        """
 
-        info = []
-        info.append(self.node.get('hostname'))
+        if remote_endpoint.is_rm_instance("PlanetlabTap"):
+            self._vroute = self.ec.register_resource("PlanetlabVroute")
+            self.ec.set(self._vroute, "action", "add")
+            self.ec.set(self._vroute, "network", self.get("network"))
+
+            print "Vroute Guid :" + str(self._vroute)
+
+            self.ec.register_connection(self._vroute, remote_endpoint.guid)
+            self.ec.deploy(guids=[self._vroute], group = self.deployment_group)
+
+            # For debugging
+            msg = "Route for the tap configured"
+            self.debug(msg)
+
+        return self.port_number
+
 
-        #Return the ip of the node
-        import socket
-        ip = socket.gethostbyname(self.node.get('hostname'))
-        info.append(ip)
+    def establish_udp_connection(self,remote_endpoint, port):
+        establish_connection_command = self._establish_connection_command(port)
 
-        info.append(self.get('port_name'))
-        info.append(self.ovsswitch.get('virtual_ip_pref'))
-        info.append(self.port_number)
-        return info
+        # upload command to connect.sh script
+        shfile = os.path.join(self.app_home, "sw-connect.sh")
+        self.node.upload_command(establish_connection_command,
+                shfile = shfile,
+                overwrite = False)
 
-    def switch_connect_command(self, local_port_name, 
-            remote_ip, remote_port_num):
+        # invoke connect script
+        cmd = "bash %s" % shfile
+        (out, err), proc = self.node.run(cmd, self.run_home,
+                sudo  = True,
+                stdout = "sw_stdout",
+                stderr = "sw_stderr") 
+             
+        # 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
+        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 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
+
+        # For debugging
+        msg = "Connection on port configured"
+        self.debug(msg)
+
+
+    def _establish_connection_command(self, port):
         """ Script to create the connection from a switch to a 
              remote endpoint
         """
+        local_port_name = self.get('port_name')
 
         command = ["sliver-ovs"]
         command.append("set-remote-endpoint ")
         command.append("%s " % local_port_name)
-        command.append("%s " % remote_ip)
-        command.append("%s " % remote_port_num)
+        command.append("%s " % self.remote_ip)
+        command.append("%s " % port)
         command = " ".join(command)
         command = self.replace_paths(command)
         return command
         
+    def verify_connection(self):
+        self.ovsswitch.ovs_status()
+
+    def terminate_connection(self):
+        return True
+
+    def check_status(self):
+        return self.node.status(self._pid, self._ppid)
+
     def do_deploy(self):
         """ Deploy the OVS port after the OVS Switch
         """
@@ -210,25 +279,22 @@ class OVSPort(LinuxApplication):
         self.do_provision()
 
         self.create_port()
-        self.get_local_end()
+        end_ip = self.ovsswitch.get('virtual_ip_pref').split('/')
+        self.set("endpoint_ip", end_ip[0])
 
         #Check the status of the OVS Switch
         self.ovsswitch.ovs_status()
 
-        # Save all the information inside a list
-        self.port_info = self.set_port_info()
-
         super(OVSPort, self).do_deploy()
 
     def do_release(self):
         """ Delete the port on the OVSwitch. It needs to wait for the tunnel
         to be released.
         """
+        from nepi.resources.linux.udptunnel import LinuxUdpTunnel
+        rm = self.get_connected(LinuxUdpTunnel.get_rtype())
 
-        from nepi.resources.planetlab.openvswitch.tunnel import OVSTunnel
-        rm = self.get_connected(OVSTunnel.get_rtype())
-
-        if rm and rm[0].state < ResourceState.RELEASED:
+        if rm and rm[0].state < ResourceState.STOPPED:
             self.ec.schedule(reschedule_delay, self.release)
             return 
             
diff --git a/src/nepi/resources/planetlab/openvswitch/tunnel.py b/src/nepi/resources/planetlab/openvswitch/tunnel.py
deleted file mode 100644 (file)
index 682d796..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-#
-#    NEPI, a framework to manage network experiments
-#    Copyright (C) 2013 INRIA
-#
-#    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    This program is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU General Public License for more details.
-#
-#    You should have received a copy of the GNU General Public License
-#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Authors: Alina Quereilhac <alina.quereilhac@inria.fr>
-#         Alexandros Kouvakas <alexandros.kouvakas@inria.fr>
-#         Julien Tribino <julien.tribino@inria.fr>
-
-
-from nepi.execution.attribute import Attribute, Flags, Types
-from nepi.execution.resource import ResourceManager, ResourceFactory, clsinit_copy, \
-        ResourceState
-from nepi.resources.linux.application import LinuxApplication
-from nepi.resources.planetlab.node import PlanetlabNode            
-from nepi.resources.planetlab.openvswitch.ovs import OVSSwitch   
-from nepi.util.timefuncs import tnow, tdiffsec    
-from nepi.resources.planetlab.vroute import PlanetlabVroute
-from nepi.resources.planetlab.tap import PlanetlabTap
-
-import os
-import time
-import socket
-
-reschedule_delay = "0.5s"
-
-@clsinit_copy                 
-class OVSTunnel(LinuxApplication):
-    """
-    .. class:: Class Args :
-      
-        :param ec: The Experiment controller
-        :type ec: ExperimentController
-        :param guid: guid of the RM
-        :type guid: int
-        :param creds: Credentials to communicate with the rm 
-        :type creds: dict
-
-    """
-    
-    _rtype = "OVSTunnel"
-    _authorized_connections = ["OVSPort", "PlanetlabTap"]    
-
-    @classmethod
-    def _register_attributes(cls):
-        """ Register the attributes of OVSTunnel RM 
-
-        """
-        network = Attribute("network", "IPv4 Network Address",
-               flags = Flags.Design)
-
-        cipher = Attribute("cipher",
-               "Cipher to encript communication. "
-                "One of PLAIN, AES, Blowfish, DES, DES3. ",
-                default = None,
-                allowed = ["PLAIN", "AES", "Blowfish", "DES", "DES3"],
-                type = Types.Enumerate, 
-                flags = Flags.Design)
-
-        cipher_key = Attribute("cipherKey",
-                "Specify a symmetric encryption key with which to protect "
-                "packets across the tunnel. python-crypto must be installed "
-                "on the system." ,
-                flags = Flags.Design)
-
-        txqueuelen = Attribute("txQueueLen",
-                "Specifies the interface's transmission queue length. "
-                "Defaults to 1000. ", 
-                type = Types.Integer, 
-                flags = Flags.Design)
-
-        bwlimit = Attribute("bwLimit",
-                "Specifies the interface's emulated bandwidth in bytes "
-                "per second.",
-                type = Types.Integer, 
-                flags = Flags.Design)
-
-        cls._register_attribute(network)
-        cls._register_attribute(cipher)
-        cls._register_attribute(cipher_key)
-        cls._register_attribute(txqueuelen)
-        cls._register_attribute(bwlimit)
-
-    def __init__(self, ec, guid):
-        """
-        :param ec: The Experiment controller
-        :type ec: ExperimentController
-        :param guid: guid of the RM
-        :type guid: int
-    
-        """
-        super(OVSTunnel, self).__init__(ec, guid)
-        self._home = "tunnel-%s" % self.guid
-        self.port_info_tunl = []
-        self._pid = None
-        self._ppid = None
-        self._vroute = None
-        self._node_endpoint1 = None
-        self._node_endpoint2 = None
-
-    def log_message(self, msg):
-        return " guid %d - Tunnel - %s " % (self.guid, msg)
-
-    def app_home(self, node):
-        return os.path.join(node.exp_home, self._home)
-
-    def run_home(self, node):
-        return os.path.join(self.app_home(node), self.ec.run_id)
-
-    @property
-    def tap(self):
-        """ Return the Tap RM if it exists """
-        rclass = ResourceFactory.get_resource_type(PlanetlabTap.get_rtype())
-        for guid in self.connections:
-            rm = self.ec.get_resource(guid)
-            if isinstance(rm, rclass):
-                return rm
-
-    @property
-    def ovsswitch(self):
-        """ Return the 1st switch """
-        for guid in self.connections:
-            rm_port = self.ec.get_resource(guid)
-            if hasattr(rm_port, "create_port"):
-                rm_list = rm_port.get_connected(OVSSwitch.get_rtype())
-                if rm_list:
-                    return rm_list[0]
-
-    @property         
-    def check_switch_host_link(self):
-        """ Check if the links are between switches
-            or switch-host. Return False for the latter.
-        """
-        if self.tap :
-            return True
-        return False
-
-
-    def endpoints(self):
-        """ Return the list with the two connected elements.
-        Either Switch-Switch or Switch-Host
-        """
-        connected = [1, 1]
-        position = 0
-        for guid in self.connections:
-            rm = self.ec.get_resource(guid)
-            if hasattr(rm, "create_port"):
-                connected[position] = rm
-                position += 1
-            elif hasattr(rm, "udp_connect"):
-                connected[1] = rm
-        return connected
-
-    def get_node(self, endpoint):
-        """ Get the nodes of the endpoint
-        """
-        rm = []
-        if hasattr(endpoint, "create_port"):
-            rm_list = endpoint.get_connected(OVSSwitch.get_rtype())
-            if rm_list:
-                rm = rm_list[0].get_connected(PlanetlabNode.get_rtype())
-        else:
-            rm = endpoint.get_connected(PlanetlabNode.get_rtype())
-
-        if rm :
-            return rm[0]
-
-    @property
-    def endpoint1(self):
-        """ Return the first endpoint : Always a Switch
-        """
-        endpoint = self.endpoints()
-        return endpoint[0]
-
-    @property
-    def endpoint2(self):
-        """ Return the second endpoint : Either a Switch or a TAP
-        """
-        endpoint = self.endpoints()
-        return endpoint[1]
-
-    def get_port_info(self, endpoint1, endpoint2):
-        #TODO : Need to change it. Really bad to have method that return different type of things !!!!!
-        """ Retrieve the port_info list for each port
-       
-        """
-        if self.check_switch_host_link :
-            host0, ip0, pname0, virt_ip0, pnumber0 = endpoint1.port_info
-            return pnumber0
-
-        host0, ip0, pname0, virt_ip0, pnumber0 = endpoint1.port_info
-        host1, ip1, pname1, virt_ip1, pnumber1 = endpoint2.port_info
-
-        return pname0, ip1, pnumber1
-    
-    def wait_local_port(self, node_endpoint):
-        """ Waits until the if_name file for the command is generated, 
-            and returns the if_name for the device """
-
-        local_port = None
-        delay = 1.0
-
-        #TODO : Need to change it with reschedule to avoid the problem 
-        #        of the order of connection
-        for i in xrange(10):
-            (out, err), proc = node_endpoint.check_output(self.run_home(node_endpoint), 'local_port')
-            if out:
-                local_port = int(out)
-                break
-            else:
-                time.sleep(delay)
-                delay = delay * 1.5
-        else:
-            msg = "Couldn't retrieve local_port"
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-
-        return local_port
-
-    def connection(self, local_endpoint, rm_endpoint):
-        """ Create the connect command for each case : 
-              - Host - Switch,  
-              - Switch - Switch,  
-              - Switch - Host
-        """
-        local_node = self.get_node(local_endpoint)
-        local_node.mkdir(self.run_home(local_node))
-
-        rm_node = self.get_node(rm_endpoint)
-        rm_node.mkdir(self.run_home(rm_node))
-
-        # Host to switch
-        if self.check_switch_host_link and local_endpoint == self.endpoint2 :
-        # Collect info from rem_endpoint
-            remote_ip = socket.gethostbyname(rm_node.get("hostname"))
-
-        # Collect info from endpoint
-            connection_run_home = self.run_home(local_node)
-            connection_app_home = self.app_home(local_node)
-            cipher = self.get("cipher")
-            cipher_key = self.get("cipherKey")
-            bwlimit = self.get("bwLimit")
-            txqueuelen = self.get("txQueueLen")
-
-           
-        # Upload the remote port in a file
-            rem_port = str(self.get_port_info(rm_endpoint,local_endpoint))
-            rem_port_file = os.path.join(self.run_home(local_node), "remote_port")
-            local_node.upload(rem_port, rem_port_file,
-                 text = True,
-                 overwrite = False)
-       
-            self._pid, self._ppid = local_endpoint.udp_connect(
-                 rm_node, connection_run_home, connection_app_home,
-                 cipher, cipher_key, bwlimit, txqueuelen) 
-
-
-#            connect_command = local_endpoint.udp_connect_command(
-#                 remote_ip, local_port_file, rem_port_file,
-#                 ret_file, cipher, cipher_key, bwlimit, txqueuelen) 
-
-#            self.connection_command(connect_command, local_node, rm_node)
-
-#        # Wait for pid file to be generated
-#            self._pid, self._ppid = local_node.wait_pid(self.run_home(local_node))
-
-            if not self._pid or not self._ppid:
-                (out, err), proc = local_node.check_errors(self.run_home(local_node))
-                # Out is what was written in the stderr file
-                if err:
-                    msg = " Failed to start connection of the OVS Tunnel "
-                    self.error(msg, out, err)
-                    raise RuntimeError, msg
-            return
-
-        # Switch to Host
-        if self.check_switch_host_link and local_endpoint == self.endpoint1:
-            local_port_name = local_endpoint.get('port_name')
-            remote_port_num = self.wait_local_port(rm_node)
-            remote_ip = socket.gethostbyname(rm_node.get("hostname"))
-  
-        # Switch to Switch
-        if not self.check_switch_host_link :
-            local_port_name, remote_ip, remote_port_num = self.get_port_info(local_endpoint, rm_endpoint)
-
-        connect_command = local_endpoint.switch_connect_command(
-                    local_port_name, remote_ip, remote_port_num)
-
-        self.connection_command(connect_command, local_node, rm_node)       
-
-    def connection_command(self, command, node_endpoint, rm_node_endpoint):
-        """ Execute the connection command on the node and check if the processus is
-            correctly running on the node.
-        """
-        shfile = os.path.join(self.app_home(node_endpoint), "sw_connect.sh")
-        node_endpoint.upload(command,
-                shfile,
-                text = True,
-                overwrite = False)
-
-        # Invoke connect script
-        out = err= ''       
-        cmd = "bash %s" % shfile
-        (out, err), proc = node_endpoint.run(cmd, self.run_home(node_endpoint),
-                sudo  = True,
-                stdout = "sw_stdout",
-                stderr = "sw_stderr")
-        
-        # Check if execution errors occured
-
-        if proc.poll():
-            msg = "Failed to connect endpoints"
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-
-        # For debugging
-        msg = "Connection on port configured"
-        self.debug(msg)
-
-    def do_provision(self):
-        """ Provision the tunnel
-        """
-        
-        #TODO : The order of the connection is important for now ! 
-        # Need to change the code of wait local port
-        self.connection(self.endpoint2, self.endpoint1)
-        self.connection(self.endpoint1, self.endpoint2)
-
-    def configure_route(self):
-        """ Configure the route for the tap device
-
-            .. note : In case of a conection between a switch and a host, a route
-                      was missing on the node with the Tap Device. This method create
-                      the missing route. 
-        """
-
-        if  self.check_switch_host_link:
-            self._vroute = self.ec.register_resource("PlanetlabVroute")
-            self.ec.set(self._vroute, "action", "add")
-            self.ec.set(self._vroute, "network", self.get("network"))
-
-            self.ec.register_connection(self._vroute, self.tap.guid)
-            self.ec.deploy(guids=[self._vroute], group = self.deployment_group)
-
-    def do_deploy(self):
-        """ Deploy the tunnel after the endpoint get ready
-        """
-        if (not self.endpoint1 or self.endpoint1.state < ResourceState.READY) or \
-            (not self.endpoint2 or self.endpoint2.state < ResourceState.READY):
-            self.ec.schedule(reschedule_delay, self.deploy)
-            return
-
-        self.do_discover()
-        self.do_provision()
-        self.configure_route()
-
-        # Cannot call the deploy of the linux application 
-        #         because of a log error.
-        # Need to investigate if it is right that the tunnel 
-        #    inherits from the linux application
-        #  super(OVSTunnel, self).do_deploy()
-        self.set_ready()
-    def do_release(self):
-        """ Release the tunnel by releasing the Tap Device if exists
-        """
-        if self.check_switch_host_link:
-            # TODO: Make more generic Release method of PLTAP
-            tap_node = self.get_node(self.endpoint2)
-            if self._pid and self._ppid:
-                (out, err), proc = tap_node.kill(self._pid,
-                        self._ppid, sudo = True)
-
-                if err or proc.poll():
-                    msg = " Failed to delete TAP device"
-                    self.error(msg, out, err)
-
-        super(OVSTunnel, self).do_release()
-
index 5a47663..4df138b 100644 (file)
@@ -343,6 +343,14 @@ class PlanetlabTap(LinuxApplication):
 
         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(
@@ -350,14 +358,14 @@ class PlanetlabTap(LinuxApplication):
                 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
-        (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 "
@@ -367,19 +375,21 @@ class PlanetlabTap(LinuxApplication):
             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 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
 
-        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):
@@ -389,13 +399,13 @@ class PlanetlabTap(LinuxApplication):
 
         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")
 
-        remote_port_file = os.path.join(connection_run_home, 
+        remote_port_file = os.path.join(self.run_home, 
                 "remote_port")
 
-        ret_file = os.path.join(connection_run_home, 
+        ret_file = os.path.join(self.run_home, 
                 "ret_file")
 
         # Generate UDP connect command
@@ -432,6 +442,67 @@ class PlanetlabTap(LinuxApplication):
 
         return command
 
+    def establish_udp_connection(self, remote_endpoint, 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): 
         # Set the remote endpoint
         self.set("pointopoint", remote_endpoint.get("endpoint_ip"))
@@ -456,6 +527,7 @@ class PlanetlabTap(LinuxApplication):
 
         return command
 
+
     @property
     def _start_command(self):
         if self.gre_enabled:
index fa93c3c..24ddf14 100755 (executable)
@@ -144,11 +144,11 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
 
         ec.shutdown()
 
-    def ztest_tap_udp_tunnel(self):
+    def test_tap_udp_tunnel(self):
         self.t_tap_udp_tunnel(self.user1, self.host1, self.identity,
                 self.user2, self.host2, self.identity)
 
-    def test_tun_udp_tunnel(self):
+    def ztest_tun_udp_tunnel(self):
         self.t_tun_udp_tunnel(self.user1, self.host1, self.identity,
                 self.user2, self.host2, self.identity)
 
index 1254d19..e54c3ef 100755 (executable)
@@ -34,7 +34,8 @@ class PlanetlabUdpTunnelTestCase(unittest.TestCase):
         self.host1 = "planetlab1.informatik.uni-erlangen.de"
         self.host2 = "planck227ple.test.ibbt.be"
         self.user = "inria_nepi"
-        self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
+        #self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
+        self.identity = "%s/.ssh/id_rsa" % (os.environ['HOME'])
         #self.netblock = "192.168.1"
         self.netblock = "192.168.3"