105269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh# Copyright Martin J. Bligh, Andy Whitcroft, 2007
205269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh#
3ea397bbc85f1a3eda39c9f2ef4fc209b4ff336f4mbligh# Define the server-side test class
405269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh#
5e8ce6542fee3a701b72267766ffb03011847a65cXixuan Wu# pylint: disable=missing-docstring
605269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh
75019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wuimport logging
85019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wuimport os
95019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wuimport tempfile
10ea397bbc85f1a3eda39c9f2ef4fc209b4ff336f4mbligh
115019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wufrom autotest_lib.client.common_lib import log
125019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wufrom autotest_lib.client.common_lib import test as common_test
135019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wufrom autotest_lib.client.common_lib import utils
1405269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh
1505269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh
16ccb9e18237137e547fc0f815506710a8b1d94453mblighclass test(common_test.base_test):
17089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh    disable_sysinfo_install_cache = False
1843dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh    host_parameter = None
1905269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh
2005269369a9bbfee9481ce8b03b88f7abce4bad7bmbligh
214395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh_sysinfo_before_test_script = """\
2254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskiimport pickle
2354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskifrom autotest_lib.client.bin import test
2454f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskimytest = test.test(job, '', %r)
2554f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskijob.sysinfo.log_before_each_test(mytest)
2654f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskisysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
2754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskipickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
2854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskijob.record('GOOD', '', 'sysinfo.before')
2954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski"""
3054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
314395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh_sysinfo_after_test_script = """\
3254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskiimport pickle
3354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskifrom autotest_lib.client.bin import test
3454f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskimytest = test.test(job, '', %r)
354eba9f0d9fdac5dc3a57663a42ffadd559da4655Dan Shi# success is passed in so diffable_logdir can decide if or not to collect
364eba9f0d9fdac5dc3a57663a42ffadd559da4655Dan Shi# full log content.
374eba9f0d9fdac5dc3a57663a42ffadd559da4655Dan Shimytest.success = %s
3854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskisysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
3954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskiif os.path.exists(sysinfo_pickle):
4054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski    job.sysinfo = pickle.load(open(sysinfo_pickle))
4154f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski    job.sysinfo.__init__(job.resultdir)
4254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskijob.sysinfo.log_after_each_test(mytest)
4354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskijob.record('GOOD', '', 'sysinfo.after')
4454f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski"""
4554f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
464395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh# this script is ran after _sysinfo_before_test_script and before
474395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh# _sysinfo_after_test_script which means the pickle file exists
484395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh# already and should be dumped with updated state for
494395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh# _sysinfo_after_test_script to pick it up later
504395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh_sysinfo_iteration_script = """\
514395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighimport pickle
524395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighfrom autotest_lib.client.bin import test
534395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighmytest = test.test(job, '', %r)
544395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighsysinfo_pickle = os.path.join(mytest.outputdir, 'sysinfo.pickle')
554395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighif os.path.exists(sysinfo_pickle):
564395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    job.sysinfo = pickle.load(open(sysinfo_pickle))
574395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    job.sysinfo.__init__(job.resultdir)
584395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighjob.sysinfo.%s(mytest, iteration=%d)
594395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighpickle.dump(job.sysinfo, open(sysinfo_pickle, 'w'))
604395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmblighjob.record('GOOD', '', 'sysinfo.iteration.%s')
614395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh"""
624395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
6354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
647c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanskidef install_autotest_and_run(func):
657c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    def wrapper(self, mytest):
663524589241ead1fcbc3b9e7f31648850463d01admbligh        host, at, outputdir = self._install()
677093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng        # TODO(kevcheng): remove when host client install is supported for
687093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng        # ADBHost. crbug.com/543702
697093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng        if not host.is_client_install_supported:
707093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            logging.debug('host client install not supported, skipping %s:',
717093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng                          func.__name__)
727093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            return
737093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng
74089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh        try:
75089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            host.erase_dir_contents(outputdir)
76089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            func(self, mytest, host, at, outputdir)
77089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh        finally:
78089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            # the test class can define this flag to make us remove the
79089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            # sysinfo install files and outputdir contents after each run
80089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            if mytest.disable_sysinfo_install_cache:
81089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                self.cleanup(host_close=False)
823524589241ead1fcbc3b9e7f31648850463d01admbligh
837c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    return wrapper
847c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski
857c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski
8654f90af69daac8a781678f0ccd42d6728d5d81d1jadmanskiclass _sysinfo_logger(object):
8754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski    def __init__(self, job):
8854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        self.job = job
8954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        self.pickle = None
903524589241ead1fcbc3b9e7f31648850463d01admbligh
913524589241ead1fcbc3b9e7f31648850463d01admbligh        # for now support a single host
923524589241ead1fcbc3b9e7f31648850463d01admbligh        self.host = None
933524589241ead1fcbc3b9e7f31648850463d01admbligh        self.autotest = None
943524589241ead1fcbc3b9e7f31648850463d01admbligh        self.outputdir = None
953524589241ead1fcbc3b9e7f31648850463d01admbligh
9654f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        if len(job.machines) != 1:
9754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski            # disable logging on multi-machine tests
9854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski            self.before_hook = self.after_hook = None
993524589241ead1fcbc3b9e7f31648850463d01admbligh            self.before_iteration_hook = self.after_iteration_hook = None
10054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
10154f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
10254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski    def _install(self):
1033524589241ead1fcbc3b9e7f31648850463d01admbligh        if not self.host:
1043524589241ead1fcbc3b9e7f31648850463d01admbligh            from autotest_lib.server import hosts, autotest
105d7f1242be09c5f889641af4783f26e3a470bae1dDan Shi            self.host = hosts.create_target_machine(
106d7f1242be09c5f889641af4783f26e3a470bae1dDan Shi                    self.job.machine_dict_list[0])
1077093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            # TODO(kevcheng): remove when host client install is supported for
1087093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            # ADBHost. crbug.com/543702
1097093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            if not self.host.is_client_install_supported:
1107093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng                return self.host, None, None
111f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh            try:
11274a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                tmp_dir = self.host.get_tmp_dir(parent="/tmp/sysinfo")
113f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                self.autotest = autotest.Autotest(self.host)
11474a314b490ff542c4dd2ae4aa0d11c6394d92960Dale Curtis                self.autotest.install(autodir=tmp_dir)
115f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                self.outputdir = self.host.get_tmp_dir()
116f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh            except:
117f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                # if installation fails roll back the host
118f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                try:
119f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                    self.host.close()
120f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                except:
121f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                    logging.exception("Unable to close host %s",
122f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                                      self.host.hostname)
123f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                self.host = None
124f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                self.autotest = None
125f780bbfa740b0706cec4e7bf42747cda5d457da9mbligh                raise
126089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh        else:
1277093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            # TODO(kevcheng): remove when host client install is supported for
1287093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            # ADBHost. crbug.com/543702
1297093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            if not self.host.is_client_install_supported:
1307093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng                return self.host, None, None
131089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh
132089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            # if autotest client dir does not exist, reinstall (it may have
133089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            # been removed by the test code)
1347093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            autodir = self.host.get_autodir()
1357093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            if not autodir or not self.host.path_exists(autodir):
13627b529165c63274395ff1d207e346201cea4cb25jadmanski                self.autotest.install(autodir=autodir)
137089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh
138089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            # if the output dir does not exist, recreate it
1397093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng            if not self.host.path_exists(self.outputdir):
1407093669cc7037b0d7c03c5097065bd86a02e721eKevin Cheng                self.host.run('mkdir -p %s' % self.outputdir)
1413524589241ead1fcbc3b9e7f31648850463d01admbligh
1423524589241ead1fcbc3b9e7f31648850463d01admbligh        return self.host, self.autotest, self.outputdir
14354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
14454f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
1454395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    def _pull_pickle(self, host, outputdir):
1464395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        """Pulls from the client the pickle file with the saved sysinfo state.
1474395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        """
14854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
14954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        os.close(fd)
15054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        host.get_file(os.path.join(outputdir, "sysinfo.pickle"), path)
15154f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        self.pickle = path
15254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
15354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
1544395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    def _push_pickle(self, host, outputdir):
1554395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        """Pushes the server saved sysinfo pickle file to the client.
1564395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        """
15754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        if self.pickle:
15854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski            host.send_file(self.pickle,
15954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski                           os.path.join(outputdir, "sysinfo.pickle"))
16054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski            os.remove(self.pickle)
16154f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski            self.pickle = None
16254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
16354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
1644395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    def _pull_sysinfo_keyval(self, host, outputdir, mytest):
1654395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        """Pulls sysinfo and keyval data from the client.
1664395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        """
16754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        # pull the sysinfo data back on to the server
16854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        host.get_file(os.path.join(outputdir, "sysinfo"), mytest.outputdir)
16954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
17054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        # pull the keyval data back into the local one
17154f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        fd, path = tempfile.mkstemp(dir=self.job.tmpdir)
17254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        os.close(fd)
17354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        host.get_file(os.path.join(outputdir, "keyval"), path)
17454f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        keyval = utils.read_keyval(path)
17554f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        os.remove(path)
17654f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski        mytest.write_test_keyval(keyval)
17754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
17854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski
1794395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    @log.log_and_ignore_errors("pre-test server sysinfo error:")
1807c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    @install_autotest_and_run
1817c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    def before_hook(self, mytest, host, at, outputdir):
1824395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # run the pre-test sysinfo script
1834395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        at.run(_sysinfo_before_test_script % outputdir,
1849285ddf562c698fda569390be6763170215663d7Dale Curtis               results_dir=self.job.resultdir)
1854395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
1864395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._pull_pickle(host, outputdir)
1874395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
1884395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
1894395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    @log.log_and_ignore_errors("pre-test iteration server sysinfo error:")
1907c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    @install_autotest_and_run
1917c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    def before_iteration_hook(self, mytest, host, at, outputdir):
1924395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # this function is called after before_hook() se we have sysinfo state
1934395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # to push to the server
1944395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._push_pickle(host, outputdir);
1954395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # run the pre-test iteration sysinfo script
1964395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        at.run(_sysinfo_iteration_script %
1974395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh               (outputdir, 'log_before_each_iteration', mytest.iteration,
1984395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh                'before'),
1999285ddf562c698fda569390be6763170215663d7Dale Curtis               results_dir=self.job.resultdir)
2004395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2014395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # get the new sysinfo state from the client
2024395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._pull_pickle(host, outputdir)
2034395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2044395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2054395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    @log.log_and_ignore_errors("post-test iteration server sysinfo error:")
2067c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    @install_autotest_and_run
2077c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    def after_iteration_hook(self, mytest, host, at, outputdir):
2084395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # push latest sysinfo state to the client
2094395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._push_pickle(host, outputdir);
2104395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # run the post-test iteration sysinfo script
2114395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        at.run(_sysinfo_iteration_script %
2124395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh               (outputdir, 'log_after_each_iteration', mytest.iteration,
2134395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh                'after'),
2149285ddf562c698fda569390be6763170215663d7Dale Curtis               results_dir=self.job.resultdir)
2154395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2164395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # get the new sysinfo state from the client
2174395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._pull_pickle(host, outputdir)
2184395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2194395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2204395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh    @log.log_and_ignore_errors("post-test server sysinfo error:")
2217c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    @install_autotest_and_run
2227c7aff3a2ed5787d502642a3f5eaa0107aad1661jadmanski    def after_hook(self, mytest, host, at, outputdir):
2234395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._push_pickle(host, outputdir);
2244395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        # run the post-test sysinfo script
2254eba9f0d9fdac5dc3a57663a42ffadd559da4655Dan Shi        at.run(_sysinfo_after_test_script % (outputdir, mytest.success),
2269285ddf562c698fda569390be6763170215663d7Dale Curtis               results_dir=self.job.resultdir)
2274395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2284395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh        self._pull_sysinfo_keyval(host, outputdir, mytest)
2294395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
2304395bbd96ed53aec5fad87d6c169a47dfdb8c9ddmbligh
231089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh    def cleanup(self, host_close=True):
2323524589241ead1fcbc3b9e7f31648850463d01admbligh        if self.host and self.autotest:
2333524589241ead1fcbc3b9e7f31648850463d01admbligh            try:
234089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                try:
235089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                    self.autotest.uninstall()
236089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                finally:
237089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                    if host_close:
238089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                        self.host.close()
239089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                    else:
240089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                        self.host.erase_dir_contents(self.outputdir)
241089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh
242089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh            except Exception:
243089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                # ignoring exceptions here so that we don't hide the true
244089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                # reason of failure from runtest
245089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                logging.exception('Error cleaning up the sysinfo autotest/host '
246089f1e3c2cd3acba1a703b5460a52ef6181fd717mbligh                                  'objects, ignoring it')
2473524589241ead1fcbc3b9e7f31648850463d01admbligh
2483524589241ead1fcbc3b9e7f31648850463d01admbligh
24905269369a9bbfee9481ce8b03b88f7abce4bad7bmblighdef runtest(job, url, tag, args, dargs):
250c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    """Server-side runtest.
251c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng
252c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    @param job: A server_job instance.
253c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    @param url: URL to the test.
254c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    @param tag: Test tag that will be appended to the test name.
255c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng                See client/common_lib/test.py:runtest
256c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    @param args: args to pass to the test.
257c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    @param dargs: key-val based args to pass to the test.
258c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    """
259c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng
260c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    disable_before_test_hook = dargs.pop('disable_before_test_sysinfo', False)
261c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    disable_after_test_hook = dargs.pop('disable_after_test_sysinfo', False)
262c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    disable_before_iteration_hook = dargs.pop(
263c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng            'disable_before_iteration_sysinfo', False)
264c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng    disable_after_iteration_hook = dargs.pop(
265c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng            'disable_after_iteration_sysinfo', False)
266c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng
2675019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu    disable_sysinfo = dargs.pop('disable_sysinfo', False)
2685019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu    if job.fast and not disable_sysinfo:
2695019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu        # Server job will be executed in fast mode, which means
2705019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu        # 1) if job succeeds, no hook will be executed.
2715019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu        # 2) if job failed, after_hook will be executed.
2725019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu        logger = _sysinfo_logger(job)
273f4fb11b73a916ba9a73013e47dc188f5c39286b1Xixuan Wu        logging_args = [None, logger.after_hook, None,
274f4fb11b73a916ba9a73013e47dc188f5c39286b1Xixuan Wu                        logger.after_iteration_hook]
2755019d69a182f2a7b8616d9cbcab54ffeaf3efe66Xixuan Wu    elif not disable_sysinfo:
27679a2ee19751173af33227bd4438e0bc7d2ced6e7mbligh        logger = _sysinfo_logger(job)
277c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng        logging_args = [
278c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng            logger.before_hook if not disable_before_test_hook else None,
279c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng            logger.after_hook if not disable_after_test_hook else None,
280c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng            (logger.before_iteration_hook
281c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng                 if not disable_before_iteration_hook else None),
282c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng            (logger.after_iteration_hook
283c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng                 if not disable_after_iteration_hook else None),
284c2282213e0c17496c395d0c7f6ac45732dcd0935Fang Deng        ]
28579a2ee19751173af33227bd4438e0bc7d2ced6e7mbligh    else:
2863524589241ead1fcbc3b9e7f31648850463d01admbligh        logger = None
2873524589241ead1fcbc3b9e7f31648850463d01admbligh        logging_args = [None, None, None, None]
2883524589241ead1fcbc3b9e7f31648850463d01admbligh
28943dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh    # add in a hook that calls host.log_kernel if we can
29043dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh    def log_kernel_hook(mytest, existing_hook=logging_args[0]):
29143dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh        if mytest.host_parameter:
29243dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh            host = dargs[mytest.host_parameter]
29343dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh            if host:
29443dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh                host.log_kernel()
29543dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh        # chain this call with any existing hook
29643dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh        if existing_hook:
29743dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh            existing_hook(mytest)
29843dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh    logging_args[0] = log_kernel_hook
29943dd549ce3ec132c24d2cbeb1c233cd887f5d1e8mbligh
3003524589241ead1fcbc3b9e7f31648850463d01admbligh    try:
3013524589241ead1fcbc3b9e7f31648850463d01admbligh        common_test.runtest(job, url, tag, args, dargs, locals(), globals(),
3023524589241ead1fcbc3b9e7f31648850463d01admbligh                            *logging_args)
3033524589241ead1fcbc3b9e7f31648850463d01admbligh    finally:
3043524589241ead1fcbc3b9e7f31648850463d01admbligh        if logger:
3053524589241ead1fcbc3b9e7f31648850463d01admbligh            logger.cleanup()
306