From: Thierry Parmentelat Date: Thu, 9 Apr 2015 10:29:10 +0000 (+0200) Subject: released to pypi X-Git-Tag: nepi-3.2-pypi X-Git-Url: http://git.onelab.eu/?p=nepi.git;a=commitdiff_plain;h=e96e370df463518cf451a8f8df9f9a93d2b94730 released to pypi --- diff --git a/Makefile b/Makefile index 01a1d3bf..118c778b 100644 --- a/Makefile +++ b/Makefile @@ -64,3 +64,18 @@ dist: MANIFEST ./setup.py sdist .PHONY: all clean distclean dist test coverage install MANIFEST + +########## for uploading onto pypi +# use pypitest instead for tests (both entries need to be defined in your .pypirc) +PYPI_TARGET=pypi +PYPI_TARBALL_HOST=root@build.onelab.eu +PYPI_TARBALL_TOPDIR=/build/nepi + +VERSIONTAG=$(shell cat VERSION) + +# run this only once the sources are in on the right tag +pypi: + setup.py sdist upload -r $(PYPI_TARGET) + ssh $(PYPI_TARBALL_HOST) mkdir -p $(PYPI_TARBALL_TOPDIR)/$(VERSIONTAG) + rsync -av dist/nepi-$(VERSIONTAG).tar.gz $(PYPI_TARBALL_HOST):$(PYPI_TARBALL_TOPDIR)/ + diff --git a/README b/README new file mode 100644 index 00000000..aede580a --- /dev/null +++ b/README @@ -0,0 +1 @@ +NEPI is a Python-based library to model and run network experiments on a variety of network evaluation platforms, including PlanetLab, OMF wireless testbeds, ns-3 simulators, and others. It allows to specify resources to use in an experiment, to define experiment workflow constraints and to automate deployment, resource control and result collection. diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..a3ec5a4b --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +3.2 diff --git a/setup.py b/setup.py index 7037c19b..988b4bc0 100755 --- a/setup.py +++ b/setup.py @@ -3,41 +3,52 @@ from distutils.core import setup import sys + +with open('VERSION') as f: + version_tag = f.read().strip() +with open("COPYING") as f: + license = f.read() +with open("README") as f: + long_description = f.read() + setup( - name = "nepi", - version = "nepi-3-dev", - description = "Network Experiment Management Framework", - author = "Alina Quereilhac, Julien Tribino, Lucia Guevgeozian", - url = "http://nepi.inria.fr", - license = "GPLv2", - platforms = "Linux, OSX", - packages = [ - "nepi", - "nepi.execution", - "nepi.resources", - "nepi.resources.all", - "nepi.resources.linux", - "nepi.resources.linux.ccn", - "nepi.resources.linux.ns3", - "nepi.resources.linux.ns3.ccn", - "nepi.resources.linux.netns", - "nepi.resources.netns", - "nepi.resources.ns3", - "nepi.resources.ns3.classes", - "nepi.resources.omf", - "nepi.resources.planetlab", - "nepi.resources.planetlab.ns3", - "nepi.resources.planetlab.openvswitch", - "nepi.util", - "nepi.util.parsers", - "nepi.data", - "nepi.data.processing", - "nepi.data.processing.ccn", - "nepi.data.processing.ping"], - package_dir = {"": "src"}, - package_data = { - "nepi.resources.planetlab" : [ "scripts/*.py" ], - "nepi.resources.linux" : [ "scripts/*.py" ], - "nepi.resources.linux.ns3" : [ "dependencies/*.tar.gz" ] - } - ) + name = "nepi", + version = version_tag, + description = "Network Experiment Management Framework", + long_description = long_description, + license = license, + author = "Alina Quereilhac", + author_email = "alina.quereilhac@inria.fr", + download_url = "http://build.onelab.eu/nepi/nepi-{v}.tar.gz".format(v=version_tag), + url = "http://nepi.inria.fr/", + platforms = "Linux, OSX", + package_dir = {"": "src"}, + packages = [ + "nepi", + "nepi.execution", + "nepi.resources", + "nepi.resources.all", + "nepi.resources.linux", + "nepi.resources.linux.ccn", + "nepi.resources.linux.ns3", + "nepi.resources.linux.ns3.ccn", + "nepi.resources.linux.netns", + "nepi.resources.netns", + "nepi.resources.ns3", + "nepi.resources.ns3.classes", + "nepi.resources.omf", + "nepi.resources.planetlab", + "nepi.resources.planetlab.ns3", + "nepi.resources.planetlab.openvswitch", + "nepi.util", + "nepi.util.parsers", + "nepi.data", + "nepi.data.processing", + "nepi.data.processing.ccn", + "nepi.data.processing.ping"], + package_data = { + "nepi.resources.planetlab" : [ "scripts/*.py" ], + "nepi.resources.linux" : [ "scripts/*.py" ], + "nepi.resources.linux.ns3" : [ "dependencies/*.tar.gz" ] + } +) diff --git a/src/nepi/resources/linux/node.py b/src/nepi/resources/linux/node.py index b0d63c93..0abbf8fe 100644 --- a/src/nepi/resources/linux/node.py +++ b/src/nepi/resources/linux/node.py @@ -17,8 +17,8 @@ # Author: Alina Quereilhac from nepi.execution.attribute import Attribute, Flags, Types -from nepi.execution.resource import ResourceManager, clsinit_copy, \ - ResourceState +from nepi.execution.resource import (ResourceManager, clsinit_copy, + ResourceState) from nepi.resources.linux import rpmfuncs, debfuncs from nepi.util import sshfuncs, execfuncs from nepi.util.sshfuncs import ProcStatus @@ -147,77 +147,81 @@ class LinuxNode(ResourceManager): @classmethod def _register_attributes(cls): - hostname = Attribute("hostname", "Hostname of the machine", - flags = Flags.Design) + cls._register_attribute(Attribute( + "hostname", "Hostname of the machine", + flags = Flags.Design)) - username = Attribute("username", "Local account username", - flags = Flags.Credential) + cls._register_attribute(Attribute( + "username", "Local account username", + flags = Flags.Credential)) - port = Attribute("port", "SSH port", flags = Flags.Design) + cls._register_attribute(Attribute( + "port", "SSH port", + flags = Flags.Design)) - home = Attribute("home", - "Experiment home directory to store all experiment related files", - flags = Flags.Design) + cls._register_attribute(Attribute( + "home", + "Experiment home directory to store all experiment related files", + flags = Flags.Design)) - identity = Attribute("identity", "SSH identity file", - flags = Flags.Credential) + cls._register_attribute(Attribute( + "identity", "SSH identity file", + flags = Flags.Credential)) - server_key = Attribute("serverKey", "Server public key", - flags = Flags.Design) + cls._register_attribute(Attribute( + "serverKey", "Server public key", + flags = Flags.Design)) - clean_home = Attribute("cleanHome", "Remove all nepi files and directories " - " from node home folder before starting experiment", - type = Types.Bool, - default = False, - flags = Flags.Design) - - clean_experiment = Attribute("cleanExperiment", "Remove all files and directories " - " from a previous same experiment, before the new experiment starts", - type = Types.Bool, - default = False, - flags = Flags.Design) + cls._register_attribute(Attribute( + "cleanHome", + "Remove all nepi files and directories " + " from node home folder before starting experiment", + type = Types.Bool, + default = False, + flags = Flags.Design)) + + cls._register_attribute(Attribute( + "cleanExperiment", "Remove all files and directories " + " from a previous same experiment, before the new experiment starts", + type = Types.Bool, + default = False, + flags = Flags.Design)) - clean_processes = Attribute("cleanProcesses", - "Kill all running processes before starting experiment", - type = Types.Bool, - default = False, - flags = Flags.Design) + cls._register_attribute(Attribute( + "cleanProcesses", + "Kill all running processes before starting experiment", + type = Types.Bool, + default = False, + flags = Flags.Design)) - clean_processes_after = Attribute("cleanProcessesAfter", - """Kill all running processes after starting experiment -This might be dangerous when using user root""", - type = Types.Bool, - default = True, - flags = Flags.Design) + cls._register_attribute(Attribute( + "cleanProcessesAfter", + """Kill all running processes after starting experiment + This might be dangerous when using user root""", + type = Types.Bool, + default = True, + flags = Flags.Design)) - tear_down = Attribute("tearDown", "Bash script to be executed before " + \ - "releasing the resource", - flags = Flags.Design) - - gateway_user = Attribute("gatewayUser", "Gateway account username", - flags = Flags.Design) - - gateway = Attribute("gateway", "Hostname of the gateway machine", - flags = Flags.Design) - - ip = Attribute("ip", "Linux host public IP address. " - "Must not be modified by the user unless hostname is 'localhost'", - flags = Flags.Design) - - cls._register_attribute(hostname) - cls._register_attribute(username) - cls._register_attribute(port) - cls._register_attribute(home) - cls._register_attribute(identity) - cls._register_attribute(server_key) - cls._register_attribute(clean_home) - cls._register_attribute(clean_experiment) - cls._register_attribute(clean_processes) - cls._register_attribute(clean_processes_after) - cls._register_attribute(tear_down) - cls._register_attribute(gateway_user) - cls._register_attribute(gateway) - cls._register_attribute(ip) + cls._register_attribute(Attribute( + "tearDown", + "Bash script to be executed before releasing the resource", + flags = Flags.Design)) + + cls._register_attribute(Attribute( + "gatewayUser", + "Gateway account username", + flags = Flags.Design)) + + cls._register_attribute(Attribute( + "gateway", + "Hostname of the gateway machine", + flags = Flags.Design)) + + cls._register_attribute(Attribute( + "ip", + "Linux host public IP address. " + "Must not be modified by the user unless hostname is 'localhost'", + flags = Flags.Design)) def __init__(self, ec, guid): super(LinuxNode, self).__init__(ec, guid) @@ -233,17 +237,17 @@ This might be dangerous when using user root""", # of a file or folder prior to its creation, and another # application creating the same file or folder in between. self._node_lock = threading.Lock() - + def log_message(self, msg): - return " guid %d - host %s - %s " % (self.guid, - self.get("hostname"), msg) + return " guid {} - host {} - {} "\ + .format(self.guid, self.get("hostname"), msg) @property def home_dir(self): home = self.get("home") or "" if not home.startswith("/"): - home = os.path.join(self._home_dir, home) - return home + home = os.path.join(self._home_dir, home) + return home @property def nepi_home(self): @@ -279,7 +283,7 @@ This might be dangerous when using user root""", @property def node_home(self): - return os.path.join(self.exp_home, "node-%d" % self.guid) + return os.path.join(self.exp_home, "node-{}".format(self.guid)) @property def run_home(self): @@ -312,7 +316,7 @@ This might be dangerous when using user root""", else: msg = "Unsupported OS" self.error(msg, out) - raise RuntimeError, "%s - %s " %( msg, out ) + raise RuntimeError("{} - {} ".format(msg, out)) return self._os @@ -324,13 +328,13 @@ This might be dangerous when using user root""", out = "" try: (out, err), proc = self.execute("cat /etc/issue", - with_lock = True, - blocking = True) + with_lock = True, + blocking = True) except: trace = traceback.format_exc() - msg = "Error detecting OS: %s " % trace + msg = "Error detecting OS: {} ".format(trace) self.error(msg, out, err) - + return out @property @@ -348,7 +352,7 @@ This might be dangerous when using user root""", def do_provision(self): # check if host is alive if not self.is_alive(): - msg = "Deploy failed. Unresponsive node %s" % self.get("hostname") + msg = "Deploy failed. Unresponsive node {}".format(self.get("hostname")) self.error(msg) raise RuntimeError, msg @@ -359,16 +363,16 @@ This might be dangerous when using user root""", if self.get("cleanHome"): self.clean_home() - + if self.get("cleanExperiment"): self.clean_experiment() - + # Create shared directory structure and node home directory paths = [self.lib_dir, - self.bin_dir, - self.src_dir, - self.share_dir, - self.node_home] + self.bin_dir, + self.src_dir, + self.share_dir, + self.node_home] self.mkdir(paths) @@ -379,7 +383,7 @@ This might be dangerous when using user root""", self.set("ip", ip) except: if self.get("gateway") is None: - msg = "Local DNS can not resolve hostname %s" % self.get("hostname") + msg = "Local DNS can not resolve hostname {}".format(self.get("hostname")) self.error(msg) super(LinuxNode, self).do_provision() @@ -431,8 +435,8 @@ This might be dangerous when using user root""", if self.get("username") != 'root': cmd = ("sudo -S killall tcpdump || /bin/true ; " + - "sudo -S kill -9 $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; " + - "sudo -S killall -u %s || /bin/true ; " % self.get("username")) + "sudo -S kill -9 $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; " + + "sudo -S killall -u {} || /bin/true ; ".format(self.get("username"))) else: if self.state >= ResourceState.READY: import pickle @@ -448,14 +452,14 @@ This might be dangerous when using user root""", kill_pids = ' '.join(dict(kill_pids).keys()) cmd = ("killall tcpdump || /bin/true ; " + - "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; " + - "kill %s || /bin/true ; " % kill_pids) + "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; " + + "kill {} || /bin/true ; ".format(kill_pids)) else: cmd = ("killall tcpdump || /bin/true ; " + - "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; ") + "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; ") else: cmd = ("killall tcpdump || /bin/true ; " + - "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; ") + "kill $(ps aux | grep '[.]nepi' | awk '{print $2}') || /bin/true ; ") (out, err), proc = self.execute(cmd, retry = 1, with_lock = True) @@ -464,8 +468,8 @@ This might be dangerous when using user root""", """ self.info("Cleaning up home") - cmd = "cd %s ; find . -maxdepth 1 -name \.nepi -execdir rm -rf {} + " % ( - self.home_dir ) + cmd = "cd {} ; find . -maxdepth 1 -name \.nepi -execdir rm -rf {} + "\ + .format(self.home_dir) return self.execute(cmd, with_lock = True) @@ -476,33 +480,33 @@ This might be dangerous when using user root""", """ self.info("Cleaning up experiment files") - cmd = "cd %s ; find . -maxdepth 1 -name '%s' -execdir rm -rf {} + " % ( - self.exp_dir, - self.ec.exp_id ) - + cmd = "cd {} ; find . -maxdepth 1 -name '{}' -execdir rm -rf {} + "\ + .format(self.exp_dir, self.ec.exp_id) + return self.execute(cmd, with_lock = True) def execute(self, command, - sudo = False, - env = None, - tty = False, - forward_x11 = False, - retry = 3, - connect_timeout = 30, - strict_host_checking = False, - persistent = True, - blocking = True, - with_lock = False - ): + sudo = False, + env = None, + tty = False, + forward_x11 = False, + retry = 3, + connect_timeout = 30, + strict_host_checking = False, + persistent = True, + blocking = True, + with_lock = False + ): """ Notice that this invocation will block until the execution finishes. If this is not the desired behavior, use 'run' instead.""" if self.localhost: - (out, err), proc = execfuncs.lexec(command, - user = self.get("username"), # still problem with localhost - sudo = sudo, - env = env) + (out, err), proc = execfuncs.lexec( + command, + user = self.get("username"), # still problem with localhost + sudo = sudo, + env = env) else: if with_lock: # If the execute command is blocking, we don't want to keep @@ -529,7 +533,7 @@ This might be dangerous when using user root""", persistent = persistent, blocking = blocking, strict_host_checking = strict_host_checking - ) + ) else: (out, err), proc = sshfuncs.rexec( command, @@ -550,7 +554,7 @@ This might be dangerous when using user root""", persistent = persistent, blocking = blocking, strict_host_checking = strict_host_checking - ) + ) return (out, err), proc @@ -564,16 +568,17 @@ This might be dangerous when using user root""", tty = False, strict_host_checking = False): - self.debug("Running command '%s'" % command) + self.debug("Running command '{}'".format(command)) if self.localhost: - (out, err), proc = execfuncs.lspawn(command, pidfile, - home = home, - create_home = create_home, - stdin = stdin or '/dev/null', - stdout = stdout or '/dev/null', - stderr = stderr or '/dev/null', - sudo = sudo) + (out, err), proc = execfuncs.lspawn( + command, pidfile, + home = home, + create_home = create_home, + 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( @@ -595,7 +600,7 @@ This might be dangerous when using user root""", server_key = self.get("serverKey"), tty = tty, strict_host_checking = strict_host_checking - ) + ) return (out, err), proc @@ -615,7 +620,7 @@ This might be dangerous when using user root""", identity = self.get("identity"), server_key = self.get("serverKey"), strict_host_checking = False - ) + ) return pidtuple @@ -625,17 +630,17 @@ This might be dangerous when using user root""", else: with self._node_lock: status = sshfuncs.rstatus( - pid, ppid, - host = self.get("hostname"), - user = self.get("username"), - port = self.get("port"), - gwuser = self.get("gatewayUser"), - gw = self.get("gateway"), - agent = True, - identity = self.get("identity"), - server_key = self.get("serverKey"), - strict_host_checking = False - ) + pid, ppid, + host = self.get("hostname"), + user = self.get("username"), + port = self.get("port"), + gwuser = self.get("gatewayUser"), + gw = self.get("gateway"), + agent = True, + identity = self.get("identity"), + server_key = self.get("serverKey"), + strict_host_checking = False + ) return status @@ -661,14 +666,15 @@ This might be dangerous when using user root""", identity = self.get("identity"), server_key = self.get("serverKey"), strict_host_checking = False - ) + ) return (out, err), proc def copy(self, src, dst): if self.localhost: - (out, err), proc = execfuncs.lcopy(src, dst, - recursive = True) + (out, err), proc = execfuncs.lcopy( + src, dst, + recursive = True) else: with self._node_lock: (out, err), proc = sshfuncs.rcopy( @@ -684,7 +690,7 @@ This might be dangerous when using user root""", return (out, err), proc def upload(self, src, dst, text = False, overwrite = True, - raise_on_error = True): + raise_on_error = True): """ Copy content to destination src string with the content to copy. Can be: @@ -721,7 +727,7 @@ This might be dangerous when using user root""", if not self.localhost: # Build destination as @: - dst = "%s@%s:%s" % (self.get("username"), self.get("hostname"), dst) + dst = "{}@{}:{}".format(self.get("username"), self.get("hostname"), dst) ((out, err), proc) = self.copy(src, dst) @@ -730,10 +736,10 @@ This might be dangerous when using user root""", os.remove(f.name) if err: - msg = " Failed to upload files - src: %s dst: %s" % (";".join(src), dst) + msg = " Failed to upload files - src: {} dst: {}".format(";".join(src), dst) self.error(msg, out, err) - msg = "%s out: %s err: %s" % (msg, out, err) + msg = "{} out: {} err: {}".format(msg, out, err) if raise_on_error: raise RuntimeError, msg @@ -742,12 +748,12 @@ This might be dangerous when using user root""", 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) + src = "{}@{}:{}".format(self.get("username"), self.get("hostname"), src) ((out, err), proc) = self.copy(src, dst) if err: - msg = " Failed to download files - src: %s dst: %s" % (";".join(src), dst) + msg = " Failed to download files - src: {} dst: {}".format(";".join(src), dst) self.error(msg, out, err) if raise_on_error: @@ -768,8 +774,9 @@ This might be dangerous when using user root""", return command - def install_packages(self, packages, home, run_home = None, - raise_on_error = True): + 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. @@ -780,18 +787,18 @@ This might be dangerous when using user root""", run_home = run_home or home (out, err), proc = self.run_and_wait(command, run_home, - shfile = os.path.join(home, "instpkg.sh"), - pidfile = "instpkg_pidfile", - ecodefile = "instpkg_exitcode", - stdout = "instpkg_stdout", - stderr = "instpkg_stderr", - overwrite = False, - raise_on_error = raise_on_error) + shfile = os.path.join(home, "instpkg.sh"), + pidfile = "instpkg_pidfile", + ecodefile = "instpkg_exitcode", + stdout = "instpkg_stdout", + stderr = "instpkg_stderr", + overwrite = False, + raise_on_error = raise_on_error) return (out, err), proc def remove_packages(self, packages, home, run_home = None, - raise_on_error = True): + raise_on_error = True): """ Uninstall packages from the Linux host. 'home' is the directory to upload the package un-installation script. @@ -809,14 +816,14 @@ This might be dangerous when using user root""", run_home = run_home or home (out, err), proc = self.run_and_wait(command, run_home, - shfile = os.path.join(home, "rmpkg.sh"), - pidfile = "rmpkg_pidfile", - ecodefile = "rmpkg_exitcode", - stdout = "rmpkg_stdout", - stderr = "rmpkg_stderr", - overwrite = False, - raise_on_error = raise_on_error) - + shfile = os.path.join(home, "rmpkg.sh"), + pidfile = "rmpkg_pidfile", + ecodefile = "rmpkg_exitcode", + stdout = "rmpkg_stdout", + stderr = "rmpkg_stderr", + overwrite = False, + raise_on_error = raise_on_error) + return (out, err), proc def mkdir(self, paths, clean = False): @@ -829,7 +836,7 @@ This might be dangerous when using user root""", if isinstance(paths, str): paths = [paths] - cmd = " ; ".join(map(lambda path: "mkdir -p %s" % path, paths)) + cmd = " ; ".join(["mkdir -p {}".format(path) for path in paths]) return self.execute(cmd, with_lock = True) @@ -841,23 +848,23 @@ This might be dangerous when using user root""", if isinstance(paths, str): paths = [paths] - cmd = " ; ".join(map(lambda path: "rm -rf %s" % path, paths)) + cmd = " ; ".join(map(lambda path: "rm -rf {}".format(path), paths)) return self.execute(cmd, with_lock = True) - + def run_and_wait(self, command, home, - shfile="cmd.sh", - env=None, - overwrite=True, - wait_run=True, - pidfile="pidfile", - ecodefile="exitcode", - stdin=None, - stdout="stdout", - stderr="stderr", - sudo=False, - tty=False, - raise_on_error=True): + shfile="cmd.sh", + env=None, + overwrite=True, + wait_run=True, + pidfile="pidfile", + ecodefile="exitcode", + stdin=None, + stdout="stdout", + stderr="stderr", + sudo=False, + tty=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 @@ -868,45 +875,45 @@ This might be dangerous when using user root""", shfile = os.path.join(home, shfile) self.upload_command(command, - shfile = shfile, - ecodefile = ecodefile, - env = env, - overwrite = overwrite) + shfile = shfile, + ecodefile = ecodefile, + env = env, + overwrite = overwrite) - command = "bash %s" % shfile + command = "bash {}".format(shfile) # run command in background in remote host (out, err), proc = self.run(command, home, - pidfile = pidfile, - stdin = stdin, - stdout = stdout, - stderr = stderr, - sudo = sudo, - tty = tty) + pidfile = pidfile, + stdin = stdin, + stdout = stdout, + stderr = stderr, + sudo = sudo, + tty = tty) # check no errors occurred if proc.poll(): - msg = " Failed to run command '%s' " % command + msg = " Failed to run command '{}' ".format(command) self.error(msg, out, err) if raise_on_error: raise RuntimeError, msg # Wait for pid file to be generated pid, ppid = self.wait_pid( - home = home, - pidfile = pidfile, - raise_on_error = raise_on_error) + home = home, + pidfile = pidfile, + raise_on_error = raise_on_error) if wait_run: # wait until command finishes to execute self.wait_run(pid, ppid) - + (eout, err), proc = self.check_errors(home, - ecodefile = ecodefile, - stderr = stderr) + ecodefile = ecodefile, + stderr = stderr) # Out is what was written in the stderr file if err: - msg = " Failed to run command '%s' " % command + msg = " Failed to run command '{}' ".format(command) self.error(msg, eout, err) if raise_on_error: @@ -939,22 +946,20 @@ This might be dangerous when using user root""", return ExitCode.ERROR def upload_command(self, command, - shfile="cmd.sh", - ecodefile="exitcode", - overwrite=True, - env=None): + shfile="cmd.sh", + ecodefile="exitcode", + overwrite=True, + env=None): """ Saves the command as a bash script file in the remote host, and forces to save the exit code of the command execution to the ecodefile """ if not (command.strip().endswith(";") or command.strip().endswith("&")): command += ";" - + # The exit code of the command will be stored in ecodefile - command = " { %(command)s } ; echo $? > %(ecodefile)s ;" % { - 'command': command, - 'ecodefile': ecodefile, - } + command = " {{ {command} }} ; echo $? > {ecodefile} ;"\ + .format(command=command, ecodefile=ecodefile) # Export environment environ = self.format_environment(env) @@ -976,11 +981,11 @@ This might be dangerous when using user root""", env = re.sub(r'\s+', ' ', env.strip()) sep = ";" if inline else "\n" - return sep.join(map(lambda e: " export %s" % e, env.split(" "))) + sep + return sep.join([" export {}".format(e) for e in env.split(" ")]) + sep def check_errors(self, home, - ecodefile = "exitcode", - stderr = "stderr"): + ecodefile = "exitcode", + stderr = "stderr"): """ Checks whether errors occurred while running a command. It first checks the exit code for the command, and only if the exit code is an error one it returns the error output. @@ -993,7 +998,7 @@ This might be dangerous when using user root""", ecode = self.exitcode(home, ecodefile) if ecode in [ ExitCode.CORRUPTFILE, ExitCode.ERROR ]: - err = "Error retrieving exit code status from file %s/%s" % (home, ecodefile) + err = "Error retrieving exit code status from file {}/{}".format(home, ecodefile) elif ecode > 0 or ecode == ExitCode.FILENOTFOUND: # The process returned an error code or didn't exist. # Check standard error. @@ -1004,9 +1009,9 @@ This might be dangerous when using user root""", # (cat returns 1 for error "No such file or directory") if ecode == ExitCode.FILENOTFOUND and proc.poll() == 1: err = "" - + return ("", err), proc - + def wait_pid(self, home, pidfile = "pidfile", raise_on_error = False): """ Waits until the pid file for the command is generated, and returns the pid and ppid of the process """ @@ -1023,10 +1028,9 @@ This might be dangerous when using user root""", time.sleep(delay) delay = delay * 1.5 else: - msg = " Failed to get pid for pidfile %s/%s " % ( - home, pidfile ) + msg = " Failed to get pid for pidfile {}/{} ".format(home, pidfile ) self.error(msg) - + if raise_on_error: raise RuntimeError, msg @@ -1054,8 +1058,8 @@ This might be dangerous when using user root""", def check_output(self, home, filename): """ Retrives content of file """ - (out, err), proc = self.execute("cat %s" % - os.path.join(home, filename), retry = 1, with_lock = True) + (out, err), proc = self.execute( + "cat {}".format(os.path.join(home, filename)), retry = 1, with_lock = True) return (out, err), proc def is_alive(self): @@ -1073,20 +1077,21 @@ This might be dangerous when using user root""", # until the result is not empty string try: (out, err), proc = self.execute("echo 'ALIVE'", - blocking = True, - with_lock = True) - + blocking = True, + with_lock = True) + if out.find("ALIVE") > -1: return True except: trace = traceback.format_exc() - msg = "Unresponsive host. Error reaching host: %s " % trace + msg = "Unresponsive host. Error reaching host: {} ".format(trace) self.error(msg, out, err) return False def find_home(self): - """ Retrieves host home directory + """ + Retrieves host home directory """ # The underlying SSH layer will sometimes return an empty # output (even if the command was executed without errors). @@ -1095,14 +1100,14 @@ This might be dangerous when using user root""", msg = "Impossible to retrieve HOME directory" try: (out, err), proc = self.execute("echo ${HOME}", - blocking = True, - with_lock = True) - + blocking = True, + with_lock = True) + if out.strip() != "": self._home_dir = out.strip() except: trace = traceback.format_exc() - msg = "Impossible to retrieve HOME directory %s" % trace + msg = "Impossible to retrieve HOME directory {}".format(trace) if not self._home_dir: self.error(msg) @@ -1112,17 +1117,17 @@ This might be dangerous when using user root""", """ Removes files that already exist in the Linux host from src list """ # construct a dictionary with { dst: src } - dests = dict(map(lambda s: (os.path.join(dst, os.path.basename(s)), s), src)) \ - if len(src) > 1 else dict({dst: src[0]}) + dests = { os.path.join(dst, os.path.basename(s)) : s for s in src } \ + if len(src) > 1 else {dst: src[0]} command = [] for d in dests.keys(): - command.append(" [ -f %(dst)s ] && echo '%(dst)s' " % {'dst' : d} ) + command.append(" [ -f {dst} ] && echo '{dst}' ".format(dst=d) ) command = ";".join(command) (out, err), proc = self.execute(command, retry = 1, with_lock = True) - + for d in dests.keys(): if out.find(d) > -1: del dests[d]