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

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

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('WARNING! Action %s failed to be applied. No '
              'server with given role %s was found.' % (action, role),
              file=sys.stderr)
        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('Failed to check server %s, error: %s' %
                  (server.hostname, e), file=sys.stderr)


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(message, file=sys.stderr)
