* make utils.system* default to directing output to the logging module, instead of sys.std*. this involved refactoring the code out of ssh_host/paramiko_host/abstrash_ssh, which previously did the same thing (they still do, but now the use the common logic in utils)
* change packages.py to suppress command output properly. it was using the verbose option previously, which was added to ssh_host.run() and paramiko_host.run() specifically for this call site. in this context, verbose=False meant "dont print the command and dont print the output either). but this doesn't make the interface of utils.run(), for which verbose=False just means "dont print the command", because utils.run() suppresses output by default (while *host.run() doesn't). to resolve that, i made verbose on *host.run() match the interface of utils.run(), and i made packages.py suppress the output properly by passing stdout_tee=None.
* move tee.flush() calls in utils.BgJob code to where it makes more sense (and interacts with LoggingFiles better)
Signed-off-by: Steve Howard <showard@google.com>
git-svn-id: http://test.kernel.org/svn/autotest/trunk@3307 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/client/common_lib/utils.py b/client/common_lib/utils.py
index 93617ed..eca81f2 100644
--- a/client/common_lib/utils.py
+++ b/client/common_lib/utils.py
@@ -5,7 +5,7 @@
import os, pickle, random, re, resource, select, shutil, signal, StringIO
import socket, struct, subprocess, sys, time, textwrap, urllib, urlparse
import warnings, smtplib, logging, urllib2
-from autotest_lib.client.common_lib import error, barrier
+from autotest_lib.client.common_lib import error, barrier, logging_manager
def deprecated(func):
"""This is a decorator which can be used to mark functions as deprecated.
@@ -20,12 +20,32 @@
return new_func
+class _NullStream(object):
+ def write(self, data):
+ pass
+
+
+ def flush(self):
+ pass
+
+
+TEE_TO_LOGS = object()
+_the_null_stream = _NullStream()
+
+def get_stream_tee_file(stream, level):
+ if stream is None:
+ return _the_null_stream
+ if stream is TEE_TO_LOGS:
+ return logging_manager.LoggingFile(level=level)
+ return stream
+
+
class BgJob(object):
def __init__(self, command, stdout_tee=None, stderr_tee=None, verbose=True,
stdin=None):
self.command = command
- self.stdout_tee = stdout_tee
- self.stderr_tee = stderr_tee
+ self.stdout_tee = get_stream_tee_file(stdout_tee, logging.DEBUG)
+ self.stderr_tee = get_stream_tee_file(stderr_tee, logging.ERROR)
self.result = CmdResult(command)
if verbose:
logging.debug("Running '%s'" % command)
@@ -60,12 +80,12 @@
# perform a single read
data = os.read(pipe.fileno(), 1024)
buf.write(data)
- if tee:
- tee.write(data)
- tee.flush()
+ tee.write(data)
def cleanup(self):
+ self.stdout_tee.flush()
+ self.stderr_tee.flush()
self.sp.stdout.close()
self.sp.stderr.close()
self.result.stdout = self.stdout_file.getvalue()
@@ -325,6 +345,7 @@
will be written as it is generated (data will still
be stored in result.stdout)
stderr_tee: likewise for stderr
+ verbose: if True, log the command being run
stdin: stdin to pass to the executed process
Returns:
@@ -527,7 +548,7 @@
def system(command, timeout=None, ignore_status=False):
"""This function returns the exit status of command."""
return run(command, timeout=timeout, ignore_status=ignore_status,
- stdout_tee=sys.stdout, stderr_tee=sys.stderr).exit_status
+ stdout_tee=TEE_TO_LOGS, stderr_tee=TEE_TO_LOGS).exit_status
def system_parallel(commands, timeout=None, ignore_status=False):
@@ -535,14 +556,14 @@
list of commands."""
return [bg_jobs.exit_status for bg_jobs in
run_parallel(commands, timeout=timeout, ignore_status=ignore_status,
- stdout_tee=sys.stdout, stderr_tee=sys.stderr)]
+ stdout_tee=TEE_TO_LOGS, stderr_tee=TEE_TO_LOGS)]
def system_output(command, timeout=None, ignore_status=False,
retain_output=False):
if retain_output:
out = run(command, timeout=timeout, ignore_status=ignore_status,
- stdout_tee=sys.stdout, stderr_tee=sys.stderr).stdout
+ stdout_tee=TEE_TO_LOGS, stderr_tee=TEE_TO_LOGS).stdout
else:
out = run(command, timeout=timeout, ignore_status=ignore_status).stdout
if out[-1:] == '\n': out = out[:-1]
@@ -552,9 +573,10 @@
def system_output_parallel(commands, timeout=None, ignore_status=False,
retain_output=False):
if retain_output:
- out = [bg_job.stdout for bg_job in run_parallel(commands,
- timeout=timeout, ignore_status=ignore_status,
- stdout_tee=sys.stdout, stderr_tee=sys.stderr)]
+ out = [bg_job.stdout for bg_job
+ in run_parallel(commands, timeout=timeout,
+ ignore_status=ignore_status,
+ stdout_tee=TEE_TO_LOGS, stderr_tee=TEE_TO_LOGS)]
else:
out = [bg_job.stdout for bg_job in run_parallel(commands,
timeout=timeout, ignore_status=ignore_status)]