From: Alina Quereilhac Date: Tue, 18 Feb 2014 16:51:41 +0000 (+0100) Subject: Fix #128 - [NS3] Test ns-3 with localhost X-Git-Tag: nepi-3.1.0~118 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=0cff9603cef884887e19b6f594745284e54a2b19;p=nepi.git Fix #128 - [NS3] Test ns-3 with localhost --- diff --git a/src/nepi/resources/linux/ccn/ccnd.py b/src/nepi/resources/linux/ccn/ccnd.py index 95ac92ff..ffaee508 100644 --- a/src/nepi/resources/linux/ccn/ccnd.py +++ b/src/nepi/resources/linux/ccn/ccnd.py @@ -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: diff --git a/src/nepi/resources/linux/ccn/ccnr.py b/src/nepi/resources/linux/ccn/ccnr.py index 69a84375..9ac5cce0 100644 --- a/src/nepi/resources/linux/ccn/ccnr.py +++ b/src/nepi/resources/linux/ccn/ccnr.py @@ -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: diff --git a/src/nepi/resources/linux/node.py b/src/nepi/resources/linux/node.py index f9ae091c..214c4ef0 100644 --- a/src/nepi/resources/linux/node.py +++ b/src/nepi/resources/linux/node.py @@ -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 @: 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 @: 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 diff --git a/src/nepi/resources/linux/ns3/ns3simulation.py b/src/nepi/resources/linux/ns3/ns3simulation.py index a7780b07..9ce8291c 100644 --- a/src/nepi/resources/linux/ns3/ns3simulation.py +++ b/src/nepi/resources/linux/ns3/ns3simulation.py @@ -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 " " ) " " ) " diff --git a/src/nepi/resources/ns3/ns3application.py b/src/nepi/resources/ns3/ns3application.py index db6096b7..302e1289 100644 --- a/src/nepi/resources/ns3/ns3application.py +++ b/src/nepi/resources/ns3/ns3application.py @@ -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): diff --git a/src/nepi/util/execfuncs.py b/src/nepi/util/execfuncs.py index d2da3ace..c9980383 100644 --- a/src/nepi/util/execfuncs.py +++ b/src/nepi/util/execfuncs.py @@ -17,8 +17,10 @@ # # Author: Alina Quereilhac -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), diff --git a/src/nepi/util/sshfuncs.py b/src/nepi/util/sshfuncs.py index b9b5342c..d1952bcf 100644 --- a/src/nepi/util/sshfuncs.py +++ b/src/nepi/util/sshfuncs.py @@ -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)) diff --git a/test/resources/linux/ns3/ns3simulation.py b/test/resources/linux/ns3/ns3simulation.py index 25a11b2d..e632bcfb 100644 --- a/test/resources/linux/ns3/ns3simulation.py +++ b/test/resources/linux/ns3/ns3simulation.py @@ -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)