#!/usr/bin/python2

# 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 generates a csv file containing the mapping of
(device_hostname, rpm_hostname, outlet, hydra_hostname) for each
host in our lab. The csv file is in the following format.

chromeos-rack2-host1,chromeos-rack2-rpm1,.A1,chromeos-197-hydra1.mtv
chromeos-rack2-host2,chromeos-rack2-rpm1,.A2,chromeos-197-hydra1.mtv
...

The generated csv file can be used as input to add_host_powerunit_info.py

Workflow:
    <Generate the csv file>
    python generate_rpm_mapping.py --csv mapping_file.csv --server cautotest

    <Upload mapping information in csv file to AFE>
    python add_host_powerunit_info.py --csv mapping_file.csv

"""
import argparse
import collections
import logging
import re
import sys

import common

from autotest_lib.client.common_lib import autotest_enum
from autotest_lib.server.cros.dynamic_suite import frontend_wrappers

CHROMEOS_LABS = autotest_enum.AutotestEnum('OysterBay', 'Atlantis',
                                   'Chaos', 'Destiny', start_value=1)
HOST_REGX = 'chromeos(\d+)(-row(\d+))*-rack(\d+)-host(\d+)'
DeviceHostname = collections.namedtuple(
        'DeviceHostname', ['lab', 'row', 'rack', 'host'])


class BaseLabConfig(object):
    """Base class for a lab configuration."""
    RPM_OUTLET_MAP = {}
    LAB_NUMBER = -1

    @classmethod
    def get_rpm_hostname(cls, device_hostname):
        """Get rpm hostname given a device.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: the rpm hostname, default to empty string.

        """
        return ''


    @classmethod
    def get_rpm_outlet(cls, device_hostname):
        """Get rpm outlet given a device.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: the rpm outlet, default to empty string.

        """
        return ''


    @classmethod
    def get_hydra_hostname(cls, device_hostname):
        """Get hydra hostname given a device.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: the hydra hostname, default to empty string.

        """
        return ''


    @classmethod
    def is_device_in_the_lab(cls, device_hostname):
        """Check whether a dut belongs to the lab.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: True if the dut belongs to the lab,
                  False otherwise.

        """
        return device_hostname.lab == cls.LAB_NUMBER


class OysterBayConfig(BaseLabConfig):
    """Configuration for OysterBay"""

    LAB_NUMBER = CHROMEOS_LABS.OYSTERBAY


    @classmethod
    def get_rpm_hostname(cls, device_hostname):
        """Get rpm hostname.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: hostname of the rpm that has the device.

        """
        if not device_hostname.row:
            return ''
        return 'chromeos%d-row%d-rack%d-rpm1' % (
                device_hostname.lab, device_hostname.row,
                device_hostname.rack)


    @classmethod
    def get_rpm_outlet(cls, device_hostname):
        """Get rpm outlet.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: rpm outlet, e.g. '.A1'

        """
        if not device_hostname.row:
            return ''
        return '.A%d' % device_hostname.host


class AtlantisConfig(BaseLabConfig):
    """Configuration for Atlantis lab."""

    LAB_NUMBER = CHROMEOS_LABS.ATLANTIS
    # chromeos2, hostX -> outlet
    RPM_OUTLET_MAP = {
            1: 1,
            7: 2,
            2: 4,
            8: 5,
            3: 7,
            9: 8,
            4: 9,
            10: 10,
            5: 12,
            11: 13,
            6: 15,
            12: 16}

    @classmethod
    def get_rpm_hostname(cls, device_hostname):
        """Get rpm hostname.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: hostname of the rpm that has the device.

        """
        return 'chromeos%d-row%d-rack%d-rpm1' % (
                device_hostname.lab, device_hostname.row,
                device_hostname.rack)


    @classmethod
    def get_rpm_outlet(cls, device_hostname):
        """Get rpm outlet.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: rpm outlet, e.g. '.A1'

        """
        return '.A%d' % cls.RPM_OUTLET_MAP[device_hostname.host]


    @classmethod
    def get_hydra_hostname(cls, device_hostname):
        """Get hydra hostname.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: hydra hostname

        """
        row = device_hostname.row
        rack = device_hostname.rack
        if row >= 1 and row <= 5 and rack >= 1 and rack <= 7:
            return 'chromeos-197-hydra1.cros'
        elif row >= 1 and row <= 5 and rack >= 8 and rack <= 11:
            return 'chromeos-197-hydra2.cros'
        else:
            logging.error('Could not determine hydra for %s',
                          device_hostname)
            return ''


class ChaosConfig(BaseLabConfig):
    """Configuration for Chaos lab."""

    LAB_NUMBER = CHROMEOS_LABS.CHAOS


    @classmethod
    def get_rpm_hostname(cls, device_hostname):
        """Get rpm hostname.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: hostname of the rpm that has the device.

        """
        return 'chromeos%d-row%d-rack%d-rpm1' % (
                device_hostname.lab, device_hostname.row,
                device_hostname.rack)


    @classmethod
    def get_rpm_outlet(cls, device_hostname):
        """Get rpm outlet.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: rpm outlet, e.g. '.A1'

        """
        return '.A%d' % device_hostname.host


class DestinyConfig(BaseLabConfig):
    """Configuration for Desitny lab."""

    LAB_NUMBER = CHROMEOS_LABS.DESTINY
    # None-densified rack: one host per shelf
    # (rowX % 2, hostY) -> outlet
    RPM_OUTLET_MAP = {
            (1, 1): 1,
            (0, 1): 2,
            (1, 2): 4,
            (0, 2): 5,
            (1, 3): 7,
            (0, 3): 8,
            (1, 4): 9,
            (0, 4): 10,
            (1, 5): 12,
            (0, 5): 13,
            (1, 6): 15,
            (0, 6): 16,
    }

    # Densified rack: one shelf can have two chromeboxes or one notebook.
    # (rowX % 2, hostY) -> outlet
    DENSIFIED_RPM_OUTLET_MAP = {
            (1, 2):  1,  (1, 1): 1,
            (0, 1):  2,  (0, 2): 2,
            (1, 4):  3,  (1, 3): 3,
            (0, 3):  4,  (0, 4): 4,
            (1, 6):  5,  (1, 5): 5,
            (0, 5):  6,  (0, 6): 6,
            (1, 8):  7,  (1, 7): 7,
            (0, 7):  8,  (0, 8): 8,
            # outlet 9, 10 are not used
            (1, 10): 11, (1, 9): 11,
            (0, 9):  12, (0, 10): 12,
            (1, 12): 13, (1, 11): 13,
            (0, 11): 14, (0, 12): 14,
            (1, 14): 15, (1, 13): 15,
            (0, 13): 16, (0, 14): 16,
            (1, 16): 17, (1, 15): 17,
            (0, 15): 18, (0, 16): 18,
            (1, 18): 19, (1, 17): 19,
            (0, 17): 20, (0, 18): 20,
            (1, 20): 21, (1, 19): 21,
            (0, 19): 22, (0, 20): 22,
            (1, 22): 23, (1, 21): 23,
            (0, 21): 24, (0, 22): 24,
    }


    @classmethod
    def is_densified(cls, device_hostname):
        """Whether the host is on a densified rack.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: True if on a densified rack, False otherwise.
        """
        return device_hostname.rack in (0, 12, 13)


    @classmethod
    def get_rpm_hostname(cls, device_hostname):
        """Get rpm hostname.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: hostname of the rpm that has the device.

        """
        row = device_hostname.row
        if row == 13:
            logging.warn('Rule not implemented for row 13 in chromeos4')
            return ''

        # rpm row is like chromeos4-row1_2-rackX-rpmY
        rpm_row = ('%d_%d' % (row - 1, row) if row % 2 == 0 else
                   '%d_%d' % (row, row + 1))

        if cls.is_densified(device_hostname):
            # Densified rack has two rpms, decide which one the host belongs to
            # Rule:
            #     odd row number,  even host number -> rpm1
            #     odd row number,  odd host number  -> rpm2
            #     even row number, odd host number  -> rpm1
            #     even row number, even host number -> rpm2
            rpm_number = 1 if (row + device_hostname.host) % 2 == 1 else 2
        else:
            # Non-densified rack only has one rpm
            rpm_number = 1
        return 'chromeos%d-row%s-rack%d-rpm%d' % (
                device_hostname.lab,
                rpm_row, device_hostname.rack, rpm_number)


    @classmethod
    def get_rpm_outlet(cls, device_hostname):
        """Get rpm outlet.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: rpm outlet, e.g. '.A1'

        """
        try:
            outlet_map = (cls.DENSIFIED_RPM_OUTLET_MAP
                          if cls.is_densified(device_hostname) else
                          cls.RPM_OUTLET_MAP)
            outlet_number = outlet_map[(device_hostname.row % 2,
                                        device_hostname.host)]
            return '.A%d' % outlet_number
        except KeyError:
            logging.error('Could not determine outlet for device %s',
                          device_hostname)
            return ''


    @classmethod
    def get_hydra_hostname(cls, device_hostname):
        """Get hydra hostname.

        @param device_hostname: A DeviceHostname named tuple.

        @returns: hydra hostname

        """
        row = device_hostname.row
        rack = device_hostname.rack
        if row >= 1 and row <= 6 and rack >=1 and rack <= 11:
            return 'chromeos-destiny-hydra1.cros'
        elif row >= 7 and row <= 12 and rack >=1 and rack <= 11:
            return 'chromeos-destiny-hydra2.cros'
        elif row >= 1 and row <= 10 and rack >=12 and rack <= 13:
            return 'chromeos-destiny-hydra3.cros'
        elif row in [3, 4, 5, 6, 9, 10] and rack == 0:
            return 'chromeos-destiny-hydra3.cros'
        elif row == 13 and rack >= 0 and rack <= 11:
            return 'chromeos-destiny-hydra3.cros'
        else:
            logging.error('Could not determine hydra hostname for %s',
                          device_hostname)
            return ''


def parse_device_hostname(device_hostname):
    """Parse device_hostname to DeviceHostname object.

    @param device_hostname: A string, e.g. 'chromeos2-row2-rack4-host3'

    @returns: A DeviceHostname named tuple or None if the
              the hostname doesn't follow the pattern
              defined in HOST_REGX.

    """
    m = re.match(HOST_REGX, device_hostname.strip())
    if m:
        return DeviceHostname(
                lab=int(m.group(1)),
                row=int(m.group(3)) if m.group(3) else None,
                rack=int(m.group(4)),
                host=int(m.group(5)))
    else:
        logging.error('Could not parse %s', device_hostname)
        return None


def generate_mapping(hosts, lab_configs):
    """Generate device_hostname-rpm-outlet-hydra mapping.

    @param hosts: hosts objects get from AFE.
    @param lab_configs: A list of configuration classes,
                        each one for a lab.

    @returns: A dictionary that maps device_hostname to
              (rpm_hostname, outlet, hydra_hostname)

    """
    # device hostname -> (rpm_hostname, outlet, hydra_hostname)
    rpm_mapping = {}
    for host in hosts:
        device_hostname = parse_device_hostname(host.hostname)
        if not device_hostname:
            continue
        for lab in lab_configs:
            if lab.is_device_in_the_lab(device_hostname):
                rpm_hostname = lab.get_rpm_hostname(device_hostname)
                rpm_outlet = lab.get_rpm_outlet(device_hostname)
                hydra_hostname = lab.get_hydra_hostname(device_hostname)
                if not rpm_hostname or not rpm_outlet:
                    logging.error(
                            'Skipping device %s: could not determine '
                            'rpm hostname or outlet.', host.hostname)
                    break
                rpm_mapping[host.hostname] = (
                        rpm_hostname, rpm_outlet, hydra_hostname)
                break
        else:
            logging.info(
                    '%s is not in a know lab '
                    '(oyster bay, atlantis, chaos, destiny)',
                    host.hostname)
    return rpm_mapping


def output_csv(rpm_mapping, csv_file):
    """Dump the rpm mapping dictionary to csv file.

    @param rpm_mapping: A dictionary that maps device_hostname to
                        (rpm_hostname, outlet, hydra_hostname)
    @param csv_file: The name of the file to write to.

    """
    with open(csv_file, 'w') as f:
        for hostname, rpm_info in rpm_mapping.iteritems():
            line = ','.join(rpm_info)
            line = ','.join([hostname, line])
            f.write(line + '\n')


if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    parser = argparse.ArgumentParser(
            description='Generate device_hostname-rpm-outlet-hydra mapping '
                        'file needed by add_host_powerunit_info.py')
    parser.add_argument('--csv', type=str, dest='csv_file', required=True,
                        help='The path to the csv file where we are going to '
                             'write the mapping information to.')
    parser.add_argument('--server', type=str, dest='server', default=None,
                        help='AFE server that the script will be talking to. '
                             'If not specified, will default to using the '
                             'server in global_config.ini')
    options = parser.parse_args()

    AFE = frontend_wrappers.RetryingAFE(timeout_min=5, delay_sec=10,
                                        server=options.server)
    logging.info('Connected to %s', AFE.server)
    rpm_mapping = generate_mapping(
            AFE.get_hosts(),
            [OysterBayConfig, AtlantisConfig, ChaosConfig, DestinyConfig])
    output_csv(rpm_mapping, options.csv_file)
