# 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 provisioner
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)
        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:
            provisioner.ChromiumOSProvisioner(url,
                                              host=dut_host).run_provision()
        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
