# Lint as: python2, python3
# 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.

"""This module provides functions to manage servers in server database
(defined in global config section AUTOTEST_SERVER_DB).

create(hostname, role=None, note=None)
    Create a server with given role, with status primary.

delete(hostname)
    Delete a server from the database.

modify(hostname, role=None, status=None, note=None, delete=False,
       attribute=None, value=None)
    Modify a server's role, status, note, or attribute:
    1. Add role to a server. If the server is in primary status, proper actions
       like service restart will be executed to enable the role.
    2. Delete a role from a server. If the server is in primary status, proper
       actions like service restart will be executed to disable the role.
    3. Change status of a server. If the server is changed from or to primary
       status, proper actions like service restart will be executed to enable
       or disable each role of the server.
    4. Change note of a server. Note is a field you can add description about
       the server.
    5. Change/delete attribute of a server. Attribute can be used to store
       information about a server. For example, the max_processes count for a
       drone.

"""


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import datetime

import common

from autotest_lib.frontend.server import models as server_models
from autotest_lib.site_utils import server_manager_actions
from autotest_lib.site_utils import server_manager_utils


def _add_role(server, role, action):
    """Add a role to the server.

    @param server: An object of server_models.Server.
    @param role: Role to be added to the server.
    @param action: Execute actions after role or status is changed. Default to
                   False.

    @raise ServerActionError: If role is failed to be added.
    """
    server_models.validate(role=role)
    if role in server.get_role_names():
        raise server_manager_utils.ServerActionError(
                'Server %s already has role %s.' % (server.hostname, role))

    # Verify server
    if not server_manager_utils.check_server(server.hostname, role):
        raise server_manager_utils.ServerActionError(
                'Server %s is not ready for role %s.' % (server.hostname, role))

    if (role in server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE and
        server.status == server_models.Server.STATUS.PRIMARY):
        servers = server_models.Server.objects.filter(
                roles__role=role, status=server_models.Server.STATUS.PRIMARY)
        if len(servers) >= 1:
            raise server_manager_utils.ServerActionError(
                'Role %s must be unique. Server %s already has role %s.' %
                (role, servers[0].hostname, role))

    server_models.ServerRole.objects.create(server=server, role=role)

    # If needed, apply actions to enable the role for the server.
    server_manager_actions.try_execute(server, [role], enable=True,
                                       post_change=True, do_action=action)

    print('Role %s is added to server %s.' % (role, server.hostname))


def _delete_role(server, role, action=False):
    """Delete a role from the server.

    @param server: An object of server_models.Server.
    @param role: Role to be deleted from the server.
    @param action: Execute actions after role or status is changed. Default to
                   False.

    @raise ServerActionError: If role is failed to be deleted.
    """
    server_models.validate(role=role)
    if role not in server.get_role_names():
        raise server_manager_utils.ServerActionError(
                'Server %s does not have role %s.' % (server.hostname, role))

    if server.status == server_models.Server.STATUS.PRIMARY:
        server_manager_utils.warn_missing_role(role, server)

    # Apply actions to disable the role for the server before the role is
    # removed from the server.
    server_manager_actions.try_execute(server, [role], enable=False,
                                       post_change=False, do_action=action)

    print('Deleting role %s from server %s...' % (role, server.hostname))
    server.roles.get(role=role).delete()

    # Apply actions to disable the role for the server after the role is
    # removed from the server.
    server_manager_actions.try_execute(server, [role], enable=False,
                                       post_change=True, do_action=action)

    if (not server.get_role_names() and
        server.status == server_models.Server.STATUS.PRIMARY):
        print ('Server %s has no role.')

    print('Role %s is deleted from server %s.' % (role, server.hostname))


def _change_status(server, status, action):
    """Change the status of the server.

    @param server: An object of server_models.Server.
    @param status: New status of the server.
    @param action: Execute actions after role or status is changed. Default to
                   False.

    @raise ServerActionError: If status is failed to be changed.
    """
    server_models.validate(status=status)
    if server.status == status:
        raise server_manager_utils.ServerActionError(
                'Server %s already has status of %s.' %
                (server.hostname, status))
    if (not server.roles.all() and
        status == server_models.Server.STATUS.PRIMARY):
        raise server_manager_utils.ServerActionError(
                'Server %s has no role associated. Server must have a role to '
                'be in status primary.' % server.hostname)

    # Abort the action if the server's status will be changed to primary and
    # the Autotest instance already has another server running an unique role.
    # For example, a scheduler server is already running, and a repair_required
    # server with role scheduler should not be changed to status primary.
    unique_roles = server.roles.filter(
            role__in=server_models.ServerRole.ROLES_REQUIRE_UNIQUE_INSTANCE)
    if unique_roles and status == server_models.Server.STATUS.PRIMARY:
        for role in unique_roles:
            servers = server_models.Server.objects.filter(
                    roles__role=role.role,
                    status=server_models.Server.STATUS.PRIMARY)
            if len(servers) == 1:
                raise server_manager_utils.ServerActionError(
                        'Role %s must be unique. Server %s already has the '
                        'role.' % (role.role, servers[0].hostname))

    # Post a warning if the server's status will be changed from primary to
    # other value and the server is running a unique role across database, e.g.
    # scheduler.
    if server.status == server_models.Server.STATUS.PRIMARY:
        for role in server.get_role_names():
            server_manager_utils.warn_missing_role(role, server)

    enable = status == server_models.Server.STATUS.PRIMARY
    server_manager_actions.try_execute(server, server.get_role_names(),
                                       enable=enable, post_change=False,
                                       do_action=action)

    prev_status = server.status
    server.status = status
    server.save()

    # Apply actions to enable/disable roles of the server after the status is
    # changed.
    server_manager_actions.try_execute(server, server.get_role_names(),
                                       enable=enable, post_change=True,
                                       prev_status=prev_status,
                                       do_action=action)

    print('Status of server %s is changed from %s to %s. Affected roles: %s' %
          (server.hostname, prev_status, status,
           ', '.join(server.get_role_names())))


@server_manager_utils.verify_server(exist=False)
def create(hostname, role=None, note=None):
    """Create a new server.

    The status of new server will always be primary.

    @param hostname: hostname of the server.
    @param role: role of the new server, default to None.
    @param note: notes about the server, default to None.

    @return: A Server object that contains the server information.
    """
    server_models.validate(hostname=hostname, role=role)
    server = server_models.Server.objects.create(
            hostname=hostname, status=server_models.Server.STATUS.PRIMARY,
            note=note, date_created=datetime.datetime.now())
    server_models.ServerRole.objects.create(server=server, role=role)
    return server


@server_manager_utils.verify_server()
def delete(hostname, server=None):
    """Delete given server from server database.

    @param hostname: hostname of the server to be deleted.
    @param server: Server object from database query, this argument should be
                   injected by the verify_server_exists decorator.

    @raise ServerActionError: If delete server action failed, e.g., server is
            not found in database.
    """
    print('Deleting server %s from server database.' % hostname)

    if (server_manager_utils.use_server_db() and
        server.status == server_models.Server.STATUS.PRIMARY):
        print('Server %s is in status primary, need to disable its '
              'current roles first.' % hostname)
        for role in server.roles.all():
            _delete_role(server, role.role)

    server.delete()
    print('Server %s is deleted from server database.' % hostname)


@server_manager_utils.verify_server()
def modify(hostname, role=None, status=None, delete=False, note=None,
           attribute=None, value=None, action=False, server=None):
    """Modify given server with specified actions.

    @param hostname: hostname of the server to be modified.
    @param role: Role to be added to the server.
    @param status: Modify server status.
    @param delete: True to delete given role from the server, default to False.
    @param note: Note of the server.
    @param attribute: Name of an attribute of the server.
    @param value: Value of an attribute of the server.
    @param action: Execute actions after role or status is changed. Default to
                   False.
    @param server: Server object from database query, this argument should be
                   injected by the verify_server_exists decorator.

    @raise InvalidDataError: If the operation failed with any wrong value of
                             the arguments.
    @raise ServerActionError: If any operation failed.
    """
    if role:
        if not delete:
            _add_role(server, role, action)
        else:
            _delete_role(server, role, action)

    if status:
        _change_status(server, status, action)

    if note is not None:
        server.note = note
        server.save()

    if attribute and value:
        server_manager_utils.change_attribute(server, attribute, value)
    elif attribute and delete:
        server_manager_utils.delete_attribute(server, attribute)

    return server
