# Lint as: python2, python3
"""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 six

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 control_data
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 as 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)

        if self.control:
            parsed_control = control_data.parse_control(
                    self.control, raise_warnings=False)
            self.fast = parsed_control.fast

        # 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)
            # Run the dependency, as it could create more files needed for the
            # tests.
            # In future this might want to be changed, as this always returns
            # None, unless the dep.py errors. In which case, it'll error rather
            # than returning.
            if eval(compile(open('%s.py' % dep, "rb").read(),
                            '%s.py' % dep, 'exec'), {}) 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)

            self._forkwait(pid, timeout)

        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 as 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 _forkwait(self, pid, timeout=None):
        """Wait for the given pid to complete

        @param pid (int) process id to wait for
        @param timeout (int) seconds to wait before timing out the process"""
        if timeout:
            logging.debug('Waiting for pid %d for %d seconds', pid, timeout)
            parallel.fork_waitfor_timed(self.resultdir, pid, timeout)
        else:
            logging.debug('Waiting for pid %d', pid)
            parallel.fork_waitfor(self.resultdir, pid)
        logging.info('pid %d completed', pid)


    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 as 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.


    def stage_control_file(self, url):
        """
        Install the test package and return the control file path.

        @param url The name of the test, e.g. login_LoginSuccess.  This is the
            string passed to run_test in the client test control file:
            job.run_test('login_LoginSuccess')
            This name can also be something like 'camera_HAL3.jea',
            which corresponds to a test package containing multiple
            control files, each with calls to:
            job.run_test('camera_HAL3', **opts)

        @returns Absolute path to the control file for the test.
        """
        testname, _, _tag = url.partition('.')
        bindir = os.path.join(self.testdir, testname)
        self.install_pkg(testname, 'test', bindir)
        return _locate_test_control_file(bindir, url)


    @_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 as 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 as e:
                self.record('END %s' % e.exit_status, subdir, testname)
                raise
            except error.JobError as e:
                self.record('END ABORT', subdir, testname)
                raise
            except Exception as 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 as 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, **kwargs):
        """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:])
            forked_pid = parallel.fork_start(self.resultdir, task_func)
            logging.info('Just forked pid %d', forked_pid)
            pids.append(forked_pid)

        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:
                self._forkwait(pid, kwargs.get('timeout'))
            except Exception as e:
                logging.info('pid %d completed with error', pid)
                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"""
        # 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, six.string_types):
            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 as detail:
            self.record(detail.exit_status, None, fn, str(detail))
        except Exception as 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:
            exec(compile(open(self.control, "rb").read(), self.control, 'exec'),
                 global_control_vars, global_control_vars)
        except error.TestNAError as 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 as 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 as 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 as 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


# TODO(ayatane): This logic should be deduplicated with
# server/cros/dynamic_suite/control_file_getter.py, but the server
# libraries are not available on clients.
def _locate_test_control_file(dirpath, testname):
    """
    Locate the control file for the given test.

    @param dirpath Root directory to search.
    @param testname Name of test.

    @returns Absolute path to the control file.
    @raise JobError: Raised if control file not found.
    """
    for dirpath, _dirnames, filenames in os.walk(dirpath):
        for filename in filenames:
            if 'control' not in filename:
                continue
            path = os.path.join(dirpath, filename)
            if _is_control_file_for_test(path, testname):
                return os.path.abspath(path)
    raise error.JobError(
            'could not find client test control file',
            dirpath, testname)


_NAME_PATTERN = "NAME *= *['\"]([^'\"]+)['\"]"


def _is_control_file_for_test(path, testname):
    with open(path) as f:
        for line in f:
            match = re.match(_NAME_PATTERN, line)
            if match is not None:
                return match.group(1) == testname
