#!/usr/bin/python2

# Copyright (c) 2013 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.
"""A small wrapper script, iterates through
the known hosts and tries to call get_labels()
to discover host functionality, and adds these
detected labels to host.

Limitations:
 - Does not keep a count of how many labels were
   actually added.
 - If a label is added by this script because it
   is detected as supported by get_labels, but later becomes
   unsupported, this script has no way to know that it
   should be removed, so it will remain attached to the host.
   See crosbug.com/38569
"""


from multiprocessing import pool
import logging
import socket
import argparse
import sys

import common

from autotest_lib.server import hosts
from autotest_lib.server import frontend
from autotest_lib.client.common_lib import error


# A list of label prefix that each dut should only have one of such label with
# the given prefix, e.g., a dut can't have both labels of power:battery and
# power:AC_only.
SINGLETON_LABEL_PREFIX = ['power:']

def add_missing_labels(afe, hostname):
    """
    Queries the detectable labels supported by the given host,
    and adds those labels to the host.

    @param afe: A frontend.AFE() instance.
    @param hostname: The host to query and update.

    @return: True on success.
             False on failure to fetch labels or to add any individual label.
    """
    host = None
    try:
        host = hosts.create_host(hostname)
        labels = host.get_labels()
    except socket.gaierror:
        logging.warning('Unable to establish ssh connection to hostname '
                        '%s. Skipping.', hostname)
        return False
    except error.AutoservError:
        logging.warning('Unable to query labels on hostname %s. Skipping.',
                         hostname)
        return False
    finally:
        if host:
            host.close()

    afe_host = afe.get_hosts(hostname=hostname)[0]

    label_matches = afe.get_labels(name__in=labels)

    for label in label_matches:
        singleton_prefixes = [p for p in SINGLETON_LABEL_PREFIX
                              if label.name.startswith(p)]
        if len(singleton_prefixes) == 1:
            singleton_prefix = singleton_prefixes[0]
            # Delete existing label with `singleton_prefix`
            labels_to_delete = [l for l in afe_host.labels
                                if l.startswith(singleton_prefix) and
                                not l in labels]
            if labels_to_delete:
                logging.warning('Removing label %s', labels_to_delete)
                afe_labels_to_delete = afe.get_labels(name__in=labels_to_delete)
                for afe_label in afe_labels_to_delete:
                    afe_label.remove_hosts(hosts=[hostname])
        label.add_hosts(hosts=[hostname])

    missing_labels = set(labels) - set([l.name for l in label_matches])

    if missing_labels:
        for label in missing_labels:
            logging.warning('Unable to add label %s to host %s. '
                            'Skipping unknown label.', label, hostname)
        return False

    return True


def main():
    """"
    Entry point for add_detected_host_labels script.
    """

    parser = argparse.ArgumentParser()
    parser.add_argument('-s', '--silent', dest='silent', action='store_true',
                        help='Suppress all but critical logging messages.')
    parser.add_argument('-i', '--info', dest='info_only', action='store_true',
                        help='Suppress logging messages below INFO priority.')
    parser.add_argument('-m', '--machines', dest='machines',
                        help='Comma separated list of machines to check.')
    options = parser.parse_args()

    if options.silent and options.info_only:
        print 'The -i and -s flags cannot be used together.'
        parser.print_help()
        return 0


    if options.silent:
        logging.disable(logging.CRITICAL)

    if options.info_only:
        logging.disable(logging.DEBUG)

    threadpool = pool.ThreadPool()
    afe = frontend.AFE()

    if options.machines:
        hostnames = [m.strip() for m in options.machines.split(',')]
    else:
        hostnames = afe.get_hostnames()
    successes = sum(threadpool.imap_unordered(
                        lambda x: add_missing_labels(afe, x),
                        hostnames))
    attempts = len(hostnames)

    logging.info('Label updating finished. Failed update on %d out of %d '
                 'hosts.', attempts-successes, attempts)

    return 0


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