#
# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
+import os
+import subprocess
+import logging
+
from nepi.execution.attribute import Attribute, Flags, Types
from nepi.execution.trace import Trace, TraceAttr
from nepi.execution.resource import ResourceManager, clsinit_copy, \
ResourceState
from nepi.resources.linux.node import LinuxNode
-from nepi.util.sshfuncs import ProcStatus
+from nepi.util.sshfuncs import ProcStatus, STDOUT
from nepi.util.timefuncs import tnow, tdiffsec
-import os
-import subprocess
+# to debug, just use
+# logging.getLogger('application').setLevel(logging.DEBUG)
+logger = logging.getLogger("application")
# TODO: Resolve wildcards in commands!!
# TODO: When a failure occurs during deployment, scp and ssh processes are left running behind!!
Attribute("tearDown",
"Command to be executed just before releasing the resource",
flags = Flags.Design))
+ cls._register_attribute(
+ Attribute("splitStderr",
+ "requests stderr to be retrieved separately",
+ default = False))
@classmethod
def _register_traces(cls):
- stdout = Trace("stdout", "Standard output stream", enabled = True)
- stderr = Trace("stderr", "Standard error stream", enabled = True)
-
- cls._register_trace(stdout)
- cls._register_trace(stderr)
+ cls._register_trace(
+ Trace("stdout", "Standard output stream", enabled = True))
+ cls._register_trace(
+ Trace("stderr", "Standard error stream", enabled = True))
def __init__(self, ec, guid):
super(LinuxApplication, self).__init__(ec, guid)
self.info("Retrieving '{}' trace {} ".format(name, attr))
path = self.trace_filepath(name)
+ logger.debug("trace: path= {}".format(path))
command = "(test -f {} && echo 'success') || echo 'error'".format(path)
(out, err), proc = self.node.execute(command)
# in background ( but wait until the command has
# finished to continue )
shfile = os.path.join(self.app_home, "{}.sh".format(prefix))
+ # low-level spawn tools in both sshfuncs and execfuncs
+ # expect stderr=sshfuncs.STDOUT to mean std{out,err} are merged
+ stderr = "{}_stderr".format(prefix) \
+ if self.get("splitStderr") \
+ else STDOUT
+ print("{} : prefix = {}, command={}, stderr={}"
+ .format(self, prefix, command, stderr))
self.node.run_and_wait(command, self.run_home,
shfile = shfile,
overwrite = False,
pidfile = "{}_pidfile".format(prefix),
ecodefile = "{}_exitcode".format(prefix),
stdout = "{}_stdout".format(prefix),
- stderr = "{}_stderr".format(prefix))
+ stderr = stderr)
def upload_sources(self, sources = None, src_dir = None):
if not sources:
sudo = self.get("sudo") or False
stdout = "stdout"
- stderr = "stderr"
+ # low-level spawn tools in both sshfuncs and execfuncs
+ # expect stderr=sshfuncs.STDOUT to mean std{out,err} are merged
+ stderr = "stderr" \
+ if self.get("splitStderr") \
+ else STDOUT
stdin = os.path.join(self.app_home, "stdin") if self.get("stdin") \
else None
= self.node.check_errors(self.run_home)
if err:
- msg = "Failed to execute command '{}'"\
- .format(self.get("command"))
- self.error(msg, out, err)
- self.do_fail()
+ # Thierry : there's nothing wrong with a non-empty
+ # stderr, is there ?
+ #msg = "Failed to execute command '{}'"\
+ # .format(self.get("command"))
+ #self.error(msg, out, err)
+ #self.do_fail()
+ # xxx TODO OTOH it would definitely make sense
+ # to check the exitcode
+ pass
else:
self.set_stopped()