Added sysinfo support to log pre and post iteration (currently it logs
the contents of /proc/schedstat). Added client.common_lib.test hooks to
call pre and post iteration. Used the hooks in client.bin.test.runtest()
for client tests. Refactored server.test and added wrappers for the
pre/post iteration logging and used them on the new pre/post iteration
hooks.
For each iteration there will be a
resultsdir/sysinfo/iteration.N/schedstat.after and schedstat.before.
If there are tests that override execute() and implement their own
iteration logic they need to be changed over to override run_once()
instead and take advantage of the default execute() that supports the
pre/post iteration hooks and other things.
Signed-off-by: Mihai Rusu <[email protected]>
git-svn-id: http://test.kernel.org/svn/autotest/trunk@2929 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/server/test.py b/server/test.py
index d1eecf9..00e81a7 100755
--- a/server/test.py
+++ b/server/test.py
@@ -12,7 +12,7 @@
pass
-_sysinfo_before_script = """\
+_sysinfo_before_test_script = """\
import pickle
from autotest_lib.client.bin import test
mytest = test.test(job, '', %r)
@@ -22,7 +22,7 @@
job.record('GOOD', '', 'sysinfo.before')
"""
-_sysinfo_after_script = """\
+_sysinfo_after_test_script = """\
import pickle
from autotest_lib.client.bin import test
mytest = test.test(job, '', %r)
@@ -34,6 +34,23 @@
job.record('GOOD', '', 'sysinfo.after')
"""
+# this script is ran after _sysinfo_before_test_script and before
+# _sysinfo_after_test_script which means the pickle file exists
+# already and should be dumped with updated state for
+# _sysinfo_after_test_script to pick it up later
+_sysinfo_iteration_script = """\
+import pickle
+from autotest_lib.client.bin import test
+mytest = test.test(job, '', %r)
+sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
+if os.path.exists(sysinfo_pickle):
+ job.sysinfo = pickle.load(open(sysinfo_pickle))
+ job.sysinfo.__init__(job.resultdir)
+job.sysinfo.%s(mytest, iteration=%d)
+pickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
+job.record('GOOD', '', 'sysinfo.iteration.%s')
+"""
+
class _sysinfo_logger(object):
def __init__(self, job):
@@ -53,38 +70,28 @@
return host, at
- @log.log_and_ignore_errors("pre-test server sysinfo error:")
- def before_hook(self, mytest):
- host, at = self._install()
- outputdir = host.get_tmp_dir()
-
- # run the pre-test sysinfo script
- at.run(_sysinfo_before_script % outputdir,
- results_dir=self.job.resultdir)
-
- # pull back the sysinfo pickle
+ def _pull_pickle(self, host, outputdir):
+ """Pulls from the client the pickle file with the saved sysinfo state.
+ """
fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
os.close(fd)
host.get_file(os.path.join(outputdir, "sysinfo.pickle"), path)
self.pickle = path
- @log.log_and_ignore_errors("post-test server sysinfo error:")
- def after_hook(self, mytest):
- host, at = self._install()
- outputdir = host.get_tmp_dir()
-
- # push the sysinfo pickle out to the remote machine
+ def _push_pickle(self, host, outputdir):
+ """Pushes the server saved sysinfo pickle file to the client.
+ """
if self.pickle:
host.send_file(self.pickle,
os.path.join(outputdir, "sysinfo.pickle"))
os.remove(self.pickle)
self.pickle = None
- # run the post-test sysinfo script
- at.run(_sysinfo_after_script % outputdir,
- results_dir=self.job.resultdir)
+ def _pull_sysinfo_keyval(self, host, outputdir, mytest):
+ """Pulls sysinfo and keyval data from the client.
+ """
# pull the sysinfo data back on to the server
host.get_file(os.path.join(outputdir, "sysinfo"), mytest.outputdir)
@@ -97,10 +104,73 @@
mytest.write_test_keyval(keyval)
+ @log.log_and_ignore_errors("pre-test server sysinfo error:")
+ def before_hook(self, mytest):
+ host, at = self._install()
+ outputdir = host.get_tmp_dir()
+
+ # run the pre-test sysinfo script
+ at.run(_sysinfo_before_test_script % outputdir,
+ results_dir=self.job.resultdir)
+
+ self._pull_pickle(host, outputdir)
+
+
+ @log.log_and_ignore_errors("pre-test iteration server sysinfo error:")
+ def before_iteration_hook(self, mytest):
+ host, at = self._install()
+ outputdir = host.get_tmp_dir()
+
+ # this function is called after before_hook() se we have sysinfo state
+ # to push to the server
+ self._push_pickle(host, outputdir);
+ # run the pre-test iteration sysinfo script
+ at.run(_sysinfo_iteration_script %
+ (outputdir, 'log_before_each_iteration', mytest.iteration,
+ 'before'),
+ results_dir=self.job.resultdir)
+
+ # get the new sysinfo state from the client
+ self._pull_pickle(host, outputdir)
+
+
+ @log.log_and_ignore_errors("post-test iteration server sysinfo error:")
+ def after_iteration_hook(self, mytest):
+ host, at = self._install()
+ outputdir = host.get_tmp_dir()
+
+ # push latest sysinfo state to the client
+ self._push_pickle(host, outputdir);
+ # run the post-test iteration sysinfo script
+ at.run(_sysinfo_iteration_script %
+ (outputdir, 'log_after_each_iteration', mytest.iteration,
+ 'after'),
+ results_dir=self.job.resultdir)
+
+ # get the new sysinfo state from the client
+ self._pull_pickle(host, outputdir)
+ self._pull_sysinfo_keyval(host, outputdir, mytest)
+
+
+ @log.log_and_ignore_errors("post-test server sysinfo error:")
+ def after_hook(self, mytest):
+ host, at = self._install()
+ outputdir = host.get_tmp_dir()
+
+ self._push_pickle(host, outputdir);
+ # run the post-test sysinfo script
+ at.run(_sysinfo_after_test_script % outputdir,
+ results_dir=self.job.resultdir)
+
+ self._pull_sysinfo_keyval(host, outputdir, mytest)
+
+
def runtest(job, url, tag, args, dargs):
if not dargs.pop('disable_sysinfo', False):
logger = _sysinfo_logger(job)
- logging_args = [logger.before_hook, logger.after_hook]
+ logging_args = [logger.before_hook, logger.after_hook,
+ logger.before_iteration_hook,
+ logger.after_iteration_hook]
else:
logging_args = [None, None]
common_test.runtest(job, url, tag, args, dargs, locals(), globals(),