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

import logging
import multiprocessing
import sys

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
from autotest_lib.client.common_lib.cros import dev_server
from autotest_lib.server.cros import autoupdater
from autotest_lib.server.cros.dynamic_suite import constants

#Update status
UPDATE_SUCCESS = 0
UPDATE_FAILURE = 1

def update_dut_worker(updater_obj, dut, image, force):
    """The method called by multiprocessing worker pool for updating DUT.
    This function is the function which is repeatedly scheduled for each
    DUT through the multiprocessing worker. This has to be defined outside
    the class because it needs to be pickleable.

    @param updater_obj: An CliqueDUTUpdater object.
    @param dut: DUTObject representing the DUT.
    @param image: The build type and version to install on the host.
    @param force: If False, will only updated the host if it is not
                  already running the build. If True, force the
                  update regardless, and force a full-reimage.

    """
    updater_obj.update_dut(dut_host=dut.host, image=image, force=force)


class CliqueDUTUpdater(object):
    """CliqueDUTUpdater is responsible for updating all the DUT's in the
    DUT pool to the same release.
    """

    def __init__(self):
        """Initializes the DUT updater for updating the DUT's in the pool."""


    @staticmethod
    def _get_board_name_from_host(dut_host):
        """Get the board name of the remote host.

        @param host: Host object representing the DUT.

        @return: A string representing the board of the remote host.
        """
        try:
            board = dut_host.get_board().replace(constants.BOARD_PREFIX, '')
        except error.AutoservRunError:
            raise error.TestFail(
                    'Cannot determine board for host %s' % dut_host.hostname)
        logging.debug('Detected board %s for host %s', board, dut_host.hostname)
        return board

    @staticmethod
    def _construct_image_label(dut_board, release_version):
        """Constructs a label combining the board name and release version.

        @param dut_board: A string representing the board of the remote host.
        @param release_version: A chromeOS release version.

        @return: A string representing the release version.
                 Ex: lumpy-release/R28-3993.0.0
        """
        # todo(rpius): We should probably make this more flexible to accept
        # images from trybot's, etc.
        return dut_board + '-release/' + release_version

    @staticmethod
    def _get_update_url(ds_url, image):
        """Returns the full update URL. """
        config = global_config.global_config
        image_url_pattern = config.get_config_value(
                'CROS', 'image_url_pattern', type=str)
        return image_url_pattern % (ds_url, image)

    @staticmethod
    def _get_release_version_from_dut(dut_host):
        """Get release version from the DUT located in lsb-release file.

        @param dut_host: Host object representing the DUT.

        @return: A string representing the release version.
        """
        return dut_host.get_release_version()

    @staticmethod
    def _get_release_version_from_image(image):
        """Get release version from the image label.

        @param image: The build type and version to install on the host.

        @return: A string representing the release version.
        """
        return image.split('-')[-1]

    @staticmethod
    def _get_latest_release_version_from_server(dut_board):
        """Gets the latest release version for a given board from a dev server.

        @param dut_board: A string representing the board of the remote host.

        @return: A string representing the release version.
        """
        build_target = dut_board + "-release"
        config = global_config.global_config
        server_url_list = config.get_config_value(
                'CROS', 'dev_server', type=list, default=[])
        ds = dev_server.ImageServer(server_url_list[0])
        return ds.get_latest_build_in_server(build_target)

    def update_dut(self, dut_host, image, force=True):
        """The method called by to start the upgrade of a single DUT.

        @param dut_host: Host object representing the DUT.
        @param image: The build type and version to install on the host.
        @param force: If False, will only updated the host if it is not
                      already running the build. If True, force the
                      update regardless, and force a full-reimage.

        """
        logging.debug('Host: %s. Start updating DUT to %s', dut_host, image)

        # If the host is already on the correct build, we have nothing to do.
        dut_release_version = self._get_release_version_from_dut(dut_host)
        image_release_version = self._get_release_version_from_image(image)
        if not force and dut_release_version == image_release_version:
            logging.info('Host: %s. Already running %s',
                         dut_host, image_release_version)
            sys.exit(UPDATE_SUCCESS)

        try:
            ds = dev_server.ImageServer.resolve(image)
            # We need the autotest packages to run the tests.
            ds.stage_artifacts(image, ['full_payload', 'stateful',
                                       'autotest_packages'])
        except dev_server.DevServerException as e:
            error_str = 'Host: ' + dut_host + '. ' + e
            logging.error(error_str)
            sys.exit(UPDATE_FAILURE)

        url = self._get_update_url(ds.url(), image)
        logging.debug('Host: %s. Installing image from %s', dut_host, url)
        try:
            autoupdater.ChromiumOSUpdater(url, host=dut_host).run_update()
        except error.TestFail as e:
            error_str = 'Host: ' + dut_host + '. ' + e
            logging.error(error_str)
            sys.exit(UPDATE_FAILURE)

        dut_release_version = self._get_release_version_from_dut(dut_host)
        if dut_release_version != image_release_version:
            error_str = 'Host: ' + dut_host + '. Expected version of ' + \
                        image_release_version + ' in DUT, but found '  + \
                        dut_release_version + '.'
            logging.error(error_str)
            sys.exit(UPDATE_FAILURE)

        logging.info('Host: %s. Finished updating DUT to %s', dut_host, image)
        sys.exit(UPDATE_SUCCESS)

    def update_dut_pool(self, dut_objects, release_version=""):
        """Updates all the DUT's in the pool to a provided release version.

        @param dut_objects: An array of DUTObjects corresponding to all the
                            DUT's in the DUT pool.
        @param release_version: A chromeOS release version.

        @return: True if all the DUT's successfully upgraded, False otherwise.
        """
        tasks = []
        for dut in dut_objects:
            dut_board = self._get_board_name_from_host(dut.host)
            if release_version == "":
                release_version = self._get_latest_release_version_from_server(
                        dut_board)
            dut_image = self._construct_image_label(dut_board, release_version)
            # Schedule the update for this DUT to the update process pool.
            task = multiprocessing.Process(
                    target=update_dut_worker,
                    args=(self, dut, dut_image, False))
            tasks.append(task)
        # Run the updates in parallel.
        for task in tasks:
            task.start()
        for task in tasks:
            task.join()

        # Check the exit code to determine if the updates were all successful
        # or not.
        for task in tasks:
            if task.exitcode == UPDATE_FAILURE:
                return False
        return True
