blob: 5a56ba6a467fcf0f644c7498090d4f1d41f7c27c [file] [log] [blame]
mbligh05269362007-10-16 16:58:11 +00001# Copyright Martin J. Bligh, Andy Whitcroft, 2007
2#
mblighea397bb2008-02-02 19:17:51 +00003# Define the server-side test class
mbligh05269362007-10-16 16:58:11 +00004#
mbligh05269362007-10-16 16:58:11 +00005
mbligh089f1e32009-06-22 18:26:45 +00006import os, tempfile, logging
mblighea397bb2008-02-02 19:17:51 +00007
jadmanski54f90af2008-10-10 16:20:55 +00008from autotest_lib.client.common_lib import log, utils, test as common_test
mbligh05269362007-10-16 16:58:11 +00009
10
mblighccb9e182008-04-17 15:42:10 +000011class test(common_test.base_test):
mbligh089f1e32009-06-22 18:26:45 +000012 disable_sysinfo_install_cache = False
mblighdccabe32008-02-01 17:39:32 +000013
14
mbligh4395bbd2009-03-25 19:34:17 +000015_sysinfo_before_test_script = """\
jadmanski54f90af2008-10-10 16:20:55 +000016import pickle
17from autotest_lib.client.bin import test
18mytest = test.test(job, '', %r)
19job.sysinfo.log_before_each_test(mytest)
20sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
21pickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
22job.record('GOOD', '', 'sysinfo.before')
23"""
24
mbligh4395bbd2009-03-25 19:34:17 +000025_sysinfo_after_test_script = """\
jadmanski54f90af2008-10-10 16:20:55 +000026import pickle
27from autotest_lib.client.bin import test
28mytest = test.test(job, '', %r)
29sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
30if os.path.exists(sysinfo_pickle):
31 job.sysinfo = pickle.load(open(sysinfo_pickle))
32 job.sysinfo.__init__(job.resultdir)
33job.sysinfo.log_after_each_test(mytest)
34job.record('GOOD', '', 'sysinfo.after')
35"""
36
mbligh4395bbd2009-03-25 19:34:17 +000037# this script is ran after _sysinfo_before_test_script and before
38# _sysinfo_after_test_script which means the pickle file exists
39# already and should be dumped with updated state for
40# _sysinfo_after_test_script to pick it up later
41_sysinfo_iteration_script = """\
42import pickle
43from autotest_lib.client.bin import test
44mytest = test.test(job, '', %r)
45sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
46if os.path.exists(sysinfo_pickle):
47 job.sysinfo = pickle.load(open(sysinfo_pickle))
48 job.sysinfo.__init__(job.resultdir)
49job.sysinfo.%s(mytest, iteration=%d)
50pickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
51job.record('GOOD', '', 'sysinfo.iteration.%s')
52"""
53
jadmanski54f90af2008-10-10 16:20:55 +000054
jadmanski7c7aff32009-03-25 22:43:07 +000055def install_autotest_and_run(func):
56 def wrapper(self, mytest):
mbligh35245892009-06-08 16:43:21 +000057 host, at, outputdir = self._install()
mbligh089f1e32009-06-22 18:26:45 +000058 try:
59 host.erase_dir_contents(outputdir)
60 func(self, mytest, host, at, outputdir)
61 finally:
62 # the test class can define this flag to make us remove the
63 # sysinfo install files and outputdir contents after each run
64 if mytest.disable_sysinfo_install_cache:
65 self.cleanup(host_close=False)
mbligh35245892009-06-08 16:43:21 +000066
jadmanski7c7aff32009-03-25 22:43:07 +000067 return wrapper
68
69
jadmanski54f90af2008-10-10 16:20:55 +000070class _sysinfo_logger(object):
71 def __init__(self, job):
72 self.job = job
73 self.pickle = None
mbligh35245892009-06-08 16:43:21 +000074
75 # for now support a single host
76 self.host = None
77 self.autotest = None
78 self.outputdir = None
79
jadmanski54f90af2008-10-10 16:20:55 +000080 if len(job.machines) != 1:
81 # disable logging on multi-machine tests
82 self.before_hook = self.after_hook = None
mbligh35245892009-06-08 16:43:21 +000083 self.before_iteration_hook = self.after_iteration_hook = None
jadmanski54f90af2008-10-10 16:20:55 +000084
85
86 def _install(self):
mbligh35245892009-06-08 16:43:21 +000087 if not self.host:
88 from autotest_lib.server import hosts, autotest
89 self.host = hosts.create_host(self.job.machines[0],
90 auto_monitor=False)
91 tmp_dir = self.host.get_tmp_dir(parent="/tmp/sysinfo")
92 self.autotest = autotest.Autotest(self.host)
93 self.autotest.install_base(autodir=tmp_dir)
94 self.outputdir = self.host.get_tmp_dir()
mbligh089f1e32009-06-22 18:26:45 +000095 else:
96 host = self.host
97
98 # if autotest client dir does not exist, reinstall (it may have
99 # been removed by the test code)
100 autodir = host.get_autodir()
101 if not autodir or not host.path_exists(autodir):
102 self.autotest.install_base(autodir=autodir)
103
104 # if the output dir does not exist, recreate it
105 if not host.path_exists(self.outputdir):
106 host.run('mkdir -p %s' % self.outputdir)
mbligh35245892009-06-08 16:43:21 +0000107
108 return self.host, self.autotest, self.outputdir
jadmanski54f90af2008-10-10 16:20:55 +0000109
110
mbligh4395bbd2009-03-25 19:34:17 +0000111 def _pull_pickle(self, host, outputdir):
112 """Pulls from the client the pickle file with the saved sysinfo state.
113 """
jadmanski54f90af2008-10-10 16:20:55 +0000114 fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
115 os.close(fd)
116 host.get_file(os.path.join(outputdir, "sysinfo.pickle"), path)
117 self.pickle = path
118
119
mbligh4395bbd2009-03-25 19:34:17 +0000120 def _push_pickle(self, host, outputdir):
121 """Pushes the server saved sysinfo pickle file to the client.
122 """
jadmanski54f90af2008-10-10 16:20:55 +0000123 if self.pickle:
124 host.send_file(self.pickle,
125 os.path.join(outputdir, "sysinfo.pickle"))
126 os.remove(self.pickle)
127 self.pickle = None
128
jadmanski54f90af2008-10-10 16:20:55 +0000129
mbligh4395bbd2009-03-25 19:34:17 +0000130 def _pull_sysinfo_keyval(self, host, outputdir, mytest):
131 """Pulls sysinfo and keyval data from the client.
132 """
jadmanski54f90af2008-10-10 16:20:55 +0000133 # pull the sysinfo data back on to the server
134 host.get_file(os.path.join(outputdir, "sysinfo"), mytest.outputdir)
135
136 # pull the keyval data back into the local one
137 fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
138 os.close(fd)
139 host.get_file(os.path.join(outputdir, "keyval"), path)
140 keyval = utils.read_keyval(path)
141 os.remove(path)
142 mytest.write_test_keyval(keyval)
143
144
mbligh4395bbd2009-03-25 19:34:17 +0000145 @log.log_and_ignore_errors("pre-test server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000146 @install_autotest_and_run
147 def before_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000148 # run the pre-test sysinfo script
149 at.run(_sysinfo_before_test_script % outputdir,
150 results_dir=self.job.resultdir)
151
152 self._pull_pickle(host, outputdir)
153
154
155 @log.log_and_ignore_errors("pre-test iteration server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000156 @install_autotest_and_run
157 def before_iteration_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000158 # this function is called after before_hook() se we have sysinfo state
159 # to push to the server
160 self._push_pickle(host, outputdir);
161 # run the pre-test iteration sysinfo script
162 at.run(_sysinfo_iteration_script %
163 (outputdir, 'log_before_each_iteration', mytest.iteration,
164 'before'),
165 results_dir=self.job.resultdir)
166
167 # get the new sysinfo state from the client
168 self._pull_pickle(host, outputdir)
169
170
171 @log.log_and_ignore_errors("post-test iteration server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000172 @install_autotest_and_run
173 def after_iteration_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000174 # push latest sysinfo state to the client
175 self._push_pickle(host, outputdir);
176 # run the post-test iteration sysinfo script
177 at.run(_sysinfo_iteration_script %
178 (outputdir, 'log_after_each_iteration', mytest.iteration,
179 'after'),
180 results_dir=self.job.resultdir)
181
182 # get the new sysinfo state from the client
183 self._pull_pickle(host, outputdir)
184 self._pull_sysinfo_keyval(host, outputdir, mytest)
185
186
187 @log.log_and_ignore_errors("post-test server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000188 @install_autotest_and_run
189 def after_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000190 self._push_pickle(host, outputdir);
191 # run the post-test sysinfo script
192 at.run(_sysinfo_after_test_script % outputdir,
193 results_dir=self.job.resultdir)
194
195 self._pull_sysinfo_keyval(host, outputdir, mytest)
196
197
mbligh089f1e32009-06-22 18:26:45 +0000198 def cleanup(self, host_close=True):
mbligh35245892009-06-08 16:43:21 +0000199 if self.host and self.autotest:
200 try:
mbligh089f1e32009-06-22 18:26:45 +0000201 try:
202 self.autotest.uninstall()
203 finally:
204 if host_close:
205 self.host.close()
206 else:
207 self.host.erase_dir_contents(self.outputdir)
208
209 except Exception:
210 # ignoring exceptions here so that we don't hide the true
211 # reason of failure from runtest
212 logging.exception('Error cleaning up the sysinfo autotest/host '
213 'objects, ignoring it')
mbligh35245892009-06-08 16:43:21 +0000214
215
mbligh05269362007-10-16 16:58:11 +0000216def runtest(job, url, tag, args, dargs):
mbligh79a2ee12008-11-05 22:07:38 +0000217 if not dargs.pop('disable_sysinfo', False):
218 logger = _sysinfo_logger(job)
mbligh4395bbd2009-03-25 19:34:17 +0000219 logging_args = [logger.before_hook, logger.after_hook,
220 logger.before_iteration_hook,
221 logger.after_iteration_hook]
mbligh79a2ee12008-11-05 22:07:38 +0000222 else:
mbligh35245892009-06-08 16:43:21 +0000223 logger = None
224 logging_args = [None, None, None, None]
225
226 try:
227 common_test.runtest(job, url, tag, args, dargs, locals(), globals(),
228 *logging_args)
229 finally:
230 if logger:
231 logger.cleanup()