#!/usr/bin/env python

# Copyright (c) 2014 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.

"""
This script provides functions to:
1. collect: Collect all hosts and their labels to metaDB, can be scheduled
            run daily, e.g.,
            ./site_utils/host_label_utils.py collect
2. query: Query for hosts and their labels information at a given day, e.g.,
          ./site_utils/host_label_utils.py query -n 172.27.213.193 -l peppy
"""

import argparse
import itertools
import logging
import pprint
import time

import common
from autotest_lib.client.common_lib import time_utils
from autotest_lib.client.common_lib.cros.graphite import autotest_es
from autotest_lib.frontend import setup_django_environment
from autotest_lib.frontend.afe import models


# _type used for ES
_HOST_LABEL_TYPE = 'host_labels'
_HOST_LABEL_TIME_INDEX_TYPE = 'host_labels_time_index'


def get_all_boards(labels=None):
    """Get a list of boards from host labels.

    Scan through all labels of all duts and get all possible boards based on
    label of name board:*

    @param labels: A list of labels to filter hosts.
    @return: A list of board names, e.g., ['peppy', 'daisy']
    """
    host_labels = get_host_labels(labels=labels)
    board_labels = [[label[6:] for label in labels
                     if label.startswith('board:')]
                    for labels in host_labels.values()]
    boards = list(set(itertools.chain.from_iterable(board_labels)))
    return boards


def get_host_labels(days_back=0, hostname=None, labels=None):
    """Get the labels for a given host or all hosts.

    @param days_back: Get the label info around that number of days back. The
                      default is 0, i.e., the latest label information.
    @param hostname: Name of the host, if set to None, return labels for all
                     hosts. Default is None.
    @param labels: A list of labels to filter hosts.
    @return: A dictionary of host labels, key is the hostname, and value is a
             list of labels, e.g.,
             {'host1': ['board:daisy', 'pool:bvt']}
    """
    # Search for the latest logged labels before the given days_back.
    # Default is 0, which means the last time host labels were logged.
    t_end = time.time() - days_back*24*3600
    results = autotest_es.query(
            fields_returned=['time_index'],
            equality_constraints=[('_type', _HOST_LABEL_TIME_INDEX_TYPE),],
            range_constraints=[('time_index', None, t_end)],
            size=1,
            sort_specs=[{'time_index': 'desc'}])
    t_end_str = time_utils.epoch_time_to_date_string(t_end)
    if results.total == 0:
        logging.error('No label information was logged before %s.', t_end_str)
        return
    time_index = results.hits[0]['time_index']
    logging.info('Host labels were recorded at %s',
                 time_utils.epoch_time_to_date_string(time_index))

    # Search for labels for a given host or all hosts, at time_index.
    equality_constraints=[('_type', _HOST_LABEL_TYPE),
                          ('time_index', time_index),]
    if hostname:
        equality_constraints.append(('hostname', hostname))
    if labels:
        for label in labels:
            equality_constraints.append(('labels', label))
    results = autotest_es.query(
            fields_returned=['hostname', 'labels'],
            equality_constraints=equality_constraints)

    host_labels = {}
    for hit in results.hits:
        if 'labels' in hit:
            host_labels[hit['hostname']] = hit['labels']

    return host_labels


def collect_info():
    """Collect label info and report to metaDB.
    """
    # time_index is to index all host labels collected together. It's
    # converted to int to make search faster.
    time_index = int(time.time())
    hosts = models.Host.objects.filter(invalid=False)
    data_list = []
    for host in hosts:
        info = {'_type': _HOST_LABEL_TYPE,
                'hostname': host.hostname,
                'labels': [label.name for label in host.labels.all()],
                'time_index': time_index}
        data_list.append(info)
    autotest_es.bulk_post(data_list, log_time_recorded=False)

    # After all host label information is logged, save the time stamp.
    autotest_es.post(use_http=True, type_str=_HOST_LABEL_TIME_INDEX_TYPE,
                     metadata={'time_index': time_index},
                     log_time_recorded=False)
    logging.info('Finished collecting host labels for %d hosts.', len(hosts))


def main():
    """Main script.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('action',
                        help=('collect or query. Action collect will collect '
                              'all hosts and their labels to metaDB. Action '
                              'query will query for hosts and their labels '
                              'information at a given day'))
    parser.add_argument('-d', '--days_back', type=int, dest='days_back',
                        help=('Number of days before current time. Query will '
                              'get host label information collected before that'
                              ' time. The option is applicable to query only. '
                              'Default to 0, i.e., get the latest label info.'),
                        default=0)
    parser.add_argument('-n', '--hostname', type=str, dest='hostname',
                        help=('Name of the host to query label information for.'
                              'The option is applicable to query only. '
                              'Default to None, i.e., return label info for all'
                              ' hosts.'),
                        default=None)
    parser.add_argument('-l', '--labels', nargs='+', dest='labels',
                        help=('A list of labels to filter hosts. The option is '
                              'applicable to query only. Default to None.'),
                        default=None)
    parser.add_argument('-v', '--verbose', action="store_true", dest='verbose',
                        help='Allow more detail information to be shown.')
    options = parser.parse_args()

    logging.getLogger().setLevel(logging.INFO if options.verbose
                                 else logging.WARN)
    if options.action == 'collect':
        collect_info()
    elif options.action == 'query':
        host_labels = get_host_labels(options.days_back, options.hostname,
                                      options.labels)
        pprint.pprint(host_labels)
    else:
        logging.error('action %s is not supported, can only be collect or '
                      'query!', options.action)


if __name__ == '__main__':
    main()
