# 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 utility functions to help managing servers in server
database (defined in global config section AUTOTEST_SERVER_DB).

After a role is added or removed from a server, certain services may need to
be restarted. For example, scheduler needs to be restarted after a drone is
added to a primary server. This module includes functions to check if actions
are required to be executed and what actions to executed on which servers.
"""

import subprocess
import sys

import common

from autotest_lib.frontend.server import models as server_models
from autotest_lib.site_utils import server_manager_utils
from autotest_lib.site_utils.lib import infra


# Actions that must be executed for server management action to be effective.
# Each action is a tuple:
# (the role of which the command should be executed, the command)
RESTART_SCHEDULER = (server_models.ServerRole.ROLE.SCHEDULER,
                     'sudo service scheduler restart')
RESTART_HOST_SCHEDULER = (server_models.ServerRole.ROLE.HOST_SCHEDULER,
                          'sudo service host-scheduler restart')
RELOAD_APACHE = (server_models.ServerRole.ROLE.SCHEDULER,
                 'sudo service apache reload')

STOP_SCHEDULER = (server_models.ServerRole.ROLE.SCHEDULER,
                  'sudo service scheduler stop')
STOP_HOST_SCHEDULER = (server_models.ServerRole.ROLE.HOST_SCHEDULER,
                       'sudo service host-scheduler stop')

# Dictionary of actions needed for a role to be enabled. Key is the role, and
# value is a list of action. All these actions should be applied after the role
# is added to the server, or the server's status is changed to primary.
ACTIONS_AFTER_ROLE_APPLIED = {
        server_models.ServerRole.ROLE.SCHEDULER: [RESTART_SCHEDULER],
        server_models.ServerRole.ROLE.HOST_SCHEDULER: [RESTART_HOST_SCHEDULER],
        server_models.ServerRole.ROLE.DRONE: [RESTART_SCHEDULER],
        server_models.ServerRole.ROLE.DATABASE:
                [RESTART_SCHEDULER, RESTART_HOST_SCHEDULER, RELOAD_APACHE],
        server_models.ServerRole.ROLE.DEVSERVER: [RESTART_SCHEDULER],
        }

# Dictionary of actions needed for a role to be disabled. Key is the role, and
# value is a list of action.
# Action should be taken before role is deleted from a server, or the server's
# status is changed to primary.
ACTIONS_BEFORE_ROLE_REMOVED = {
        server_models.ServerRole.ROLE.SCHEDULER: [STOP_SCHEDULER],
        server_models.ServerRole.ROLE.HOST_SCHEDULER: [STOP_HOST_SCHEDULER],
        server_models.ServerRole.ROLE.DATABASE:
                [STOP_SCHEDULER, STOP_HOST_SCHEDULER],
        }
# Action should be taken after role is deleted from a server, or the server's
# status is changed to primary.
ACTIONS_AFTER_ROLE_REMOVED = {
        server_models.ServerRole.ROLE.DRONE: [RESTART_SCHEDULER],
        server_models.ServerRole.ROLE.DEVSERVER: [RESTART_SCHEDULER],
        }


def apply(action):
    """Apply an given action.

    It usually involves ssh to the server with specific role and run the
    command, e.g., ssh to scheduler server and restart scheduler.

    @param action: A tuple of (the role of which the command should be executed,
                   the command)
    @raise ServerActionError: If the action can't be applied due to database
                              issue.
    @param subprocess.CalledProcessError: If command is failed to be
                                          executed.
    """
    role = action[0]
    command = action[1]
    # Find the servers with role
    servers = server_manager_utils.get_servers(
            role=role, status=server_models.Server.STATUS.PRIMARY)
    if not servers:
        print >> sys.stderr, ('WARNING! Action %s failed to be applied. No '
                              'server with given role %s was found.' %
                              (action, role))
        return

    for server in servers:
        print 'Run command `%s` on server %s' % (command, server.hostname)
        try:
            infra.execute_command(server.hostname, command)
        except subprocess.CalledProcessError as e:
            print >> sys.stderr, ('Failed to check server %s, error: %s' %
                                  (server.hostname, e))


def try_execute(server, roles, enable, post_change,
                prev_status=server_models.Server.STATUS.REPAIR_REQUIRED,
                do_action=False):
    """Try to execute actions for given role changes of the server.

    @param server: Server that has the role changes.
    @param roles: A list of roles changed.
    @param enable: Set to True if the roles are enabled, i.e., added to server.
                   If it's False, the roles are removed from the server.
    @param post_change: Set to True if to apply actions should be applied after
                        the role changes, otherwise, set to False.
    @param prev_status: The previous status after the status change if any. This
                        is to help to decide if actions should be executed,
                        since actions should be applied if the server's status
                        is changed from primary to other status. Default to
                        repair_required.
    @param do_action: Set to True to execute actions, otherwise, post a warning.
    """
    if not server_manager_utils.use_server_db():
        return
    # This check is to prevent actions to be applied to server not in primary
    # role or server database is not enabled. Note that no action is needed
    # before a server is changed to primary status. If that assumption is
    # no longer valid, this method needs to be updated accordingly.
    if (server.status != server_models.Server.STATUS.PRIMARY and
        prev_status != server_models.Server.STATUS.PRIMARY):
        return

    possible_actions = {}
    if enable:
        if post_change:
            possible_actions = ACTIONS_AFTER_ROLE_APPLIED
    else:
        if post_change:
            possible_actions = ACTIONS_AFTER_ROLE_REMOVED
        else:
            possible_actions = ACTIONS_BEFORE_ROLE_REMOVED

    all_actions = []
    for role in roles:
        all_actions.extend(possible_actions.get(role, []))
    for action in set(all_actions):
        if do_action:
            apply(action)
        else:
            message = ('WARNING! Action %s is skipped. Please manually '
                       'execute the action to make your change effective.' %
                       str(action))
            print >> sys.stderr, message
