Adding PlanetLabGRETunnel
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 29 Jul 2014 13:53:39 +0000 (15:53 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 29 Jul 2014 13:53:39 +0000 (15:53 +0200)
src/nepi/resources/linux/gretunnel.py
src/nepi/resources/planetlab/scripts/pl-vif-create.py
src/nepi/resources/planetlab/scripts/pl-vif-down.py
src/nepi/resources/planetlab/scripts/pl-vif-up.py
src/nepi/resources/planetlab/tap.py
test/resources/planetlab/gretunnel.py [changed mode: 0644->0755]
test/resources/planetlab/ovs.py [changed mode: 0644->0755]

index 2d866c2..62f94cf 100644 (file)
@@ -24,9 +24,10 @@ from nepi.resources.linux.tunnel import LinuxTunnel
 from nepi.util.sshfuncs import ProcStatus
 from nepi.util.timefuncs import tnow, tdiffsec
 
-import os
+import re
 import socket
 import time
+import os
 
 @clsinit_copy
 class LinuxGRETunnel(LinuxTunnel):
@@ -59,7 +60,7 @@ class LinuxGRETunnel(LinuxTunnel):
 
         # upload command to connect.sh script
         shfile = os.path.join(self.app_home(endpoint), "gre-connect.sh")
-        endpoint.node.upload(udp_connect_command,
+        endpoint.node.upload(gre_connect_command,
                 shfile,
                 text = True, 
                 overwrite = False)
@@ -71,7 +72,7 @@ class LinuxGRETunnel(LinuxTunnel):
         # check if execution errors occurred
         msg = " Failed to connect endpoints "
         
-        if proc.poll():
+        if proc.poll() or err:
             self.error(msg, out, err)
             raise RuntimeError, msg
     
@@ -87,6 +88,12 @@ class LinuxGRETunnel(LinuxTunnel):
                 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
+        # will write the name of the TAP to a file. We wait until
+        # we can read the interface name from the file.
+        vif_name = endpoint.wait_vif_name()
+        endpoint.set("deviceName", vif_name) 
 
         # Wait if name
         return True
@@ -95,14 +102,23 @@ class LinuxGRETunnel(LinuxTunnel):
         pass
 
     def verify_connection(self, endpoint, remote_endpoint):
-        # Execute a ping from both sides to verify that the tunnel works
-        pass
+        remote_ip = socket.gethostbyname(remote_endpoint.node.get("hostname"))
+
+        command = "ping -c 4 %s" % remote_ip
+        (out, err), proc = endpoint.node.execute(command,
+                blocking = True)
+
+        m = re.search("(\d+)% packet loss", str(out))
+        if not m or int(m.groups()[0]) == 100:
+             msg = " Erroro establishing GRE Tunnel"
+             self.error(msg, out, err)
+             raise RuntimeError, msg
 
     def terminate_connection(self, endpoint, remote_endpoint):
         pass
 
-    def check_state_connection(self, endpoint, remote_endpoint):
-        raise NotImplementedError
+    def check_state_connection(self):
+        pass
 
     def valid_connection(self, guid):
         # TODO: Validate!
index 89d86c7..a3ddecb 100644 (file)
@@ -122,7 +122,7 @@ def get_options():
 
     parser.add_option("-S", "--socket-name", dest="socket_name",
         help = "Name for the unix socket used to interact with this process", 
-        default = "tap.sock", type="str")
+        type="str")
 
     (options, args) = parser.parse_args()
     
index 0047be4..9188bbb 100644 (file)
@@ -26,16 +26,25 @@ from optparse import OptionParser
 STOP_MSG = "STOP"
 
 def get_options():
-    usage = ("usage: %prog -N <vif-name> -D <delete> -S <socket-name>")
+    usage = ("usage: %prog -u <slicename> -N <vif-name> -t <vif-type> "
+            "-D <delete> -S <socket-name>")
     
     parser = OptionParser(usage = usage)
 
+    parser.add_option("-u", "--slicename", dest="slicename",
+        help = "The name of the PlanetLab slice ",
+        type="str")
+
     parser.add_option("-N", "--vif-name", dest="vif_name",
         help = "The name of the virtual interface, or a "
                 "unique numeric identifier to name the interface "
                 "if GRE mode is used.",
         type="str")
 
+    parser.add_option("-t", "--vif-type", dest="vif_type",
+            help = "Virtual interface type. Either IFF_TAP or IFF_TUN. "
+            "Defaults to IFF_TAP. ", type="str")
+
     parser.add_option("-D", "--delete", dest="delete", 
             action="store_true", 
             default = False,
@@ -43,15 +52,20 @@ def get_options():
 
     parser.add_option("-S", "--socket-name", dest="socket_name",
         help = "Name for the unix socket used to interact with this process", 
-        default = "tap.sock", type="str")
+        type="str")
 
     (options, args) = parser.parse_args()
-    
-    return (options.vif_name, options.delete, options.socket_name)
+   
+    vif_type = vsys.IFF_TAP
+    if options.vif_type and options.vif_type == "IFF_TUN":
+        vif_type = vsys.IFF_TUN
+
+    return (options.socket_name, options.vif_name, options.slicename, 
+            options.vif_type, options.delete)
 
 if __name__ == '__main__':
 
-    (vif_name, delete, socket_name) = get_options()
+    (socket_name, vif_name, slicename, vif_type, delete) = get_options()
 
     # If a socket name is sent, send the STOP message and wait for a reply
     if socket_name:
@@ -63,8 +77,25 @@ if __name__ == '__main__':
         reply = base64.b64decode(reply)
         print reply
 
+    # If a slicename is provided, use it to remove a GRE device
+    elif slicename:
+        import pwd
+        import getpass
+
+        sliceid = pwd.getpwnam(slicename).pw_uid
+
+        if vif_type == vsys.IFF_TAP:
+            vif_prefix = "tap"
+        else:
+            vif_prefix = "tun"
+
+        # if_name should be a unique numeric vif id
+        vif_name = "%s%s-%s" % (vif_prefix, sliceid, vif_name) 
+
+        vsys.vif_down(vif_name, delete = True)
+
     # Else, use the vsys interface to set the virtual interface down
-    elif vif_name:
-        vsys.vif_down(vif_name, delete = delete)
+    else:
+        vsys.vif_down(vif_name)
 
 
index 609f2d1..d37a4ee 100644 (file)
@@ -22,12 +22,16 @@ import vsys
 from optparse import OptionParser
 
 def get_options():
-    usage = ("usage: %prog -N <vif-name> -t <vif-type> -a <ip4-address> "
-                    "-n <net-prefix> -s <snat> -p <pointopoint> -q <txqueuelen> "
+    usage = ("usage: %prog -u <slicename> -N <vif-name> -t <vif-type> -a <ip4-address> "
+                    "-n <net-prefix> -S <snat> -p <pointopoint> -q <txqueuelen> "
                     "-g <gre_key> -G <gre_remote> -f <vif-name-file> ")
  
     parser = OptionParser(usage = usage)
 
+    parser.add_option("-u", "--slicename", dest="slicename",
+        help = "The name of the PlanetLab slice ",
+        type="str")
+
     parser.add_option("-N", "--vif-name", dest="vif_name",
         help = "The name of the virtual interface, or a "
                 "unique numeric identifier to name the interface "
@@ -83,21 +87,20 @@ def get_options():
     if options.vif_type and options.vif_type == "IFF_TUN":
         vif_type = vsys.IFF_TUN
 
-    return (options.vif_name, vif_type, options.ip4_address, 
+    return (options.slicename, options.vif_name, vif_type, options.ip4_address, 
             options.net_prefix, options.snat, options.pointopoint, 
             options.txqueuelen, options.gre_key, options.gre_remote,
             options.vif_name_file)
 
 if __name__ == '__main__':
 
-    (vif_name, vif_type, ip4_address, net_prefix, snat, pointopoint,
+    (slicename, vif_name, vif_type, ip4_address, net_prefix, snat, pointopoint,
         txqueuelen, gre_key, gre_remote, vif_name_file) = get_options()
 
     if (gre_key):
         import pwd
         import getpass
 
-        slicename = getpass.getuser()
         sliceid = pwd.getpwnam(slicename).pw_uid
 
         if vif_type == vsys.IFF_TAP:
@@ -106,12 +109,22 @@ if __name__ == '__main__':
             vif_prefix = "tun"
 
         # if_name should be a unique numeric vif id
-        vif_name = "%s%s-%d" % (vif_prefix, sliceid, vif_name) 
+        vif_name = "%s%s-%s" % (vif_prefix, sliceid, vif_name) 
 
-    vsys.vif_up(vif_name, ip4_address, net_prefix, snat = snat, 
+    try:
+        vsys.vif_up(vif_name, ip4_address, net_prefix, snat = snat, 
             pointopoint = pointopoint, txqueuelen = txqueuelen, 
             gre_key = gre_key, gre_remote = gre_remote)
 
+    except RuntimeError as e:
+        import sys
+        import traceback
+        traceback.print_exc(file=sys.stderr)
+
+        # Ignore warnings
+        if e.message.find("WARNING:") < 0:
+            sys.exit(1)
+
     # Saving interface name to vif_name_file
     f = open(vif_name_file, 'w')
     f.write(vif_name)
index 6947080..dc6d448 100644 (file)
@@ -28,10 +28,6 @@ import os
 import socket
 import time
 
-# TODO:
-#       - CREATE GRE - PlanetlabGRE - it only needs to set the gre and remote
-#               properties when configuring the vif_up
-
 PYTHON_VSYS_VERSION = "1.0"
 
 @clsinit_copy
@@ -353,13 +349,13 @@ class PlanetlabTap(LinuxApplication):
     def gre_connect_command(self, remote_endpoint, connection_run_home): 
         # Set the remote endpoint
         self.set("pointopoint", remote_endpoint.get("ip4"))
-        self.set("gre_remote", socket.gethostbyname(
+        self.set("greRemote", socket.gethostbyname(
             remote_endpoint.node.get("hostname")))
 
         # Generate GRE connect command
 
         # Use vif_down command to first kill existing TAP in GRE mode
-        vif_down_command = self._vif_command_command
+        vif_down_command = self._vif_down_command
 
         # Use pl-vif-up.py script to configure TAP with peer info
         vif_up_command = self._vif_up_command
@@ -402,7 +398,7 @@ class PlanetlabTap(LinuxApplication):
     @property
     def _stop_command(self):
         if self.gre_enabled:
-            command = self._vif_down_command()
+            command = self._vif_down_command
         else:
             command = ["sudo -S "]
             command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
@@ -423,7 +419,8 @@ class PlanetlabTap(LinuxApplication):
         command = ["sudo -S "]
         command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
         command.append("python ${SRC}/pl-vif-up.py")
-        command.append("-N %s" % self.get("deviceName"))
+        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"))
@@ -438,8 +435,8 @@ class PlanetlabTap(LinuxApplication):
             command.append("-q %s" % self.get("txqueuelen"))
 
         if self.gre_enabled:
-            command.append("-g %s" % self.gre("greKey"))
-            command.append("-G %s" % self.gre("greRemote"))
+            command.append("-g %s" % self.get("greKey"))
+            command.append("-G %s" % self.get("greRemote"))
         
         command.append("-f %s " % self.vif_name_file)
 
@@ -447,11 +444,20 @@ class PlanetlabTap(LinuxApplication):
 
     @property
     def _vif_down_command(self):
+        if self.gre_enabled:
+            device_name = "%s" % self.guid
+        else:
+            device_name = self.get("deviceName")
+
         command = ["sudo -S "]
         command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
         command.append("python ${SRC}/pl-vif-down.py")
-        command.append("-D")
-        command.append("-N %s " % self.get("deviceName"))
+        command.append("-N %s " % device_name)
+        
+        if self.gre_enabled:
+            command.append("-u %s" % self.node.get("username"))
+            command.append("-t %s" % self.vif_type)
+            command.append("-D")
 
         return " ".join(command)
 
old mode 100644 (file)
new mode 100755 (executable)
index 2cde3ae..1d69a69
@@ -67,7 +67,7 @@ class GRETunnelTestCase(unittest.TestCase):
         ec.set(tap2, "prefix4", 24)
         ec.register_connection(tap2, node2)
 
-        gretun = ec.register_resource("GRETunnel")
+        gretun = ec.register_resource("LinuxGRETunnel")
         ec.register_connection(tap1, gretun)
         ec.register_connection(tap2, gretun)
 
@@ -93,7 +93,7 @@ class GRETunnelTestCase(unittest.TestCase):
         ec.shutdown()
 
     @skipIfAnyNotAliveWithIdentity
-    def t_tun_udp_tunnel(self, user1, host1, identity1, user2, host2, 
+    def t_tun_gre_tunnel(self, user1, host1, identity1, user2, host2, 
             identity2):
 
         ec = ExperimentController(exp_id = "test-tun-gre-tunnel")
@@ -107,7 +107,6 @@ class GRETunnelTestCase(unittest.TestCase):
 
         tun1 = ec.register_resource("PlanetlabTun")
         ec.set(tun1, "ip4", "%s.1" % self.netblock)
-        ec.set(tun1, "pointopoint", "%s.2" % self.netblock)
         ec.set(tun1, "prefix4", 24)
         ec.register_connection(tun1, node1)
 
@@ -120,11 +119,10 @@ class GRETunnelTestCase(unittest.TestCase):
 
         tun2 = ec.register_resource("PlanetlabTun")
         ec.set(tun2, "ip4", "%s.2" % self.netblock)
-        ec.set(tun2, "pointopoint", "%s.1" % self.netblock )
         ec.set(tun2, "prefix4", 24)
         ec.register_connection(tun2, node2)
 
-        udptun = ec.register_resource("UdpTunnel")
+        udptun = ec.register_resource("LinuxGRETunnel")
         ec.register_connection(tun1, udptun)
         ec.register_connection(tun2, udptun)
 
@@ -149,12 +147,12 @@ class GRETunnelTestCase(unittest.TestCase):
 
         ec.shutdown()
 
-    def test_tap_udp_tunnel(self):
-        self.t_tap_udp_tunnel(self.user, self.host1, self.identity,
+    def test_tap_gre_tunnel(self):
+        self.t_tap_gre_tunnel(self.user, self.host1, self.identity,
                 self.user, self.host2, self.identity)
 
-    def test_tun_udp_tunnel(self):
-        self.t_tun_udp_tunnel(self.user, self.host1, self.identity,
+    def test_tun_gre_tunnel(self):
+        self.t_tun_gre_tunnel(self.user, self.host1, self.identity,
                 self.user, self.host2, self.identity)
 
 if __name__ == '__main__':
old mode 100644 (file)
new mode 100755 (executable)