blob: 8fdba9d7c40addf23e139b060f558e17bb34e40b [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
mbligh43dd5492009-09-03 20:20:51 +000013 host_parameter = None
mblighdccabe32008-02-01 17:39:32 +000014
15
mbligh4395bbd2009-03-25 19:34:17 +000016_sysinfo_before_test_script = """\
jadmanski54f90af2008-10-10 16:20:55 +000017import pickle
18from autotest_lib.client.bin import test
19mytest = test.test(job, '', %r)
20job.sysinfo.log_before_each_test(mytest)
21sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
22pickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
23job.record('GOOD', '', 'sysinfo.before')
24"""
25
mbligh4395bbd2009-03-25 19:34:17 +000026_sysinfo_after_test_script = """\
jadmanski54f90af2008-10-10 16:20:55 +000027import pickle
28from autotest_lib.client.bin import test
29mytest = test.test(job, '', %r)
30sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
31if os.path.exists(sysinfo_pickle):
32 job.sysinfo = pickle.load(open(sysinfo_pickle))
33 job.sysinfo.__init__(job.resultdir)
34job.sysinfo.log_after_each_test(mytest)
35job.record('GOOD', '', 'sysinfo.after')
36"""
37
mbligh4395bbd2009-03-25 19:34:17 +000038# this script is ran after _sysinfo_before_test_script and before
39# _sysinfo_after_test_script which means the pickle file exists
40# already and should be dumped with updated state for
41# _sysinfo_after_test_script to pick it up later
42_sysinfo_iteration_script = """\
43import pickle
44from autotest_lib.client.bin import test
45mytest = test.test(job, '', %r)
46sysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
47if os.path.exists(sysinfo_pickle):
48 job.sysinfo = pickle.load(open(sysinfo_pickle))
49 job.sysinfo.__init__(job.resultdir)
50job.sysinfo.%s(mytest, iteration=%d)
51pickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
52job.record('GOOD', '', 'sysinfo.iteration.%s')
53"""
54
jadmanski54f90af2008-10-10 16:20:55 +000055
jadmanski7c7aff32009-03-25 22:43:07 +000056def install_autotest_and_run(func):
57 def wrapper(self, mytest):
mbligh35245892009-06-08 16:43:21 +000058 host, at, outputdir = self._install()
mbligh089f1e32009-06-22 18:26:45 +000059 try:
60 host.erase_dir_contents(outputdir)
61 func(self, mytest, host, at, outputdir)
62 finally:
63 # the test class can define this flag to make us remove the
64 # sysinfo install files and outputdir contents after each run
65 if mytest.disable_sysinfo_install_cache:
66 self.cleanup(host_close=False)
mbligh35245892009-06-08 16:43:21 +000067
jadmanski7c7aff32009-03-25 22:43:07 +000068 return wrapper
69
70
jadmanski54f90af2008-10-10 16:20:55 +000071class _sysinfo_logger(object):
72 def __init__(self, job):
73 self.job = job
74 self.pickle = None
mbligh35245892009-06-08 16:43:21 +000075
76 # for now support a single host
77 self.host = None
78 self.autotest = None
79 self.outputdir = None
80
jadmanski54f90af2008-10-10 16:20:55 +000081 if len(job.machines) != 1:
82 # disable logging on multi-machine tests
83 self.before_hook = self.after_hook = None
mbligh35245892009-06-08 16:43:21 +000084 self.before_iteration_hook = self.after_iteration_hook = None
jadmanski54f90af2008-10-10 16:20:55 +000085
86
87 def _install(self):
mbligh35245892009-06-08 16:43:21 +000088 if not self.host:
89 from autotest_lib.server import hosts, autotest
90 self.host = hosts.create_host(self.job.machines[0],
91 auto_monitor=False)
mblighf780bbf2009-09-03 20:45:46 +000092 try:
Dale Curtis74a314b2011-06-23 14:55:46 -070093 tmp_dir = self.host.get_tmp_dir(parent="/tmp/sysinfo")
mblighf780bbf2009-09-03 20:45:46 +000094 self.autotest = autotest.Autotest(self.host)
Dale Curtis74a314b2011-06-23 14:55:46 -070095 self.autotest.install(autodir=tmp_dir)
mblighf780bbf2009-09-03 20:45:46 +000096 self.outputdir = self.host.get_tmp_dir()
97 except:
98 # if installation fails roll back the host
99 try:
100 self.host.close()
101 except:
102 logging.exception("Unable to close host %s",
103 self.host.hostname)
104 self.host = None
105 self.autotest = None
106 raise
mbligh089f1e32009-06-22 18:26:45 +0000107 else:
108 host = self.host
109
110 # if autotest client dir does not exist, reinstall (it may have
111 # been removed by the test code)
112 autodir = host.get_autodir()
113 if not autodir or not host.path_exists(autodir):
jadmanski27b52912009-08-14 17:09:15 +0000114 self.autotest.install(autodir=autodir)
mbligh089f1e32009-06-22 18:26:45 +0000115
116 # if the output dir does not exist, recreate it
117 if not host.path_exists(self.outputdir):
118 host.run('mkdir -p %s' % self.outputdir)
mbligh35245892009-06-08 16:43:21 +0000119
120 return self.host, self.autotest, self.outputdir
jadmanski54f90af2008-10-10 16:20:55 +0000121
122
mbligh4395bbd2009-03-25 19:34:17 +0000123 def _pull_pickle(self, host, outputdir):
124 """Pulls from the client the pickle file with the saved sysinfo state.
125 """
jadmanski54f90af2008-10-10 16:20:55 +0000126 fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
127 os.close(fd)
128 host.get_file(os.path.join(outputdir, "sysinfo.pickle"), path)
129 self.pickle = path
130
131
mbligh4395bbd2009-03-25 19:34:17 +0000132 def _push_pickle(self, host, outputdir):
133 """Pushes the server saved sysinfo pickle file to the client.
134 """
jadmanski54f90af2008-10-10 16:20:55 +0000135 if self.pickle:
136 host.send_file(self.pickle,
137 os.path.join(outputdir, "sysinfo.pickle"))
138 os.remove(self.pickle)
139 self.pickle = None
140
jadmanski54f90af2008-10-10 16:20:55 +0000141
mbligh4395bbd2009-03-25 19:34:17 +0000142 def _pull_sysinfo_keyval(self, host, outputdir, mytest):
143 """Pulls sysinfo and keyval data from the client.
144 """
jadmanski54f90af2008-10-10 16:20:55 +0000145 # pull the sysinfo data back on to the server
146 host.get_file(os.path.join(outputdir, "sysinfo"), mytest.outputdir)
147
148 # pull the keyval data back into the local one
149 fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
150 os.close(fd)
151 host.get_file(os.path.join(outputdir, "keyval"), path)
152 keyval = utils.read_keyval(path)
153 os.remove(path)
154 mytest.write_test_keyval(keyval)
155
156
mbligh4395bbd2009-03-25 19:34:17 +0000157 @log.log_and_ignore_errors("pre-test server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000158 @install_autotest_and_run
159 def before_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000160 # run the pre-test sysinfo script
161 at.run(_sysinfo_before_test_script % outputdir,
Dale Curtis9285ddf2011-01-05 11:47:24 -0800162 results_dir=self.job.resultdir)
mbligh4395bbd2009-03-25 19:34:17 +0000163
164 self._pull_pickle(host, outputdir)
165
166
167 @log.log_and_ignore_errors("pre-test iteration server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000168 @install_autotest_and_run
169 def before_iteration_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000170 # this function is called after before_hook() se we have sysinfo state
171 # to push to the server
172 self._push_pickle(host, outputdir);
173 # run the pre-test iteration sysinfo script
174 at.run(_sysinfo_iteration_script %
175 (outputdir, 'log_before_each_iteration', mytest.iteration,
176 'before'),
Dale Curtis9285ddf2011-01-05 11:47:24 -0800177 results_dir=self.job.resultdir)
mbligh4395bbd2009-03-25 19:34:17 +0000178
179 # get the new sysinfo state from the client
180 self._pull_pickle(host, outputdir)
181
182
183 @log.log_and_ignore_errors("post-test iteration server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000184 @install_autotest_and_run
185 def after_iteration_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000186 # push latest sysinfo state to the client
187 self._push_pickle(host, outputdir);
188 # run the post-test iteration sysinfo script
189 at.run(_sysinfo_iteration_script %
190 (outputdir, 'log_after_each_iteration', mytest.iteration,
191 'after'),
Dale Curtis9285ddf2011-01-05 11:47:24 -0800192 results_dir=self.job.resultdir)
mbligh4395bbd2009-03-25 19:34:17 +0000193
194 # get the new sysinfo state from the client
195 self._pull_pickle(host, outputdir)
mbligh4395bbd2009-03-25 19:34:17 +0000196
197
198 @log.log_and_ignore_errors("post-test server sysinfo error:")
jadmanski7c7aff32009-03-25 22:43:07 +0000199 @install_autotest_and_run
200 def after_hook(self, mytest, host, at, outputdir):
mbligh4395bbd2009-03-25 19:34:17 +0000201 self._push_pickle(host, outputdir);
202 # run the post-test sysinfo script
203 at.run(_sysinfo_after_test_script % outputdir,
Dale Curtis9285ddf2011-01-05 11:47:24 -0800204 results_dir=self.job.resultdir)
mbligh4395bbd2009-03-25 19:34:17 +0000205
206 self._pull_sysinfo_keyval(host, outputdir, mytest)
207
208
mbligh089f1e32009-06-22 18:26:45 +0000209 def cleanup(self, host_close=True):
mbligh35245892009-06-08 16:43:21 +0000210 if self.host and self.autotest:
211 try:
mbligh089f1e32009-06-22 18:26:45 +0000212 try:
213 self.autotest.uninstall()
214 finally:
215 if host_close:
216 self.host.close()
217 else:
218 self.host.erase_dir_contents(self.outputdir)
219
220 except Exception:
221 # ignoring exceptions here so that we don't hide the true
222 # reason of failure from runtest
223 logging.exception('Error cleaning up the sysinfo autotest/host '
224 'objects, ignoring it')
mbligh35245892009-06-08 16:43:21 +0000225
226
mbligh05269362007-10-16 16:58:11 +0000227def runtest(job, url, tag, args, dargs):
mbligh79a2ee12008-11-05 22:07:38 +0000228 if not dargs.pop('disable_sysinfo', False):
229 logger = _sysinfo_logger(job)
mbligh4395bbd2009-03-25 19:34:17 +0000230 logging_args = [logger.before_hook, logger.after_hook,
231 logger.before_iteration_hook,
232 logger.after_iteration_hook]
mbligh79a2ee12008-11-05 22:07:38 +0000233 else:
mbligh35245892009-06-08 16:43:21 +0000234 logger = None
235 logging_args = [None, None, None, None]
236
mbligh43dd5492009-09-03 20:20:51 +0000237 # add in a hook that calls host.log_kernel if we can
238 def log_kernel_hook(mytest, existing_hook=logging_args[0]):
239 if mytest.host_parameter:
240 host = dargs[mytest.host_parameter]
241 if host:
242 host.log_kernel()
243 # chain this call with any existing hook
244 if existing_hook:
245 existing_hook(mytest)
246 logging_args[0] = log_kernel_hook
247
mbligh35245892009-06-08 16:43:21 +0000248 try:
249 common_test.runtest(job, url, tag, args, dargs, locals(), globals(),
250 *logging_args)
251 finally:
252 if logger:
253 logger.cleanup()