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


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.
        """
        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.
        """
        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.
        """
        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
