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(),