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

"""Utility to deploy and run result utils on a DUT.

This module is the one imported by other Autotest code and run result
throttling. Other modules in result_tools are designed to be copied to DUT and
executed with command line. That's why other modules (except view.py and
unittests) don't import the common module.
"""

import logging
import os

import common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
from autotest_lib.client.common_lib import utils as client_utils

try:
    from chromite.lib import metrics
except ImportError:
    metrics = client_utils.metrics_mock


CONFIG = global_config.global_config
ENABLE_RESULT_THROTTLING = CONFIG.get_config_value(
        'AUTOSERV', 'enable_result_throttling', type=bool, default=False)

_THROTTLE_OPTION_FMT = '-m %s'
_SUMMARY_CMD= '%s/result_tools/utils.py'
_BUILD_DIR_SUMMARY_CMD = _SUMMARY_CMD + ' -p %s %s'
_BUILD_DIR_SUMMARY_TIMEOUT = 120
_FIND_DIR_SUMMARY_TIMEOUT = 10
_CLEANUP_DIR_SUMMARY_CMD = _SUMMARY_CMD + ' -p %s -d'
_CLEANUP_DIR_SUMMARY_TIMEOUT = 10

# Default autotest directory on host
DEFAULT_AUTOTEST_DIR = '/usr/local/autotest'

# File patterns to be excluded from deploying to the dut.
_EXCLUDES = ['*.pyc', '*unittest.py', 'common.py', '__init__.py', 'runner.py',
             'view.py']

def _deploy_result_tools(host):
    """Send result tools to the dut.

    @param host: Host to run the result tools.
    """
    with metrics.SecondsTimer(
            'chromeos/autotest/job/send_result_tools_duration',
            fields={'dut_host_name': host.hostname}) as fields:
        try:
            result = host.run('test -f %s' %
                      (_SUMMARY_CMD % DEFAULT_AUTOTEST_DIR),
                   timeout=_FIND_DIR_SUMMARY_TIMEOUT,
                   ignore_status=True)
            if result.exit_status == 0:
                logging.debug('result tools are already deployed to %s.',
                        host.hostname)
            else:
                logging.debug('Deploy result utilities to %s', host.hostname)
                result_tools_dir = os.path.dirname(__file__)
                host.send_file(result_tools_dir, DEFAULT_AUTOTEST_DIR,
                               excludes = _EXCLUDES)
            fields['success'] = True
        except error.AutotestHostRunError:
            logging.debug('Failed to deploy result tools using `excludes`. Try '
                          'again without `excludes`.')
            host.send_file(result_tools_dir, DEFAULT_AUTOTEST_DIR)
            fields['success'] = False


def run_on_client(host, client_results_dir, cleanup_only=False):
    """Run result utils on the given host.

    @param host: Host to run the result utils.
    @param client_results_dir: Path to the results directory on the client.
    @param cleanup_only: True to delete all existing directory summary files in
            the given directory.
    @return: True: If the command runs on client without error.
             False: If the command failed with error in result throttling.
    """
    success = False
    with metrics.SecondsTimer(
            'chromeos/autotest/job/dir_summary_collection_duration',
            fields={'dut_host_name': host.hostname}) as fields:
        try:
            _deploy_result_tools(host)

            if cleanup_only:
                logging.debug('Cleaning up directory summary in %s',
                              client_results_dir)
                cmd = (_CLEANUP_DIR_SUMMARY_CMD %
                       (DEFAULT_AUTOTEST_DIR, client_results_dir))
                host.run(cmd, ignore_status=False,
                         timeout=_CLEANUP_DIR_SUMMARY_TIMEOUT)
            else:
                logging.debug('Getting directory summary for %s',
                              client_results_dir)
                throttle_option = ''
                if ENABLE_RESULT_THROTTLING:
                    try:
                        throttle_option = (_THROTTLE_OPTION_FMT %
                                           host.job.max_result_size_KB)
                    except AttributeError:
                        # In case host job is not set, skip throttling.
                        logging.warn('host object does not have job attribute, '
                                     'skipping result throttling.')
                cmd = (_BUILD_DIR_SUMMARY_CMD %
                       (DEFAULT_AUTOTEST_DIR, client_results_dir,
                        throttle_option))
                host.run(cmd, ignore_status=False,
                         timeout=_BUILD_DIR_SUMMARY_TIMEOUT)
                success = True
            fields['success'] = True
        except error.AutoservRunError:
            action = 'cleanup' if cleanup_only else 'create'
            logging.exception(
                    'Non-critical failure: Failed to %s directory summary for '
                    '%s.', action, client_results_dir)
            fields['success'] = False

    return success


def collect_last_summary(host, source_path, dest_path,
                         skip_summary_collection=False):
    """Collect the last directory summary next to the given file path.

    If the given source_path is a directory, return without collecting any
    result summary file, as the summary file should have been collected with the
    directory.

    @param host: The RemoteHost to collect logs from.
    @param source_path: The remote path to collect the directory summary file
            from. If the source_path is a file
    @param dest_path: A path to write the source_path into. The summary file
            will be saved to the same folder.
    @param skip_summary_collection: True to skip summary file collection, only
            to delete the last summary. This is used in case when result
            collection in the dut failed. Default is set to False.
    """
    if not os.path.exists(dest_path):
        logging.debug('Source path %s does not exist, no directory summary '
                      'will be collected', dest_path)
        return

    # Test if source_path is a file.
    try:
        host.run('test -f %s' % source_path, timeout=_FIND_DIR_SUMMARY_TIMEOUT)
        is_source_file = True
    except error.AutoservRunError:
        is_source_file = False
        # No need to collect summary files if the source path is a directory,
        # as the summary files should have been copied over with the directory.
        # However, the last summary should be cleaned up so it won't affect
        # later tests.
        skip_summary_collection = True

    source_dir = os.path.dirname(source_path) if is_source_file else source_path
    dest_dir = dest_path if os.path.isdir(dest_path) else dest_path

    # Get the latest directory summary file.
    try:
        summary_pattern = os.path.join(source_dir, 'dir_summary_*.json')
        summary_file = host.run(
                'ls -t %s | head -1' % summary_pattern,
                timeout=_FIND_DIR_SUMMARY_TIMEOUT).stdout.strip()
    except error.AutoservRunError:
        logging.exception(
                'Non-critical failure: Failed to locate the latest directory '
                'summary for %s', source_dir)
        return

    try:
        if not skip_summary_collection:
            host.get_file(
                    summary_file,
                    os.path.join(dest_dir, os.path.basename(summary_file)),
                    preserve_perm=False)
    finally:
        # Remove the collected summary file so it won't affect later tests.
        try:
            # Check and remove the summary file
            if host.path_exists(summary_file):
                host.run('rm %s' % summary_file,
                         timeout=_FIND_DIR_SUMMARY_TIMEOUT).stdout.strip()
        except error.AutoservRunError:
            logging.exception(
                    'Non-critical failure: Failed to delete the latest '
                    'directory summary: %s', summary_file)
