Fix #128 - [NS3] Test ns-3 with localhost
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 18 Feb 2014 16:51:41 +0000 (17:51 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 18 Feb 2014 16:51:41 +0000 (17:51 +0100)
src/nepi/resources/linux/ccn/ccnd.py
src/nepi/resources/linux/ccn/ccnr.py
src/nepi/resources/linux/node.py
src/nepi/resources/linux/ns3/ns3simulation.py
src/nepi/resources/ns3/ns3application.py
src/nepi/util/execfuncs.py
src/nepi/util/sshfuncs.py
test/resources/linux/ns3/ns3simulation.py

index 95ac92f..ffaee50 100644 (file)
@@ -194,8 +194,7 @@ class LinuxCCND(LinuxApplication):
         self.node.run_and_wait(command, self.run_home,
                 shfile = shfile,
                 overwrite = False,
-                env = env,
-                raise_on_error = True)
+                env = env)
 
     def do_start(self):
         if self.state == ResourceState.READY:
index 69a8437..9ac5cce 100644 (file)
@@ -247,8 +247,7 @@ class LinuxCCNR(LinuxApplication):
         self.node.run_and_wait(command, self.run_home,
                 shfile = shfile,
                 overwrite = False,
-                env = env,
-                raise_on_error = True)
+                env = env)
 
     def do_start(self):
         if self.state == ResourceState.READY:
index f9ae091..214c4ef 100644 (file)
@@ -274,7 +274,8 @@ class LinuxNode(ResourceManager):
         if self._os:
             return self._os
 
-        if (not self.get("hostname") or not self.get("username")):
+        if self.get("hostname") not in ["localhost", "127.0.0.1"] and \
+                not self.get("username"):
             msg = "Can't resolve OS, insufficient data "
             self.error(msg)
             raise RuntimeError, msg
@@ -400,6 +401,9 @@ class LinuxNode(ResourceManager):
     def clean_processes(self):
         self.info("Cleaning up processes")
  
+        if self.get("hostname") in ["localhost", "127.0.0.2"]:
+            return 
+        
         if self.get("username") != 'root':
             cmd = ("sudo -S killall tcpdump || /bin/true ; " +
                 "sudo -S kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; " +
@@ -424,7 +428,6 @@ class LinuxNode(ResourceManager):
                 cmd = ("killall tcpdump || /bin/true ; " +
                     "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; ")
 
-        out = err = ""
         (out, err), proc = self.execute(cmd, retry = 1, with_lock = True)
 
     def clean_home(self):
@@ -534,14 +537,13 @@ class LinuxNode(ResourceManager):
         self.debug("Running command '%s'" % command)
         
         if self.localhost:
-            (out, err), proc = execfuncs.lspawn(command, pidfile, 
-                    stdout = stdout, 
-                    stderr = stderr, 
-                    stdin = stdin, 
+            (out, err), proc = execfuncs.lspawn(command, pidfile,
                     home = home, 
                     create_home = create_home, 
-                    sudo = sudo,
-                    user = user) 
+                    stdin = stdin or '/dev/null',
+                    stdout = stdout or '/dev/null',
+                    stderr = stderr or '/dev/null',
+                    sudo = sudo) 
         else:
             with self._node_lock:
                 (out, err), proc = sshfuncs.rspawn(
@@ -549,9 +551,9 @@ class LinuxNode(ResourceManager):
                     pidfile = pidfile,
                     home = home,
                     create_home = create_home,
-                    stdin = stdin if stdin is not None else '/dev/null',
-                    stdout = stdout if stdout else '/dev/null',
-                    stderr = stderr if stderr else '/dev/null',
+                    stdin = stdin or '/dev/null',
+                    stdout = stdout or '/dev/null',
+                    stderr = stderr or '/dev/null',
                     sudo = sudo,
                     host = self.get("hostname"),
                     user = self.get("username"),
@@ -631,9 +633,8 @@ class LinuxNode(ResourceManager):
 
     def copy(self, src, dst):
         if self.localhost:
-            (out, err), proc = execfuncs.lcopy(source, dest, 
-                    recursive = True,
-                    strict_host_checking = False)
+            (out, err), proc = execfuncs.lcopy(src, dst, 
+                    recursive = True)
         else:
             with self._node_lock:
                 (out, err), proc = sshfuncs.rcopy(
@@ -648,7 +649,8 @@ class LinuxNode(ResourceManager):
 
         return (out, err), proc
 
-    def upload(self, src, dst, text = False, overwrite = True):
+    def upload(self, src, dst, text = False, overwrite = True,
+            raise_on_error = True):
         """ Copy content to destination
 
         src  string with the content to copy. Can be:
@@ -687,19 +689,36 @@ class LinuxNode(ResourceManager):
             # Build destination as <user>@<server>:<path>
             dst = "%s@%s:%s" % (self.get("username"), self.get("hostname"), dst)
 
-        result = self.copy(src, dst)
+        ((out, err), proc) = self.copy(src, dst)
 
         # clean up temp file
         if f:
             os.remove(f.name)
 
-        return result
+        if err:
+            msg = " Failed to upload files - src: %s dst: %s" %  (";".join(src), dst) 
+            self.error(msg, out, err)
+
+            if raise_on_error:
+                raise RuntimeError, msg
 
-    def download(self, src, dst):
+        return ((out, err), proc)
+
+    def download(self, src, dst, raise_on_error = True):
         if not self.localhost:
             # Build destination as <user>@<server>:<path>
             src = "%s@%s:%s" % (self.get("username"), self.get("hostname"), src)
-        return self.copy(src, dst)
+
+        ((out, err), proc) = self.copy(src, dst)
+
+        if err:
+            msg = " Failed to download files - src: %s dst: %s" %  (";".join(src), dst) 
+            self.error(msg, out, err)
+
+            if raise_on_error:
+                raise RuntimeError, msg
+
+        return ((out, err), proc)
 
     def install_packages_command(self, packages):
         command = ""
@@ -714,7 +733,8 @@ class LinuxNode(ResourceManager):
 
         return command
 
-    def install_packages(self, packages, home, run_home = None):
+    def install_packages(self, packages, home, run_home = None,
+            raise_on_error = True):
         """ Install packages in the Linux host.
 
         'home' is the directory to upload the package installation script.
@@ -731,11 +751,12 @@ class LinuxNode(ResourceManager):
             stdout = "instpkg_stdout", 
             stderr = "instpkg_stderr",
             overwrite = False,
-            raise_on_error = True)
+            raise_on_error = raise_on_error)
 
         return (out, err), proc 
 
-    def remove_packages(self, packages, home, run_home = None):
+    def remove_packages(self, packages, home, run_home = None,
+            raise_on_error = True):
         """ Uninstall packages from the Linux host.
 
         'home' is the directory to upload the package un-installation script.
@@ -759,7 +780,7 @@ class LinuxNode(ResourceManager):
             stdout = "rmpkg_stdout", 
             stderr = "rmpkg_stderr",
             overwrite = False,
-            raise_on_error = True)
+            raise_on_error = raise_on_error)
          
         return (out, err), proc 
 
@@ -783,7 +804,7 @@ class LinuxNode(ResourceManager):
             stderr = "stderr", 
             sudo = False,
             tty = False,
-            raise_on_error = False):
+            raise_on_error = True):
         """
         Uploads the 'command' to a bash script in the host.
         Then runs the script detached in background in the host, and
index a7780b0..9ce8291 100644 (file)
@@ -376,6 +376,7 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation):
                 "     ( "
                 "       tar xf ${SRC}/%(pygccxml_version)s.tar.gz -C ${SRC} && "
                 "       cd ${SRC}/%(pygccxml_version)s && "
+                "       python setup.py build && "
                 "       sudo -S python setup.py install "
                 "     ) "
                 "   ) " 
index db6096b..302e128 100644 (file)
@@ -62,6 +62,7 @@ class NS3BaseApplication(NS3Base):
             self.ec.schedule(reschedule_delay, self.start)
         else:
             super(NS3BaseApplication, self).do_start()
+            self._start_time = self.simulation.start_time
 
     @property
     def state(self):
index d2da3ac..c998038 100644 (file)
 #
 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
 
-from nepi.util.sshfuncs import ProcStatus, STDOUT
+from nepi.util.sshfuncs import ProcStatus, STDOUT, log, shell_escape
 
+import logging
+import shlex
 import subprocess
 
 def lexec(command, 
@@ -39,12 +41,21 @@ def lexec(command,
     elif user:
         command = "su %s ; %s " % (user, command)
 
+    proc = subprocess.Popen(command,
+                shell = True, 
+                stdout = subprocess.PIPE, 
+                stderr = subprocess.PIPE)
 
-    proc = subprocess.Popen(command, shell=True, 
-            stdout = subprocess.PIPE, 
-            stderr = subprocess.PIPE)
+    out = err = ""
+    log_msg = "lexec - command %s " % command
+
+    try:
+        out, err = proc.communicate()
+        log(log_msg, logging.DEBUG, out, err)
+    except:
+        log(log_msg, logging.ERROR, out, err)
+        raise
 
-    out, err = proc.communicate()
     return ((out, err), proc)
 
 def lcopy(source, dest, recursive = False):
@@ -52,28 +63,35 @@ def lcopy(source, dest, recursive = False):
     Copies from/to localy.
     """
     
-    if TRACE:
-        print "scp", source, dest
-    
-    command = ["cp"]
+    args = ["cp"]
     if recursive:
-        command.append("-R")
+        args.append("-r")
   
-    if isinstance(dest, str):
-        dest = dest.split(";")
-
-    if isinstance(src, str):
-        src = src.split(";")
-           
-    args.extend(src)
+    if isinstance(source, list):
+        args.extend(source)
+    else:
+        args.append(source)
 
-    args.extend(dest)
+    if isinstance(dest, list):
+        args.extend(dest)
+    else:
+        args.append(dest)
 
-    proc = subprocess.Popen(command
+    proc = subprocess.Popen(args
         stdout=subprocess.PIPE, 
         stderr=subprocess.PIPE)
 
-    out, err = proc.communicate()
+    out = err = ""
+    command = " ".join(args)
+    log_msg = " lcopy - command %s " % command
+
+    try:
+        out, err = proc.communicate()
+        log(log_msg, logging.DEBUG, out, err)
+    except:
+        log(log_msg, logging.ERROR, out, err)
+        raise
+
     return ((out, err), proc)
    
 def lspawn(command, pidfile, 
@@ -125,7 +143,7 @@ def lspawn(command, pidfile,
         'stdin' : stdin,
     }
     
-    cmd = "%(create)s%(gohome)s rm -f %(pidfile)s ; %(sudo)s nohup bash -c %(command)s " % {
+    cmd = "%(create)s%(gohome)s rm -f %(pidfile)s ; %(sudo)s bash -c %(command)s " % {
             'command' : shell_escape(daemon_command),
             'sudo' : 'sudo -S' if sudo else '',
             'pidfile' : shell_escape(pidfile),
index b9b5342..d1952bc 100644 (file)
@@ -46,7 +46,6 @@ def log(msg, level, out = None, err = None):
 
     logger.log(level, msg)
 
-
 if hasattr(os, "devnull"):
     DEV_NULL = os.devnull
 else:
@@ -304,7 +303,6 @@ def rcopy(source, dest,
         port = None,
         gwuser = None,
         gw = None,
-        agent = True, 
         recursive = False,
         identity = None,
         server_key = None,
@@ -377,11 +375,14 @@ def rcopy(source, dest,
         if openssh_has_persist():
             args.extend([
                 '-o', 'ControlMaster=auto',
-                '-o', 'ControlPath=%s' % (make_control_path(agent, False),)
+                '-o', 'ControlPath=%s' % (make_control_path(False, False),)
                 ])
         args.append(source)
 
-    args.append(dest)
+    if isinstance(dest, list):
+        args.extend(dest)
+    else:
+        args.append(dest)
 
     log_msg = " rcopy - host %s - command %s " % (host, " ".join(args))
     
index 25a11b2..e632bcf 100644 (file)
@@ -146,6 +146,47 @@ class LinuxNS3ClientTest(unittest.TestCase):
         self.fedora_user = "inria_nepi"
         self.fedora_identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
 
+    def test_local_p2p_ping(self):
+        ec = ExperimentController(exp_id = "test-ns3-local-p2p")
+        
+        node = ec.register_resource("LinuxNode")
+        ec.set(node, "hostname", "localhost")
+
+        simu = ec.register_resource("LinuxNS3Simulation")
+        ec.register_connection(simu, node)
+
+        nsnode1 = add_ns3_node(ec, simu)
+        dev1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
+
+        nsnode2 = add_ns3_node(ec, simu)
+        dev2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
+
+        # Create channel
+        chan = ec.register_resource("ns3::PointToPointChannel")
+        ec.set(chan, "Delay", "0s")
+        ec.register_connection(chan, dev1)
+        ec.register_connection(chan, dev2)
+
+        ### create pinger
+        ping = ec.register_resource("ns3::V4Ping")
+        ec.set (ping, "Remote", "10.0.0.2")
+        ec.set (ping, "Interval", "1s")
+        ec.set (ping, "Verbose", True)
+        ec.set (ping, "StartTime", "0s")
+        ec.set (ping, "StopTime", "20s")
+        ec.register_connection(ping, nsnode1)
+
+        ec.deploy()
+
+        ec.wait_finished([ping])
+        
+        stdout = ec.trace(simu, "stdout") 
+
+        expected = "20 packets transmitted, 20 received, 0% packet loss"
+        self.assertTrue(stdout.find(expected) > -1)
+
+        ec.shutdown()
+
     def test_simple_p2p_ping(self):
         ec = ExperimentController(exp_id = "test-ns3-p2p-ping")
         
@@ -385,15 +426,15 @@ class LinuxNS3ClientTest(unittest.TestCase):
         rm = ec.get_resource(ping)
         start_time = rm.start_time
         stop_time = rm.stop_time
-        delta =  stop_time - start_time
+        delta = stop_time - start_time
 
-        self.assertTrue(delta.seconds >= 20)
-        self.assertTrue(delta.seconds < 25)
+        self.assertTrue(delta.seconds >= 20, "Time elapsed %d" % delta.seconds)
+        self.assertTrue(delta.seconds < 25, "Time elapsed %d" % delta.seconds)
 
         ec.shutdown()
 
-    def test_dev2p_traces(self):
-        ec = ExperimentController(exp_id = "test-ns3-dev2p-traces")
+    def test_traces(self):
+        ec = ExperimentController(exp_id = "test-ns3-traces")
         
         node = ec.register_resource("LinuxNode")
         ec.set(node, "hostname", self.fedora_host)