"""The main job wrapper

This is the core infrastructure.

Copyright Andy Whitcroft, Martin J. Bligh 2006
"""

# pylint: disable=missing-docstring

import copy
from datetime import datetime
import getpass
import glob
import logging
import os
import re
import shutil
import sys
import time
import traceback
import types
import weakref

import common
from autotest_lib.client.bin import client_logging_config
from autotest_lib.client.bin import harness
from autotest_lib.client.bin import local_host
from autotest_lib.client.bin import parallel
from autotest_lib.client.bin import partition as partition_lib
from autotest_lib.client.bin import profilers
from autotest_lib.client.bin import sysinfo
from autotest_lib.client.bin import test
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import barrier
from autotest_lib.client.common_lib import base_job
from autotest_lib.client.common_lib import packages
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
from autotest_lib.client.common_lib import logging_manager
from autotest_lib.client.common_lib import packages
from autotest_lib.client.cros import cros_logging
from autotest_lib.client.tools import html_report

GLOBAL_CONFIG = global_config.global_config

LAST_BOOT_TAG = object()
JOB_PREAMBLE = """
from autotest_lib.client.common_lib.error import *
from autotest_lib.client.bin.utils import *
"""


class StepError(error.AutotestError):
    pass

class NotAvailableError(error.AutotestError):
    pass



def _run_test_complete_on_exit(f):
    """Decorator for job methods that automatically calls
    self.harness.run_test_complete when the method exits, if appropriate."""
    def wrapped(self, *args, **dargs):
        try:
            return f(self, *args, **dargs)
        finally:
            if self._logger.global_filename == 'status':
                self.harness.run_test_complete()
                if self.drop_caches:
                    utils.drop_caches()
    wrapped.__name__ = f.__name__
    wrapped.__doc__ = f.__doc__
    wrapped.__dict__.update(f.__dict__)
    return wrapped


class status_indenter(base_job.status_indenter):
    """Provide a status indenter that is backed by job._record_prefix."""
    def __init__(self, job_):
        self._job = weakref.proxy(job_)  # avoid a circular reference


    @property
    def indent(self):
        return self._job._record_indent


    def increment(self):
        self._job._record_indent += 1


    def decrement(self):
        self._job._record_indent -= 1


class base_client_job(base_job.base_job):
    """The client-side concrete implementation of base_job.

    Optional properties provided by this implementation:
        control
        harness
    """

    _WARNING_DISABLE_DELAY = 5

    # _record_indent is a persistent property, but only on the client
    _job_state = base_job.base_job._job_state
    _record_indent = _job_state.property_factory(
        '_state', '_record_indent', 0, namespace='client')
    _max_disk_usage_rate = _job_state.property_factory(
        '_state', '_max_disk_usage_rate', 0.0, namespace='client')


    def __init__(self, control, options, drop_caches=True):
        """
        Prepare a client side job object.

        @param control: The control file (pathname of).
        @param options: an object which includes:
                jobtag: The job tag string (eg "default").
                cont: If this is the continuation of this job.
                harness_type: An alternative server harness.  [None]
                use_external_logging: If true, the enable_external_logging
                          method will be called during construction.  [False]
        @param drop_caches: If true, utils.drop_caches() is called before and
                between all tests.  [True]
        """
        super(base_client_job, self).__init__(options=options)
        self._pre_record_init(control, options)
        try:
            self._post_record_init(control, options, drop_caches)
        except Exception, err:
            self.record(
                    'ABORT', None, None,'client.bin.job.__init__ failed: %s' %
                    str(err))
            raise


    @classmethod
    def _get_environ_autodir(cls):
        return os.environ['AUTODIR']


    @classmethod
    def _find_base_directories(cls):
        """
        Determine locations of autodir and clientdir (which are the same)
        using os.environ. Serverdir does not exist in this context.
        """
        autodir = clientdir = cls._get_environ_autodir()
        return autodir, clientdir, None


    @classmethod
    def _parse_args(cls, args):
        return re.findall("[^\s]*?['|\"].*?['|\"]|[^\s]+", args)


    def _find_resultdir(self, options):
        """
        Determine the directory for storing results. On a client this is
        always <autodir>/results/<tag>, where tag is passed in on the command
        line as an option.
        """
        output_dir_config = GLOBAL_CONFIG.get_config_value('CLIENT',
                                                           'output_dir',
                                                            default="")
        if options.output_dir:
            basedir = options.output_dir
        elif output_dir_config:
            basedir = output_dir_config
        else:
            basedir = self.autodir

        return os.path.join(basedir, 'results', options.tag)


    def _get_status_logger(self):
        """Return a reference to the status logger."""
        return self._logger


    def _pre_record_init(self, control, options):
        """
        Initialization function that should peform ONLY the required
        setup so that the self.record() method works.

        As of now self.record() needs self.resultdir, self._group_level,
        self.harness and of course self._logger.
        """
        if not options.cont:
            self._cleanup_debugdir_files()
            self._cleanup_results_dir()

        logging_manager.configure_logging(
            client_logging_config.ClientLoggingConfig(),
            results_dir=self.resultdir,
            verbose=options.verbose)
        logging.info('Writing results to %s', self.resultdir)

        # init_group_level needs the state
        self.control = os.path.realpath(control)
        self._is_continuation = options.cont
        self._current_step_ancestry = []
        self._next_step_index = 0
        self._load_state()

        _harness = self.handle_persistent_option(options, 'harness')
        _harness_args = self.handle_persistent_option(options, 'harness_args')

        self.harness = harness.select(_harness, self, _harness_args)

        # set up the status logger
        def client_job_record_hook(entry):
            msg_tag = ''
            if '.' in self._logger.global_filename:
                msg_tag = self._logger.global_filename.split('.', 1)[1]
            # send the entry to the job harness
            message = '\n'.join([entry.message] + entry.extra_message_lines)
            rendered_entry = self._logger.render_entry(entry)
            self.harness.test_status_detail(entry.status_code, entry.subdir,
                                            entry.operation, message, msg_tag,
                                            entry.fields)
            self.harness.test_status(rendered_entry, msg_tag)
            # send the entry to stdout, if it's enabled
            logging.info(rendered_entry)
        self._logger = base_job.status_logger(
            self, status_indenter(self), record_hook=client_job_record_hook)


    def _post_record_init(self, control, options, drop_caches):
        """
        Perform job initialization not required by self.record().
        """
        self._init_drop_caches(drop_caches)

        self._init_packages()

        self.sysinfo = sysinfo.sysinfo(self.resultdir)
        self._load_sysinfo_state()

        if not options.cont:
            download = os.path.join(self.testdir, 'download')
            if not os.path.exists(download):
                os.mkdir(download)

            shutil.copyfile(self.control,
                            os.path.join(self.resultdir, 'control'))

        self.control = control

        self.logging = logging_manager.get_logging_manager(
                manage_stdout_and_stderr=True, redirect_fds=True)
        self.logging.start_logging()

        self.profilers = profilers.profilers(self)

        self.machines = [options.hostname]
        self.machine_dict_list = [{'hostname' : options.hostname}]
        # Client side tests should always run the same whether or not they are
        # running in the lab.
        self.in_lab = False
        self.hosts = set([local_host.LocalHost(hostname=options.hostname)])

        self.args = []
        if options.args:
            self.args = self._parse_args(options.args)

        if options.user:
            self.user = options.user
        else:
            self.user = getpass.getuser()

        self.sysinfo.log_per_reboot_data()

        if not options.cont:
            self.record('START', None, None)

        self.harness.run_start()

        if options.log:
            self.enable_external_logging()

        self.num_tests_run = None
        self.num_tests_failed = None

        self.warning_loggers = None
        self.warning_manager = None


    def _init_drop_caches(self, drop_caches):
        """
        Perform the drop caches initialization.
        """
        self.drop_caches_between_iterations = (
                                    GLOBAL_CONFIG.get_config_value('CLIENT',
                                    'drop_caches_between_iterations',
                                    type=bool, default=True))
        self.drop_caches = drop_caches
        if self.drop_caches:
            utils.drop_caches()


    def _init_packages(self):
        """
        Perform the packages support initialization.
        """
        self.pkgmgr = packages.PackageManager(
            self.autodir, run_function_dargs={'timeout':3600})


    def _cleanup_results_dir(self):
        """Delete everything in resultsdir"""
        assert os.path.exists(self.resultdir)
        list_files = glob.glob('%s/*' % self.resultdir)
        for f in list_files:
            if os.path.isdir(f):
                shutil.rmtree(f)
            elif os.path.isfile(f):
                os.remove(f)


    def _cleanup_debugdir_files(self):
        """
        Delete any leftover debugdir files
        """
        list_files = glob.glob("/tmp/autotest_results_dir.*")
        for f in list_files:
            os.remove(f)


    def disable_warnings(self, warning_type):
        self.record("INFO", None, None,
                    "disabling %s warnings" % warning_type,
                    {"warnings.disable": warning_type})
        time.sleep(self._WARNING_DISABLE_DELAY)


    def enable_warnings(self, warning_type):
        time.sleep(self._WARNING_DISABLE_DELAY)
        self.record("INFO", None, None,
                    "enabling %s warnings" % warning_type,
                    {"warnings.enable": warning_type})


    def monitor_disk_usage(self, max_rate):
        """\
        Signal that the job should monitor disk space usage on /
        and generate a warning if a test uses up disk space at a
        rate exceeding 'max_rate'.

        Parameters:
             max_rate - the maximium allowed rate of disk consumption
                        during a test, in MB/hour, or 0 to indicate
                        no limit.
        """
        self._max_disk_usage_rate = max_rate


    def control_get(self):
        return self.control


    def control_set(self, control):
        self.control = os.path.abspath(control)


    def harness_select(self, which, harness_args):
        self.harness = harness.select(which, self, harness_args)


    def setup_dirs(self, results_dir, tmp_dir):
        if not tmp_dir:
            tmp_dir = os.path.join(self.tmpdir, 'build')
        if not os.path.exists(tmp_dir):
            os.mkdir(tmp_dir)
        if not os.path.isdir(tmp_dir):
            e_msg = "Temp dir (%s) is not a dir - args backwards?" % self.tmpdir
            raise ValueError(e_msg)

        # We label the first build "build" and then subsequent ones
        # as "build.2", "build.3", etc. Whilst this is a little bit
        # inconsistent, 99.9% of jobs will only have one build
        # (that's not done as kernbench, sparse, or buildtest),
        # so it works out much cleaner. One of life's compromises.
        if not results_dir:
            results_dir = os.path.join(self.resultdir, 'build')
            i = 2
            while os.path.exists(results_dir):
                results_dir = os.path.join(self.resultdir, 'build.%d' % i)
                i += 1
        if not os.path.exists(results_dir):
            os.mkdir(results_dir)

        return (results_dir, tmp_dir)


    def barrier(self, *args, **kwds):
        """Create a barrier object"""
        return barrier.barrier(*args, **kwds)


    def install_pkg(self, name, pkg_type, install_dir):
        '''
        This method is a simple wrapper around the actual package
        installation method in the Packager class. This is used
        internally by the profilers, deps and tests code.
        name : name of the package (ex: sleeptest, dbench etc.)
        pkg_type : Type of the package (ex: test, dep etc.)
        install_dir : The directory in which the source is actually
                      untarred into. (ex: client/profilers/<name> for profilers)
        '''
        if self.pkgmgr.repositories:
            self.pkgmgr.install_pkg(name, pkg_type, self.pkgdir, install_dir)


    def add_repository(self, repo_urls):
        '''
        Adds the repository locations to the job so that packages
        can be fetched from them when needed. The repository list
        needs to be a string list
        Ex: job.add_repository(['http://blah1','http://blah2'])
        '''
        for repo_url in repo_urls:
            self.pkgmgr.add_repository(repo_url)

        # Fetch the packages' checksum file that contains the checksums
        # of all the packages if it is not already fetched. The checksum
        # is always fetched whenever a job is first started. This
        # is not done in the job's constructor as we don't have the list of
        # the repositories there (and obviously don't care about this file
        # if we are not using the repos)
        try:
            checksum_file_path = os.path.join(self.pkgmgr.pkgmgr_dir,
                                              packages.CHECKSUM_FILE)
            self.pkgmgr.fetch_pkg(packages.CHECKSUM_FILE,
                                  checksum_file_path, use_checksum=False)
        except error.PackageFetchError:
            # packaging system might not be working in this case
            # Silently fall back to the normal case
            pass


    def require_gcc(self):
        """
        Test whether gcc is installed on the machine.
        """
        # check if gcc is installed on the system.
        try:
            utils.system('which gcc')
        except error.CmdError:
            raise NotAvailableError('gcc is required by this job and is '
                                    'not available on the system')


    def setup_dep(self, deps):
        """Set up the dependencies for this test.
        deps is a list of libraries required for this test.
        """
        # Fetch the deps from the repositories and set them up.
        for dep in deps:
            dep_dir = os.path.join(self.autodir, 'deps', dep)
            # Search for the dependency in the repositories if specified,
            # else check locally.
            try:
                self.install_pkg(dep, 'dep', dep_dir)
            except error.PackageInstallError:
                # see if the dep is there locally
                pass

            # dep_dir might not exist if it is not fetched from the repos
            if not os.path.exists(dep_dir):
                raise error.TestError("Dependency %s does not exist" % dep)

            os.chdir(dep_dir)
            if execfile('%s.py' % dep, {}) is None:
                logging.info('Dependency %s successfuly built', dep)


    def _runtest(self, url, tag, timeout, args, dargs):
        try:
            l = lambda : test.runtest(self, url, tag, args, dargs)
            pid = parallel.fork_start(self.resultdir, l)

            if timeout:
                logging.debug('Waiting for pid %d for %d seconds', pid, timeout)
                parallel.fork_waitfor_timed(self.resultdir, pid, timeout)
            else:
                parallel.fork_waitfor(self.resultdir, pid)

        except error.TestBaseException:
            # These are already classified with an error type (exit_status)
            raise
        except error.JobError:
            raise  # Caught further up and turned into an ABORT.
        except Exception, e:
            # Converts all other exceptions thrown by the test regardless
            # of phase into a TestError(TestBaseException) subclass that
            # reports them with their full stack trace.
            raise error.UnhandledTestError(e)


    def _run_test_base(self, url, *args, **dargs):
        """
        Prepares arguments and run functions to run_test and run_test_detail.

        @param url A url that identifies the test to run.
        @param tag An optional keyword argument that will be added to the
            test and subdir name.
        @param subdir_tag An optional keyword argument that will be added
            to the subdir name.

        @returns:
                subdir: Test subdirectory
                testname: Test name
                group_func: Actual test run function
                timeout: Test timeout
        """
        _group, testname = self.pkgmgr.get_package_name(url, 'test')
        testname, subdir, tag = self._build_tagged_test_name(testname, dargs)
        self._make_test_outputdir(subdir)

        timeout = dargs.pop('timeout', None)
        if timeout:
            logging.debug('Test has timeout: %d sec.', timeout)

        def log_warning(reason):
            self.record("WARN", subdir, testname, reason)
        @disk_usage_monitor.watch(log_warning, "/", self._max_disk_usage_rate)
        def group_func():
            try:
                self._runtest(url, tag, timeout, args, dargs)
            except error.TestBaseException, detail:
                # The error is already classified, record it properly.
                self.record(detail.exit_status, subdir, testname, str(detail))
                raise
            else:
                self.record('GOOD', subdir, testname, 'completed successfully')

        return (subdir, testname, group_func, timeout)


    @_run_test_complete_on_exit
    def run_test(self, url, *args, **dargs):
        """
        Summon a test object and run it.

        @param url A url that identifies the test to run.
        @param tag An optional keyword argument that will be added to the
            test and subdir name.
        @param subdir_tag An optional keyword argument that will be added
            to the subdir name.

        @returns True if the test passes, False otherwise.
        """
        (subdir, testname, group_func, timeout) = self._run_test_base(url,
                                                                      *args,
                                                                      **dargs)
        try:
            self._rungroup(subdir, testname, group_func, timeout)
            return True
        except error.TestBaseException:
            return False
        # Any other exception here will be given to the caller
        #
        # NOTE: The only exception possible from the control file here
        # is error.JobError as _runtest() turns all others into an
        # UnhandledTestError that is caught above.


    @_run_test_complete_on_exit
    def run_test_detail(self, url, *args, **dargs):
        """
        Summon a test object and run it, returning test status.

        @param url A url that identifies the test to run.
        @param tag An optional keyword argument that will be added to the
            test and subdir name.
        @param subdir_tag An optional keyword argument that will be added
            to the subdir name.

        @returns Test status
        @see: client/common_lib/error.py, exit_status
        """
        (subdir, testname, group_func, timeout) = self._run_test_base(url,
                                                                      *args,
                                                                      **dargs)
        try:
            self._rungroup(subdir, testname, group_func, timeout)
            return 'GOOD'
        except error.TestBaseException, detail:
            return detail.exit_status


    def _rungroup(self, subdir, testname, function, timeout, *args, **dargs):
        """\
        subdir:
                name of the group
        testname:
                name of the test to run, or support step
        function:
                subroutine to run
        *args:
                arguments for the function

        Returns the result of the passed in function
        """

        try:
            optional_fields = None
            if timeout:
                optional_fields = {}
                optional_fields['timeout'] = timeout
            self.record('START', subdir, testname,
                        optional_fields=optional_fields)

            self._state.set('client', 'unexpected_reboot', (subdir, testname))
            try:
                result = function(*args, **dargs)
                self.record('END GOOD', subdir, testname)
                return result
            except error.TestBaseException, e:
                self.record('END %s' % e.exit_status, subdir, testname)
                raise
            except error.JobError, e:
                self.record('END ABORT', subdir, testname)
                raise
            except Exception, e:
                # This should only ever happen due to a bug in the given
                # function's code.  The common case of being called by
                # run_test() will never reach this.  If a control file called
                # run_group() itself, bugs in its function will be caught
                # here.
                err_msg = str(e) + '\n' + traceback.format_exc()
                self.record('END ERROR', subdir, testname, err_msg)
                raise
        finally:
            self._state.discard('client', 'unexpected_reboot')


    def run_group(self, function, tag=None, **dargs):
        """
        Run a function nested within a group level.

        function:
                Callable to run.
        tag:
                An optional tag name for the group.  If None (default)
                function.__name__ will be used.
        **dargs:
                Named arguments for the function.
        """
        if tag:
            name = tag
        else:
            name = function.__name__

        try:
            return self._rungroup(subdir=None, testname=name,
                                  function=function, timeout=None, **dargs)
        except (SystemExit, error.TestBaseException):
            raise
        # If there was a different exception, turn it into a TestError.
        # It will be caught by step_engine or _run_step_fn.
        except Exception, e:
            raise error.UnhandledTestError(e)


    def cpu_count(self):
        return utils.count_cpus()  # use total system count


    def start_reboot(self):
        self.record('START', None, 'reboot')
        self.record('GOOD', None, 'reboot.start')


    def _record_reboot_failure(self, subdir, operation, status,
                               running_id=None):
        self.record("ABORT", subdir, operation, status)
        if not running_id:
            running_id = utils.running_os_ident()
        kernel = {"kernel": running_id.split("::")[0]}
        self.record("END ABORT", subdir, 'reboot', optional_fields=kernel)


    def _check_post_reboot(self, subdir, running_id=None):
        """
        Function to perform post boot checks such as if the system configuration
        has changed across reboots (specifically, CPUs and partitions).

        @param subdir: The subdir to use in the job.record call.
        @param running_id: An optional running_id to include in the reboot
            failure log message

        @raise JobError: Raised if the current configuration does not match the
            pre-reboot configuration.
        """
        # check to see if any partitions have changed
        partition_list = partition_lib.get_partition_list(self,
                                                          exclude_swap=False)
        mount_info = partition_lib.get_mount_info(partition_list)
        old_mount_info = self._state.get('client', 'mount_info')
        if mount_info != old_mount_info:
            new_entries = mount_info - old_mount_info
            old_entries = old_mount_info - mount_info
            description = ("mounted partitions are different after reboot "
                           "(old entries: %s, new entries: %s)" %
                           (old_entries, new_entries))
            self._record_reboot_failure(subdir, "reboot.verify_config",
                                        description, running_id=running_id)
            raise error.JobError("Reboot failed: %s" % description)

        # check to see if any CPUs have changed
        cpu_count = utils.count_cpus()
        old_count = self._state.get('client', 'cpu_count')
        if cpu_count != old_count:
            description = ('Number of CPUs changed after reboot '
                           '(old count: %d, new count: %d)' %
                           (old_count, cpu_count))
            self._record_reboot_failure(subdir, 'reboot.verify_config',
                                        description, running_id=running_id)
            raise error.JobError('Reboot failed: %s' % description)


    def partition(self, device, loop_size=0, mountpoint=None):
        """
        Work with a machine partition

            @param device: e.g. /dev/sda2, /dev/sdb1 etc...
            @param mountpoint: Specify a directory to mount to. If not specified
                               autotest tmp directory will be used.
            @param loop_size: Size of loopback device (in MB). Defaults to 0.

            @return: A L{client.bin.partition.partition} object
        """

        if not mountpoint:
            mountpoint = self.tmpdir
        return partition_lib.partition(self, device, loop_size, mountpoint)

    @utils.deprecated
    def filesystem(self, device, mountpoint=None, loop_size=0):
        """ Same as partition

        @deprecated: Use partition method instead
        """
        return self.partition(device, loop_size, mountpoint)


    def enable_external_logging(self):
        pass


    def disable_external_logging(self):
        pass


    def reboot_setup(self):
        # save the partition list and mount points, as well as the cpu count
        partition_list = partition_lib.get_partition_list(self,
                                                          exclude_swap=False)
        mount_info = partition_lib.get_mount_info(partition_list)
        self._state.set('client', 'mount_info', mount_info)
        self._state.set('client', 'cpu_count', utils.count_cpus())


    def reboot(self):
        self.reboot_setup()
        self.harness.run_reboot()

        # HACK: using this as a module sometimes hangs shutdown, so if it's
        # installed unload it first
        utils.system("modprobe -r netconsole", ignore_status=True)

        # sync first, so that a sync during shutdown doesn't time out
        utils.system("sync; sync", ignore_status=True)

        utils.system("(sleep 5; reboot) </dev/null >/dev/null 2>&1 &")
        self.quit()


    def noop(self, text):
        logging.info("job: noop: " + text)


    @_run_test_complete_on_exit
    def parallel(self, *tasklist):
        """Run tasks in parallel"""

        pids = []
        old_log_filename = self._logger.global_filename
        for i, task in enumerate(tasklist):
            assert isinstance(task, (tuple, list))
            self._logger.global_filename = old_log_filename + (".%d" % i)
            def task_func():
                # stub out _record_indent with a process-local one
                base_record_indent = self._record_indent
                proc_local = self._job_state.property_factory(
                    '_state', '_record_indent.%d' % os.getpid(),
                    base_record_indent, namespace='client')
                self.__class__._record_indent = proc_local
                task[0](*task[1:])
            pids.append(parallel.fork_start(self.resultdir, task_func))

        old_log_path = os.path.join(self.resultdir, old_log_filename)
        old_log = open(old_log_path, "a")
        exceptions = []
        for i, pid in enumerate(pids):
            # wait for the task to finish
            try:
                parallel.fork_waitfor(self.resultdir, pid)
            except Exception, e:
                exceptions.append(e)
            # copy the logs from the subtask into the main log
            new_log_path = old_log_path + (".%d" % i)
            if os.path.exists(new_log_path):
                new_log = open(new_log_path)
                old_log.write(new_log.read())
                new_log.close()
                old_log.flush()
                os.remove(new_log_path)
        old_log.close()

        self._logger.global_filename = old_log_filename

        # handle any exceptions raised by the parallel tasks
        if exceptions:
            msg = "%d task(s) failed in job.parallel" % len(exceptions)
            raise error.JobError(msg)


    def quit(self):
        # XXX: should have a better name.
        self.harness.run_pause()
        raise error.JobContinue("more to come")


    def complete(self, status):
        """Write pending reports, clean up, and exit"""
        # write out a job HTML report
        try:
            html_report.create_report(self.resultdir)
        except Exception, e:
            logging.error("Error writing job HTML report: %s", e)

        # We are about to exit 'complete' so clean up the control file.
        dest = os.path.join(self.resultdir, os.path.basename(self._state_file))
        shutil.move(self._state_file, dest)

        self.harness.run_complete()
        self.disable_external_logging()
        sys.exit(status)


    def _load_state(self):
        # grab any initial state and set up $CONTROL.state as the backing file
        init_state_file = self.control + '.init.state'
        self._state_file = self.control + '.state'
        if os.path.exists(init_state_file):
            shutil.move(init_state_file, self._state_file)
        self._state.set_backing_file(self._state_file)

        # initialize the state engine, if necessary
        has_steps = self._state.has('client', 'steps')
        if not self._is_continuation and has_steps:
            raise RuntimeError('Loaded state can only contain client.steps if '
                               'this is a continuation')

        if not has_steps:
            logging.debug('Initializing the state engine')
            self._state.set('client', 'steps', [])


    def handle_persistent_option(self, options, option_name):
        """
        Select option from command line or persistent state.
        Store selected option to allow standalone client to continue
        after reboot with previously selected options.
        Priority:
        1. explicitly specified via command line
        2. stored in state file (if continuing job '-c')
        3. default == None
        """
        option = None
        cmd_line_option = getattr(options, option_name)
        if cmd_line_option:
            option = cmd_line_option
            self._state.set('client', option_name, option)
        else:
            stored_option = self._state.get('client', option_name, None)
            if stored_option:
                option = stored_option
        logging.debug('Persistent option %s now set to %s', option_name, option)
        return option


    def __create_step_tuple(self, fn, args, dargs):
        # Legacy code passes in an array where the first arg is
        # the function or its name.
        if isinstance(fn, list):
            assert(len(args) == 0)
            assert(len(dargs) == 0)
            args = fn[1:]
            fn = fn[0]
        # Pickling actual functions is hairy, thus we have to call
        # them by name.  Unfortunately, this means only functions
        # defined globally can be used as a next step.
        if callable(fn):
            fn = fn.__name__
        if not isinstance(fn, types.StringTypes):
            raise StepError("Next steps must be functions or "
                            "strings containing the function name")
        ancestry = copy.copy(self._current_step_ancestry)
        return (ancestry, fn, args, dargs)


    def next_step_append(self, fn, *args, **dargs):
        """Define the next step and place it at the end"""
        steps = self._state.get('client', 'steps')
        steps.append(self.__create_step_tuple(fn, args, dargs))
        self._state.set('client', 'steps', steps)


    def next_step(self, fn, *args, **dargs):
        """Create a new step and place it after any steps added
        while running the current step but before any steps added in
        previous steps"""
        steps = self._state.get('client', 'steps')
        steps.insert(self._next_step_index,
                     self.__create_step_tuple(fn, args, dargs))
        self._next_step_index += 1
        self._state.set('client', 'steps', steps)


    def next_step_prepend(self, fn, *args, **dargs):
        """Insert a new step, executing first"""
        steps = self._state.get('client', 'steps')
        steps.insert(0, self.__create_step_tuple(fn, args, dargs))
        self._next_step_index += 1
        self._state.set('client', 'steps', steps)



    def _run_step_fn(self, local_vars, fn, args, dargs):
        """Run a (step) function within the given context"""

        local_vars['__args'] = args
        local_vars['__dargs'] = dargs
        try:
            exec('__ret = %s(*__args, **__dargs)' % fn, local_vars, local_vars)
            return local_vars['__ret']
        except SystemExit:
            raise  # Send error.JobContinue and JobComplete on up to runjob.
        except error.TestNAError, detail:
            self.record(detail.exit_status, None, fn, str(detail))
        except Exception, detail:
            raise error.UnhandledJobError(detail)


    def _create_frame(self, global_vars, ancestry, fn_name):
        """Set up the environment like it would have been when this
        function was first defined.

        Child step engine 'implementations' must have 'return locals()'
        at end end of their steps.  Because of this, we can call the
        parent function and get back all child functions (i.e. those
        defined within it).

        Unfortunately, the call stack of the function calling
        job.next_step might have been deeper than the function it
        added.  In order to make sure that the environment is what it
        should be, we need to then pop off the frames we built until
        we find the frame where the function was first defined."""

        # The copies ensure that the parent frames are not modified
        # while building child frames.  This matters if we then
        # pop some frames in the next part of this function.
        current_frame = copy.copy(global_vars)
        frames = [current_frame]
        for steps_fn_name in ancestry:
            ret = self._run_step_fn(current_frame, steps_fn_name, [], {})
            current_frame = copy.copy(ret)
            frames.append(current_frame)

        # Walk up the stack frames until we find the place fn_name was defined.
        while len(frames) > 2:
            if fn_name not in frames[-2]:
                break
            if frames[-2][fn_name] != frames[-1][fn_name]:
                break
            frames.pop()
            ancestry.pop()

        return (frames[-1], ancestry)


    def _add_step_init(self, local_vars, current_function):
        """If the function returned a dictionary that includes a
        function named 'step_init', prepend it to our list of steps.
        This will only get run the first time a function with a nested
        use of the step engine is run."""

        if (isinstance(local_vars, dict) and
            'step_init' in local_vars and
            callable(local_vars['step_init'])):
            # The init step is a child of the function
            # we were just running.
            self._current_step_ancestry.append(current_function)
            self.next_step_prepend('step_init')


    def step_engine(self):
        """The multi-run engine used when the control file defines step_init.

        Does the next step.
        """

        # Set up the environment and then interpret the control file.
        # Some control files will have code outside of functions,
        # which means we need to have our state engine initialized
        # before reading in the file.
        global_control_vars = {'job': self,
                               'args': self.args}
        exec(JOB_PREAMBLE, global_control_vars, global_control_vars)
        try:
            execfile(self.control, global_control_vars, global_control_vars)
        except error.TestNAError, detail:
            self.record(detail.exit_status, None, self.control, str(detail))
        except SystemExit:
            raise  # Send error.JobContinue and JobComplete on up to runjob.
        except Exception, detail:
            # Syntax errors or other general Python exceptions coming out of
            # the top level of the control file itself go through here.
            raise error.UnhandledJobError(detail)

        # If we loaded in a mid-job state file, then we presumably
        # know what steps we have yet to run.
        if not self._is_continuation:
            if 'step_init' in global_control_vars:
                self.next_step(global_control_vars['step_init'])
        else:
            # if last job failed due to unexpected reboot, record it as fail
            # so harness gets called
            last_job = self._state.get('client', 'unexpected_reboot', None)
            if last_job:
                subdir, testname = last_job
                self.record('FAIL', subdir, testname, 'unexpected reboot')
                self.record('END FAIL', subdir, testname)

        # Iterate through the steps.  If we reboot, we'll simply
        # continue iterating on the next step.
        while len(self._state.get('client', 'steps')) > 0:
            steps = self._state.get('client', 'steps')
            (ancestry, fn_name, args, dargs) = steps.pop(0)
            self._state.set('client', 'steps', steps)

            self._next_step_index = 0
            ret = self._create_frame(global_control_vars, ancestry, fn_name)
            local_vars, self._current_step_ancestry = ret
            local_vars = self._run_step_fn(local_vars, fn_name, args, dargs)
            self._add_step_init(local_vars, fn_name)


    def add_sysinfo_command(self, command, logfile=None, on_every_test=False):
        self._add_sysinfo_loggable(sysinfo.command(command, logf=logfile),
                                   on_every_test)


    def add_sysinfo_logfile(self, file, on_every_test=False):
        self._add_sysinfo_loggable(sysinfo.logfile(file), on_every_test)


    def _add_sysinfo_loggable(self, loggable, on_every_test):
        if on_every_test:
            self.sysinfo.test_loggables.add(loggable)
        else:
            self.sysinfo.boot_loggables.add(loggable)
        self._save_sysinfo_state()


    def _load_sysinfo_state(self):
        state = self._state.get('client', 'sysinfo', None)
        if state:
            self.sysinfo.deserialize(state)


    def _save_sysinfo_state(self):
        state = self.sysinfo.serialize()
        self._state.set('client', 'sysinfo', state)


class disk_usage_monitor:
    def __init__(self, logging_func, device, max_mb_per_hour):
        self.func = logging_func
        self.device = device
        self.max_mb_per_hour = max_mb_per_hour


    def start(self):
        self.initial_space = utils.freespace(self.device)
        self.start_time = time.time()


    def stop(self):
        # if no maximum usage rate was set, we don't need to
        # generate any warnings
        if not self.max_mb_per_hour:
            return

        final_space = utils.freespace(self.device)
        used_space = self.initial_space - final_space
        stop_time = time.time()
        total_time = stop_time - self.start_time
        # round up the time to one minute, to keep extremely short
        # tests from generating false positives due to short, badly
        # timed bursts of activity
        total_time = max(total_time, 60.0)

        # determine the usage rate
        bytes_per_sec = used_space / total_time
        mb_per_sec = bytes_per_sec / 1024**2
        mb_per_hour = mb_per_sec * 60 * 60

        if mb_per_hour > self.max_mb_per_hour:
            msg = ("disk space on %s was consumed at a rate of %.2f MB/hour")
            msg %= (self.device, mb_per_hour)
            self.func(msg)


    @classmethod
    def watch(cls, *monitor_args, **monitor_dargs):
        """ Generic decorator to wrap a function call with the
        standard create-monitor -> start -> call -> stop idiom."""
        def decorator(func):
            def watched_func(*args, **dargs):
                monitor = cls(*monitor_args, **monitor_dargs)
                monitor.start()
                try:
                    func(*args, **dargs)
                finally:
                    monitor.stop()
            return watched_func
        return decorator


def runjob(control, drop_caches, options):
    """
    Run a job using the given control file.

    This is the main interface to this module.

    @see base_job.__init__ for parameter info.
    """
    control = os.path.abspath(control)
    state = control + '.state'
    # Ensure state file is cleaned up before the job starts to run if autotest
    # is not running with the --continue flag
    if not options.cont and os.path.isfile(state):
        logging.debug('Cleaning up previously found state file')
        os.remove(state)

    # instantiate the job object ready for the control file.
    myjob = None
    try:
        # Check that the control file is valid
        if not os.path.exists(control):
            raise error.JobError(control + ": control file not found")

        # When continuing, the job is complete when there is no
        # state file, ensure we don't try and continue.
        if options.cont and not os.path.exists(state):
            raise error.JobComplete("all done")

        myjob = job(control=control, drop_caches=drop_caches, options=options)

        # Load in the users control file, may do any one of:
        #  1) execute in toto
        #  2) define steps, and select the first via next_step()
        myjob.step_engine()

    except error.JobContinue:
        sys.exit(5)

    except error.JobComplete:
        sys.exit(1)

    except error.JobError, instance:
        logging.error("JOB ERROR: " + str(instance))
        if myjob:
            command = None
            if len(instance.args) > 1:
                command = instance.args[1]
                myjob.record('ABORT', None, command, str(instance))
            myjob.record('END ABORT', None, None, str(instance))
            assert myjob._record_indent == 0
            myjob.complete(1)
        else:
            sys.exit(1)

    except Exception, e:
        # NOTE: job._run_step_fn and job.step_engine will turn things into
        # a JobError for us.  If we get here, its likely an autotest bug.
        msg = str(e) + '\n' + traceback.format_exc()
        logging.critical("JOB ERROR (autotest bug?): " + msg)
        if myjob:
            myjob.record('END ABORT', None, None, msg)
            assert myjob._record_indent == 0
            myjob.complete(1)
        else:
            sys.exit(1)

    # If we get here, then we assume the job is complete and good.
    myjob.record('END GOOD', None, None)
    assert myjob._record_indent == 0

    myjob.complete(0)


class job(base_client_job):

    def __init__(self, *args, **kwargs):
        base_client_job.__init__(self, *args, **kwargs)


    def run_test(self, url, *args, **dargs):
        log_pauser = cros_logging.LogRotationPauser()
        passed = False
        try:
            log_pauser.begin()
            passed = base_client_job.run_test(self, url, *args, **dargs)
            if not passed:
                # Save the VM state immediately after the test failure.
                # This is a NOOP if the the test isn't running in a VM or
                # if the VM is not properly configured to save state.
                _group, testname = self.pkgmgr.get_package_name(url, 'test')
                now = datetime.now().strftime('%I:%M:%S.%f')
                checkpoint_name = '%s-%s' % (testname, now)
                utils.save_vm_state(checkpoint_name)
        finally:
            log_pauser.end()
        return passed


    def reboot(self):
        self.reboot_setup()
        self.harness.run_reboot()

        # sync first, so that a sync during shutdown doesn't time out
        utils.system('sync; sync', ignore_status=True)

        utils.system('reboot </dev/null >/dev/null 2>&1 &')
        self.quit()


    def require_gcc(self):
        return False
