普通文本  |  78行  |  3.49 KB

# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.server import test, autotest

class desktopui_CrashyRebootServer(test.test):
    """Validate logic for mitigating too-crashy UI.

    If the UI crashes too much too fast, the device will eventually
    reboot to attempt to mitigate the problem. If the device
    determines that it's already tried that once, it will shut down
    the UI and remain up.

    This test deploys the client test desktopui_CrashyReboot in order
    to drive the device into the desired states.
    """
    version = 1

    CRASHY_DEVICE_TIMEOUT_SECONDS = 120
    CLIENT_TEST = 'desktopui_CrashyReboot'

    def run_once(self, host=None):
        host.run('rm -f /var/lib/ui/reboot-timestamps')
        boot_id = host.get_boot_id()

        # Run a client-side test that crashes the UI a bunch, and
        # expect a reboot.  We need to run this test in the background in
        # order to prevent the reboot from causing autotest to auto-fail
        # the entire test. This means we also need to handle collecting
        # and parsing results manually if it doesn't work.
        logging.info('CrashyRebootServer: start client test')
        tag = 'reboot'
        client_at = autotest.Autotest(host)
        client_at.run_test(self.CLIENT_TEST, expect_reboot=True, tag='reboot',
                           background=True)

        logging.info('Client test now running in background.')
        # Prepare for result gathering.
        collector = autotest.log_collector(host, None, '.')
        host.job.add_client_log(host.hostname,
                                collector.client_results_dir,
                                collector.server_results_dir)
        job_record_context = host.job.get_record_context()

        logging.info('Waiting for host to go down.')
        if not host.wait_down(timeout=self.CRASHY_DEVICE_TIMEOUT_SECONDS,
                              old_boot_id=boot_id):
            # Gather results to determine why device didn't reboot.
            collector.collect_client_job_results()
            collector.remove_redundant_client_logs()
            host.job.remove_client_log(host.hostname,
                                       collector.client_results_dir,
                                       collector.server_results_dir)
            job_record_context.restore()
            raise error.TestError('Host should have rebooted!')

        logging.info('Waiting for host to come back up.')
        try:
            # wait_up() issues an ssh connection attempt and then spends
            # the entire given timeout waiting for it to succeed. If it
            # does this before the device is ready to accept ssh
            # connections, it will decide that the device never came up,
            # even if it is ready and waiting. To combat this, loop with
            # a short timeout.
            utils.poll_for_condition(lambda: host.wait_up(5),
                                     timeout=self.CRASHY_DEVICE_TIMEOUT_SECONDS)
        except utils.TimeoutError:
            raise error.TestError('Host never came back!')

        # NB: If we change the reboot-attempt threshold in
        # /etc/init/ui-respawn.conf to be >1, this will start failing
        # and need to be updated.
        client_at.run_test(self.CLIENT_TEST, expect_reboot=False)