#!/usr/bin/env python3
# Copyright 2017 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Custom swarming triggering script.

This script does custom swarming triggering logic, to enable device affinity
for our bots, while lumping all trigger calls under one logical step.

For the perf use case of device affinity, this script now enables soft device
affinity.  This means that it tries to smartly allocate jobs to bots based
on what is currently alive and what bot the task was last triggered on,
preferring that last triggered bot if available.  If the
--multiple-trigger-configs flag is specified than this script overrides
the soft device affinity functionality in favor of the provided ids.

The algorithm is roughly the following:

Find eligible bots, healthy or not.
  * Query swarming for eligible bots based on the dimensions passed in
    on the swarming call.  Determine their health status based on
    is not quarantied and is not is_dead

Of the eligible bots determine what bot id to run the shard on.
(Implementation in _select_config_indices_with_soft_affinity)
  * First query swarming for the last task that ran that shard with
    given dimensions.  Assuming they are returned with most recent first.
  * Check if the bot id that ran that task is alive, if so trigger
    on that bot again.
  * If that bot isn't alive, allocate to another alive bot or if no
    other alive bots exist, trigger on the same dead one.

Scripts inheriting must have roughly the same command line interface as
swarming.py trigger. It modifies it in the following ways:

 * Intercepts the dump-json argument, and creates its own by combining the
   results from each trigger call.
 * Intercepts the dimensions from the swarming call and determines what bots
   are healthy based on the above device affinity algorithm, and triggers
 * Adds a tag to the swarming trigger job with the shard so we know the last
   bot that ran this shard.

This script is normally called from the swarming recipe module in tools/build.

"""

import argparse
import copy
import os
import subprocess
import sys
import logging
import random

import base_test_triggerer

SRC_DIR = os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)
sys.path.append(os.path.join(SRC_DIR, 'tools', 'perf'))

# //tools/perf imports.
import generate_perf_sharding
from core import bot_platforms


class Bot(object):  # pylint: disable=useless-object-inheritance
    """Eligible bots to run the task."""

    def __init__(self, bot_id, is_alive):
        self._bot_id = bot_id
        self._is_alive = is_alive

    def id(self):
        return self._bot_id

    def is_alive(self):
        return self._is_alive

    def as_json_config(self):
        return {'id': self._bot_id}


class PerfDeviceTriggerer(base_test_triggerer.BaseTestTriggerer):
    def __init__(self, args, swarming_args):
        # pylint: disable=super-with-arguments
        super(PerfDeviceTriggerer, self).__init__()
        # pylint: enable=super-with-arguments
        self._sharded_query_failed = False

        if not args.multiple_trigger_configs:
            # Represents the list of current dimensions requested
            # by the parent swarming job.
            self._dimensions = _get_swarming_dimensions(swarming_args)

            # Store what swarming server we need and whether or not we need
            # to send down authentication with it
            self._swarming_server = _get_swarming_server(swarming_args)

            # Map of all existing bots in swarming that satisfy the current
            # set of dimensions indexed by bot id.
            # Note: this assumes perf bot dimensions are unique between
            # configurations.
            self._eligible_bots_by_ids = (
                self._query_swarming_for_eligible_bot_configs(self._dimensions)
            )

        if args.multiple_dimension_script_verbose:
            logging.basicConfig(level=logging.DEBUG)

    def generate_shard_map(self, args, buildername, selected_config):
        shard_map = None
        num_of_shards = len(selected_config)
        builder = bot_platforms.find_bot_platform(buildername)
        if args.use_dynamic_shards and builder and num_of_shards:
            logging.info(
                'Generating dynamic shardmap for builder: %s with %d shards',
                buildername,
                num_of_shards,
            )
            shard_map = generate_perf_sharding.GenerateShardMap(
                builder=builder, num_of_shards=num_of_shards
            )
            for shard_index, bot_index in selected_config:
                bot_id = self._bot_configs[bot_index]['id']
                shard_map['extra_infos']['bot #%s' % shard_index] = bot_id
        return shard_map

    def append_additional_args(self, args, shard_index):
        # Append a tag to the swarming task with the shard number
        # so we can query for the last bot that ran a specific shard.
        tag = 'shard:%d' % shard_index
        shard_tag = ['--tag', tag]
        # Need to append this before the dash if present so it gets fed to
        # the swarming task itself.
        if '--' in args:
            dash_ind = args.index('--')
            return args[:dash_ind] + shard_tag + args[dash_ind:]
        return args + shard_tag

    def parse_bot_configs(self, args):
        if args.multiple_trigger_configs:
            # pylint: disable=super-with-arguments
            super(PerfDeviceTriggerer, self).parse_bot_configs(args)
            # pylint: enable=super-with-arguments
        else:
            self._bot_configs = []
            # For each eligible bot, append the dimension
            # to the eligible bot_configs
            for _, bot in self._eligible_bots_by_ids.items():
                self._bot_configs.append(bot.as_json_config())

    def select_config_indices(self, args):
        if args.multiple_trigger_configs:
            configs = []
            # If specific bot ids were passed in, we want to trigger a job for
            # every valid config regardless of health status since
            # each config represents exactly one bot in the perf swarming pool.
            for index in range(
                len(base_test_triggerer.indices_to_trigger(args))
            ):
                configs.append((index, index))
        if args.use_dynamic_shards:
            return self._select_config_indices_with_dynamic_sharding()
        return self._select_config_indices_with_soft_affinity(args)

    def _select_config_indices_with_dynamic_sharding(self):
        alive_bot_ids = [
            bot_id
            for bot_id, b in self._eligible_bots_by_ids.items()
            if b.is_alive()
        ]
        trigger_count = len(alive_bot_ids)

        indexes = list(range(trigger_count))
        random.shuffle(indexes)
        selected_config = [
            (indexes[i], self._find_bot_config_index(alive_bot_ids[i]))
            for i in range(trigger_count)
        ]
        selected_config.sort()

        for shard_index, bot_index in selected_config:
            logging.info(
                'Shard %d\n\tBot: %s',
                shard_index,
                self._bot_configs[bot_index]['id'],
            )

        return selected_config

    def _select_config_indices_with_soft_affinity(self, args):
        trigger_count = len(base_test_triggerer.indices_to_trigger(args))
        # First make sure the number of shards doesn't exceed the
        # number of eligible bots. This means there is a config error somewhere.
        if trigger_count > len(self._eligible_bots_by_ids):
            _print_device_affinity_info(
                {}, {}, self._eligible_bots_by_ids, trigger_count
            )
            raise ValueError(
                'Not enough available machines exist in swarming '
                'pool.  Shards requested (%d) exceeds available bots '
                '(%d).' % (trigger_count, len(self._eligible_bots_by_ids))
            )

        shard_to_bot_assignment_map = {}
        unallocated_bots_by_ids = copy.deepcopy(self._eligible_bots_by_ids)
        for shard_index in base_test_triggerer.indices_to_trigger(args):
            bot_id = self._query_swarming_for_last_shard_id(shard_index)
            if bot_id and bot_id in unallocated_bots_by_ids:
                bot = unallocated_bots_by_ids[bot_id]
                shard_to_bot_assignment_map[shard_index] = bot
                unallocated_bots_by_ids.pop(bot_id)
            else:
                shard_to_bot_assignment_map[shard_index] = None

        # Maintain the current map for debugging purposes
        existing_shard_bot_to_shard_map = copy.deepcopy(
            shard_to_bot_assignment_map
        )
        # Now create sets of remaining healthy and bad bots
        unallocated_healthy_bots = {
            b for b in unallocated_bots_by_ids.values() if b.is_alive()
        }
        unallocated_bad_bots = {
            b for b in unallocated_bots_by_ids.values() if not b.is_alive()
        }

        # Try assigning healthy bots for new shards first.
        for shard_index, bot in sorted(shard_to_bot_assignment_map.items()):
            if not bot and unallocated_healthy_bots:
                shard_to_bot_assignment_map[shard_index] = (
                    unallocated_healthy_bots.pop()
                )
                logging.info(
                    'First time shard %d has been triggered', shard_index
                )
            elif not bot:
                shard_to_bot_assignment_map[shard_index] = (
                    unallocated_bad_bots.pop()
                )

        # Handle the rest of shards that were assigned dead bots:
        for shard_index, bot in sorted(shard_to_bot_assignment_map.items()):
            if not bot.is_alive() and unallocated_healthy_bots:
                dead_bot = bot
                healthy_bot = unallocated_healthy_bots.pop()
                shard_to_bot_assignment_map[shard_index] = healthy_bot
                logging.info(
                    'Device affinity broken for shard #%d. bot %s is dead,'
                    ' new mapping to bot %s',
                    shard_index,
                    dead_bot.id(),
                    healthy_bot.id(),
                )

        # Now populate the indices into the bot_configs array
        selected_configs = []
        for shard_index in base_test_triggerer.indices_to_trigger(args):
            selected_configs.append(
                (
                    shard_index,
                    self._find_bot_config_index(
                        shard_to_bot_assignment_map[shard_index].id()
                    ),
                )
            )
        _print_device_affinity_info(
            shard_to_bot_assignment_map,
            existing_shard_bot_to_shard_map,
            self._eligible_bots_by_ids,
            trigger_count,
        )
        return selected_configs

    def _query_swarming_for_eligible_bot_configs(self, dimensions):
        """Query Swarming to figure out which bots are available.

        Returns: a dictionary in which the keys are the bot id and
        the values are Bot object that indicate the health status
        of the bots.
        """

        query_result = self.list_bots(dimensions, server=self._swarming_server)
        perf_bots = {}
        for bot in query_result:
            # Device maintenance is usually quick, and we can wait for it to
            # finish. However, if the device is too hot, it can take a long time
            # for it to cool down, so check for 'Device temperature' in
            # maintenance_msg.
            alive = (
                not bot.get('is_dead')
                and not bot.get('quarantined')
                and 'Device temperature' not in bot.get('maintenance_msg', '')
            )
            perf_bots[bot['bot_id']] = Bot(bot['bot_id'], alive)
        return perf_bots

    def _find_bot_config_index(self, bot_id):
        # Find the index into the bot_config map that
        # maps to the bot id in question
        for i, dimensions in enumerate(self._bot_configs):
            if dimensions['id'] == bot_id:
                return i
        return None

    def _query_swarming_for_last_shard_id(self, shard_index):
        """Per shard, query swarming for the last bot that ran the task.

        Example: swarming.py query -S server-url.com --limit 1 \\
          'tasks/list?tags=os:Windows&tags=pool:chrome.tests.perf&tags=shard:12'
        """
        values = ['%s:%s' % (k, v) for k, v in self._dimensions.items()]
        values.sort()

        # Append the shard as a tag
        values_with_shard = list(values)
        values_with_shard.append('%s:%s' % ('shard', str(shard_index)))
        values_with_shard.sort()

        # TODO(eyaich): For now we are ignoring the state of the returned
        # task (ie completed, timed_out, bot_died, etc) as we are just
        # answering the question "What bot did we last trigger this shard on?"
        # Evaluate if this is the right decision going forward.

        # Query for the last task that ran with these dimensions and this shard.
        # Query with the shard param first. This will sometimes time out for
        # queries we've never done before, so try querying without it if that
        # happens.
        try:
            if not self._sharded_query_failed:
                tasks = self.list_tasks(
                    values_with_shard, limit='1', server=self._swarming_server
                )
        except subprocess.CalledProcessError:
            self._sharded_query_failed = True
        if self._sharded_query_failed:
            tasks = self.list_tasks(
                values, limit='1', server=self._swarming_server
            )

        if tasks:
            # We queried with a limit of 1 so we could only get back
            # the most recent which is what we care about.
            task = tasks[0]
            if 'bot_id' in task:
                return task['bot_id']
            for tag in task['tags']:
                if tag.startswith('id:'):
                    return tag[len('id:') :]
        # No eligible shard for this bot
        return None


def _print_device_affinity_info(new_map, existing_map, health_map, num_shards):
    logging.info('')
    for shard_index in range(num_shards):
        existing = existing_map.get(shard_index, None)
        new = new_map.get(shard_index, None)
        existing_id = ''
        if existing:
            existing_id = existing.id()
        new_id = ''
        if new:
            new_id = new.id()
        logging.info(
            'Shard %d\n\tprevious: %s\n\tnew: %s',
            shard_index,
            existing_id,
            new_id,
        )

    healthy_bots = []
    dead_bots = []
    for _, b in health_map.items():
        if b.is_alive():
            healthy_bots.append(b.id())
        else:
            dead_bots.append(b.id())
    logging.info('Shards needed: %d', num_shards)
    logging.info(
        'Total bots (dead + healthy): %d', len(dead_bots) + len(healthy_bots)
    )
    logging.info('Healthy bots, %d: %s', len(healthy_bots), healthy_bots)
    logging.info('Dead Bots, %d: %s', len(dead_bots), dead_bots)
    logging.info('')


def _get_swarming_dimensions(args):
    dimensions = {}
    for i in range(len(args) - 2):
        if args[i] == '--dimension':
            dimensions[args[i + 1]] = args[i + 2]
    return dimensions


def _get_swarming_server(args):
    for i, argument in enumerate(args):
        if '--swarming' in argument:
            server = args[i + 1]
            slashes_index = server.index('//') + 2
            # Strip out the protocol
            return server[slashes_index:]
    return None


def main():
    logging.basicConfig(
        level=logging.INFO,
        format='(%(levelname)s) %(asctime)s pid=%(process)d'
        '  %(module)s.%(funcName)s:%(lineno)d  %(message)s',
    )
    # Setup args for common contract of base class
    parser = base_test_triggerer.BaseTestTriggerer.setup_parser_contract(
        argparse.ArgumentParser(description=__doc__)
    )
    parser.add_argument(
        '--use-dynamic-shards',
        action='store_true',
        required=False,
        help='Ignore --shards and the existing shard map. Will '
        'generate a shard map at run time and use as much '
        'device as possible.',
    )
    args, remaining = parser.parse_known_args()

    triggerer = PerfDeviceTriggerer(args, remaining)
    return triggerer.trigger_tasks(args, remaining)


if __name__ == '__main__':
    sys.exit(main())
