# Copyright 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.

"""
The server module contains the objects and methods used to manage servers in
Autotest.

The valid actions are:
list:      list all servers in the database
create:    create a server
delete:    deletes a server
modify:    modify a server's role or status.

The common options are:
--role / -r:     role that's related to server actions.

See topic_common.py for a High Level Design and Algorithm.
"""

import common

from autotest_lib.cli import action_common
from autotest_lib.cli import topic_common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import global_config
# The django setup is moved here as test_that uses sqlite setup. If this line
# is in server_manager, test_that unittest will fail.
from autotest_lib.frontend import setup_django_environment
from autotest_lib.site_utils import server_manager
from autotest_lib.site_utils import server_manager_utils

RESPECT_SKYLAB_SERVERDB = global_config.global_config.get_config_value(
        'SKYLAB', 'respect_skylab_serverdb', type=bool, default=False)
ATEST_DISABLE_MSG = ('Updating server_db via atest server command has been '
                     'disabled. Please use use go/cros-infra-inventory-tool '
                     'to update it in skylab inventory service.')


class server(topic_common.atest):
    """Server class

    atest server [list|create|delete|modify] <options>
    """
    usage_action = '[list|create|delete|modify]'
    topic = msg_topic = 'server'
    msg_items = '<server>'

    def __init__(self, hostname_required=True):
        """Add to the parser the options common to all the server actions.

        @param hostname_required: True to require the command has hostname
                                  specified. Default is True.
        """
        super(server, self).__init__()

        self.parser.add_option('-r', '--role',
                               help='Name of a role',
                               type='string',
                               default=None,
                               metavar='ROLE')
        self.parser.add_option('-x', '--action',
                               help=('Set to True to apply actions when role '
                                     'or status is changed, e.g., restart '
                                     'scheduler when a drone is removed.'),
                               action='store_true',
                               default=False,
                               metavar='ACTION')

        self.topic_parse_info = topic_common.item_parse_info(
                attribute_name='hostname', use_leftover=True)

        self.hostname_required = hostname_required


    def parse(self):
        """Parse command arguments.
        """
        role_info = topic_common.item_parse_info(attribute_name='role')
        kwargs = {}
        if self.hostname_required:
            kwargs['req_items'] = 'hostname'
        (options, leftover) = super(server, self).parse([role_info], **kwargs)
        if options.web_server:
            self.invalid_syntax('Server actions will access server database '
                                'defined in your local global config. It does '
                                'not rely on RPC, no autotest server needs to '
                                'be specified.')

        # self.hostname is a list. Action on server only needs one hostname at
        # most.
        if ((not self.hostname and self.hostname_required) or
            len(self.hostname) > 1):
            self.invalid_syntax('`server` topic can only manipulate 1 server. '
                                'Use -h to see available options.')
        if self.hostname:
            # Override self.hostname with the first hostname in the list.
            self.hostname = self.hostname[0]
        self.role = options.role
        return (options, leftover)


    def output(self, results):
        """Display output.

        For most actions, the return is a string message, no formating needed.

        @param results: return of the execute call.
        """
        print results


class server_help(server):
    """Just here to get the atest logic working. Usage is set by its parent.
    """
    pass


class server_list(action_common.atest_list, server):
    """atest server list [--role <role>]"""

    def __init__(self):
        """Initializer.
        """
        super(server_list, self).__init__(hostname_required=False)
        self.parser.add_option('-t', '--table',
                               help=('List details of all servers in a table, '
                                     'e.g., \tHostname | Status  | Roles     | '
                                     'note\t\tserver1  | primary | scheduler | '
                                     'lab'),
                               action='store_true',
                               default=False)
        self.parser.add_option('-s', '--status',
                               help='Only show servers with given status',
                               type='string',
                               default=None,
                               metavar='STATUS')
        self.parser.add_option('-u', '--summary',
                               help=('Show the summary of roles and status '
                                     'only, e.g.,\tscheduler: server1(primary) '
                                     'server2(backup)\t\tdrone: server3(primary'
                                     ') server4(backup)'),
                               action='store_true',
                               default=False)
        self.parser.add_option('--json',
                               help='Format output as JSON.',
                               action='store_true',
                               default=False)
        self.parser.add_option('-N', '--hostnames-only',
                               help='Only return hostnames.',
                               action='store_true',
                               default=False)


    def parse(self):
        """Parse command arguments.
        """
        (options, leftover) = super(server_list, self).parse()
        self.json = options.json
        self.table = options.table
        self.status = options.status
        self.summary = options.summary
        self.namesonly = options.hostnames_only
        if sum([self.table, self.summary, self.json, self.namesonly]) > 1:
            self.invalid_syntax('May only specify up to 1 output-format flag.')
        return (options, leftover)


    def execute(self):
        """Execute the command.

        @return: A list of servers matched given hostname and role.
        """
        try:
            return server_manager_utils.get_servers(hostname=self.hostname,
                                                    role=self.role,
                                                    status=self.status)
        except (server_manager_utils.ServerActionError,
                error.InvalidDataError) as e:
            self.failure(e, what_failed='Failed to find servers',
                         item=self.hostname, fatal=True)


    def output(self, results):
        """Display output.

        @param results: return of the execute call, a list of server object that
                        contains server information.
        """
        if results:
            if self.json:
                formatter = server_manager_utils.format_servers_json
            elif self.table:
                formatter = server_manager_utils.format_servers_table
            elif self.summary:
                formatter = server_manager_utils.format_servers_summary
            elif self.namesonly:
                formatter = server_manager_utils.format_servers_nameonly
            else:
                formatter = server_manager_utils.format_servers
            print formatter(results)
        else:
            self.failure('No server is found.',
                         what_failed='Failed to find servers',
                         item=self.hostname, fatal=True)


class server_create(server):
    """atest server create hostname --role <role> --note <note>
    """

    def __init__(self):
        """Initializer.
        """
        super(server_create, self).__init__()
        self.parser.add_option('-n', '--note',
                               help='note of the server',
                               type='string',
                               default=None,
                               metavar='NOTE')


    def parse(self):
        """Parse command arguments.
        """
        (options, leftover) = super(server_create, self).parse()
        self.note = options.note

        if not self.role:
            self.invalid_syntax('--role is required to create a server.')

        return (options, leftover)


    def execute(self):
        """Execute the command.

        @return: A Server object if it is created successfully.
        """
        if RESPECT_SKYLAB_SERVERDB:
            self.failure(ATEST_DISABLE_MSG,
                         what_failed='Failed to create server',
                         item=self.hostname, fatal=True)

        try:
            return server_manager.create(hostname=self.hostname, role=self.role,
                                         note=self.note)
        except (server_manager_utils.ServerActionError,
                error.InvalidDataError) as e:
            self.failure(e, what_failed='Failed to create server',
                         item=self.hostname, fatal=True)


    def output(self, results):
        """Display output.

        @param results: return of the execute call, a server object that
                        contains server information.
        """
        if results:
            print 'Server %s is added to server database:\n' % self.hostname
            print results


class server_delete(server):
    """atest server delete hostname"""

    def execute(self):
        """Execute the command.

        @return: True if server is deleted successfully.
        """
        if RESPECT_SKYLAB_SERVERDB:
            self.failure(ATEST_DISABLE_MSG,
                         what_failed='Failed to delete server',
                         item=self.hostname, fatal=True)

        try:
            server_manager.delete(hostname=self.hostname)
            return True
        except (server_manager_utils.ServerActionError,
                error.InvalidDataError) as e:
            self.failure(e, what_failed='Failed to delete server',
                         item=self.hostname, fatal=True)


    def output(self, results):
        """Display output.

        @param results: return of the execute call.
        """
        if results:
            print ('Server %s is deleted from server database successfully.' %
                   self.hostname)


class server_modify(server):
    """atest server modify hostname

    modify action can only change one input at a time. Available inputs are:
    --status:       Status of the server.
    --note:         Note of the server.
    --role:         New role to be added to the server.
    --delete_role:  Existing role to be deleted from the server.
    """

    def __init__(self):
        """Initializer.
        """
        super(server_modify, self).__init__()
        self.parser.add_option('-s', '--status',
                               help='Status of the server',
                               type='string',
                               metavar='STATUS')
        self.parser.add_option('-n', '--note',
                               help='Note of the server',
                               type='string',
                               default=None,
                               metavar='NOTE')
        self.parser.add_option('-d', '--delete',
                               help=('Set to True to delete given role.'),
                               action='store_true',
                               default=False,
                               metavar='DELETE')
        self.parser.add_option('-a', '--attribute',
                               help='Name of the attribute of the server',
                               type='string',
                               default=None,
                               metavar='ATTRIBUTE')
        self.parser.add_option('-e', '--value',
                               help='Value for the attribute of the server',
                               type='string',
                               default=None,
                               metavar='VALUE')


    def parse(self):
        """Parse command arguments.
        """
        (options, leftover) = super(server_modify, self).parse()
        self.status = options.status
        self.note = options.note
        self.delete = options.delete
        self.attribute = options.attribute
        self.value = options.value
        self.action = options.action

        # modify supports various options. However, it's safer to limit one
        # option at a time so no complicated role-dependent logic is needed
        # to handle scenario that both role and status are changed.
        # self.parser is optparse, which does not have function in argparse like
        # add_mutually_exclusive_group. That's why the count is used here.
        flags = [self.status is not None, self.role is not None,
                 self.attribute is not None, self.note is not None]
        if flags.count(True) != 1:
            msg = ('Action modify only support one option at a time. You can '
                   'try one of following 5 options:\n'
                   '1. --status:                Change server\'s status.\n'
                   '2. --note:                  Change server\'s note.\n'
                   '3. --role with optional -d: Add/delete role from server.\n'
                   '4. --attribute --value:     Set/change the value of a '
                   'server\'s attribute.\n'
                   '5. --attribute -d:          Delete the attribute from the '
                   'server.\n'
                   '\nUse option -h to see a complete list of options.')
            self.invalid_syntax(msg)
        if (self.status != None or self.note != None) and self.delete:
            self.invalid_syntax('--delete does not apply to status or note.')
        if self.attribute != None and not self.delete and self.value == None:
            self.invalid_syntax('--attribute must be used with option --value '
                                'or --delete.')
        return (options, leftover)


    def execute(self):
        """Execute the command.

        @return: The updated server object if it is modified successfully.
        """
        if RESPECT_SKYLAB_SERVERDB:
            self.failure(ATEST_DISABLE_MSG,
                         what_failed='Failed to modify server',
                         item=self.hostname, fatal=True)

        try:
            return server_manager.modify(hostname=self.hostname, role=self.role,
                                         status=self.status, delete=self.delete,
                                         note=self.note,
                                         attribute=self.attribute,
                                         value=self.value, action=self.action)
        except (server_manager_utils.ServerActionError,
                error.InvalidDataError) as e:
            self.failure(e, what_failed='Failed to modify server',
                         item=self.hostname, fatal=True)


    def output(self, results):
        """Display output.

        @param results: return of the execute call, which is the updated server
                        object.
        """
        if results:
            print 'Server %s is modified successfully.' % self.hostname
            print results
