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

import logging
import os

import common
from autotest_lib.client.common_lib import error

"""
Functions to query and control debugd dev tools.

This file provides a set of functions to check the general state of the
debugd dev tools, and a set of classes to interface to the individual
tools.

Current tool classes are:
    RootfsVerificationTool
    BootFromUsbTool
    SshServerTool
    SystemPasswordTool
These classes have functions to check the state and enable/disable the
tool. Some tools may not be able to disable themselves, in which case
an exception will be thrown (for example, RootfsVerificationTool cannot
be disabled).

General usage will look something like this:

# Make sure tools are accessible on the system.
if debugd_dev_tools.are_dev_tools_available(host):
    # Create the tool(s) you want to interact with.
    tools = [debugd_dev_tools.SshServerTool(), ...]
    for tool in tools:
        # Initialize tools and save current state.
        tool.initialize(host, save_initial_state=True)
        # Perform required action with tools.
        tool.enable()
        # Restore initial tool state.
        tool.restore_state()
    # Clean up temporary files.
    debugd_dev_tools.remove_temp_files()
"""


# Defined in system_api/dbus/service_constants.h.
DEV_FEATURES_DISABLED = 1 << 0
DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED = 1 << 1
DEV_FEATURE_BOOT_FROM_USB_ENABLED = 1 << 2
DEV_FEATURE_SSH_SERVER_CONFIGURED = 1 << 3
DEV_FEATURE_DEV_MODE_ROOT_PASSWORD_SET = 1 << 4
DEV_FEATURE_SYSTEM_ROOT_PASSWORD_SET = 1 << 5


# Location to save temporary files to store and load state. This folder should
# be persistent through a power cycle so we can't use /tmp.
_TEMP_DIR = '/usr/local/autotest/tmp/debugd_dev_tools'


class AccessError(error.CmdError):
    """Raised when debugd D-Bus access fails."""
    pass


class FeatureUnavailableError(error.TestNAError):
    """Raised when a feature cannot be enabled or disabled."""
    pass


def query_dev_tools_state(host):
    """
    Queries debugd for the current dev features state.

    @param host: Host device.

    @return: Integer debugd query return value.

    @raise AccessError: Can't talk to debugd on the host.
    """
    result = _send_debugd_command(host, 'QueryDevFeatures')
    state = int(result.stdout)
    logging.debug('query_dev_tools_state = %d (0x%04X)', state, state)
    return state


def are_dev_tools_available(host):
    """
    Check if dev tools are available on the host.

    @param host: Host device.

    @return: True if tools are available, False otherwise.
    """
    try:
        return query_dev_tools_state(host) != DEV_FEATURES_DISABLED
    except AccessError:
        return False


def remove_temp_files(host):
    """
    Removes all DevTools temporary files and directories.

    Any test using dev tools should try to call this just before
    exiting to erase any temporary files that may have been saved.

    @param host: Host device.
    """
    host.run('rm -rf "%s"' % _TEMP_DIR)


def expect_access_failure(host, tools):
    """
    Verifies that access is denied to all provided tools.

    Will check are_dev_tools_available() first to try to avoid changing
    device state in case access is allowed. Otherwise, the function
    will try to enable each tool in the list and throw an exception if
    any succeeds.

    @param host: Host device.
    @param tools: List of tools to checks.

    @raise TestFail: are_dev_tools_available() returned True or
                     a tool successfully enabled.
    """
    if are_dev_tools_available(host):
        raise error.TestFail('Unexpected dev tool access success')
    for tool in tools:
        try:
            tool.enable()
        except AccessError:
            # We want an exception, otherwise the tool succeeded.
            pass
        else:
            raise error.TestFail('Unexpected %s enable success.' % tool)


def _send_debugd_command(host, name, args=()):
    """
    Sends a debugd command.

    @param host: Host to run the command on.
    @param name: String debugd D-Bus function name.
    @param args: List of string arguments to pass to dbus-send.

    @return: The dbus-send CmdResult object.

    @raise AccessError: debugd call returned an error.
    """
    command = ('dbus-send --system --fixed --print-reply '
               '--dest=org.chromium.debugd /org/chromium/debugd '
               '"org.chromium.debugd.%s"' % name)
    for arg in args:
        command += ' %s' % arg
    try:
        return host.run(command)
    except error.CmdError as e:
        raise AccessError(e.command, e.result_obj, e.additional_text)


class DevTool(object):
    """
    Parent tool class.

    Each dev tool has its own child class that handles the details
    of disabling, enabling, and querying the functionality. This class
    provides some common functionality needed by multiple tools.

    Child classes should implement the following:
      - is_enabled(): use debugd to query whether the tool is enabled.
      - enable(): use debugd to enable the tool.
      - disable(): manually disable the tool.
      - save_state(): record the current tool state on the host.
      - restore_state(): restore the saved tool state.

    If a child class cannot perform the required action (for
    example the rootfs tool can't currently restore its initial
    state), leave the function unimplemented so it will throw an
    exception if a test attempts to use it.
    """


    def initialize(self, host, save_initial_state=False):
        """
        Sets up the initial tool state. This must be called on
        every tool before use.

        @param host: Device host the test is running on.
        @param save_initial_state: True to save the device state.
        """
        self._host = host
        if save_initial_state:
            self.save_state()


    def is_enabled(self):
        """
        Each tool should override this to query itself using debugd.
        Normally this can be done by using the provided
        _check_enabled() function.
        """
        self._unimplemented_function_error('is_enabled')


    def enable(self):
        """
        Each tool should override this to enable itself using debugd.
        """
        self._unimplemented_function_error('enable')


    def disable(self):
        """
        Each tool should override this to disable itself.
        """
        self._unimplemented_function_error('disable')


    def save_state(self):
        """
        Save the initial tool state. Should be overridden by child
        tool classes.
        """
        self._unimplemented_function_error('_save_state')


    def restore_state(self):
        """
        Restore the initial tool state. Should be overridden by child
        tool classes.
        """
        self._unimplemented_function_error('_restore_state')


    def _check_enabled(self, bits):
        """
        Checks if the given feature is currently enabled according to
        the debugd status query function.

        @param bits: Integer status bits corresponding to the features.

        @return: True if the status query is enabled and the
                 indicated bits are all set, False otherwise.
        """
        state = query_dev_tools_state(self._host)
        enabled = bool((state != DEV_FEATURES_DISABLED) and
                       (state & bits == bits))
        logging.debug('%s _check_enabled = %s (0x%04X / 0x%04X)',
                      self, enabled, state, bits)
        return enabled


    def _get_temp_path(self, source_path):
        """
        Get temporary storage path for a file or directory.

        Temporary path is based on the tool class name and the
        source directory to keep tool files isolated and prevent
        name conflicts within tools.

        The function returns a full temporary path corresponding to
        |source_path|.

        For example, _get_temp_path('/foo/bar.txt') would return
        '/path/to/temp/folder/debugd_dev_tools/FooTool/foo/bar.txt'.

        @param source_path: String path to the file or directory.

        @return: Temp path string.
        """
        return '%s/%s/%s' % (_TEMP_DIR, self, source_path)


    def _save_files(self, paths):
        """
        Saves a set of files to a temporary location.

        This can be used to save specific files so that a tool can
        save its current state before starting a test.

        See _restore_files() for restoring the saved files.

        @param paths: List of string paths to save.
        """
        for path in paths:
            temp_path = self._get_temp_path(path)
            self._host.run('mkdir -p "%s"' % os.path.dirname(temp_path))
            self._host.run('cp -r "%s" "%s"' % (path, temp_path),
                           ignore_status=True)


    def _restore_files(self, paths):
        """
        Restores saved files to their original location.

        Used to restore files that have previously been saved by
        _save_files(), usually to return the device to its initial
        state.

        This function does not erase the saved files, so it can
        be used multiple times if needed.

        @param paths: List of string paths to restore.
        """
        for path in paths:
            self._host.run('rm -rf "%s"' % path)
            self._host.run('cp -r "%s" "%s"' % (self._get_temp_path(path),
                                                path),
                           ignore_status=True)


    def _unimplemented_function_error(self, function_name):
        """
        Throws an exception if a required tool function hasn't been
        implemented.
        """
        raise FeatureUnavailableError('%s has not implemented %s()' %
                                      (self, function_name))


    def __str__(self):
        """
        Tool name accessor for temporary files and logging.

        Based on class rather than unique instance naming since all
        instances of the same tool have identical functionality.
        """
        return type(self).__name__


class RootfsVerificationTool(DevTool):
    """
    Rootfs verification removal tool.

    This tool is currently unable to transition from non-verified back
    to verified rootfs; it may potentially require re-flashing an OS.
    Since devices in the test lab run in verified mode, this tool is
    unsuitable for automated testing until this capability is
    implemented.
    """


    def is_enabled(self):
        return self._check_enabled(DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED)


    def enable(self):
        _send_debugd_command(self._host, 'RemoveRootfsVerification')
        self._host.reboot()


    def disable(self):
        raise FeatureUnavailableError('Cannot re-enable rootfs verification')


class BootFromUsbTool(DevTool):
    """USB boot configuration tool."""


    def is_enabled(self):
        return self._check_enabled(DEV_FEATURE_BOOT_FROM_USB_ENABLED)


    def enable(self):
        _send_debugd_command(self._host, 'EnableBootFromUsb')


    def disable(self):
        self._host.run('crossystem dev_boot_usb=0')


    def save_state(self):
        self.initial_state = self.is_enabled()


    def restore_state(self):
        if self.initial_state:
            self.enable()
        else:
            self.disable()


class SshServerTool(DevTool):
    """
    SSH server tool.

    SSH configuration has two components, the init file and the test
    keys. Since a system could potentially have none, just the init
    file, or all files, we want to be sure to restore just the files
    that existed before the test started.
    """


    PATHS = ('/etc/init/openssh-server.conf',
             '/root/.ssh/authorized_keys',
             '/root/.ssh/id_rsa',
             '/root/.ssh/id_rsa.pub')


    def is_enabled(self):
        return self._check_enabled(DEV_FEATURE_SSH_SERVER_CONFIGURED)


    def enable(self):
        _send_debugd_command(self._host, 'ConfigureSshServer')


    def disable(self):
        for path in self.PATHS:
            self._host.run('rm -f %s' % path)


    def save_state(self):
        self._save_files(self.PATHS)


    def restore_state(self):
        self._restore_files(self.PATHS)


class SystemPasswordTool(DevTool):
    """
    System password configuration tool.

    This tool just affects the system password (/etc/shadow). We could
    add a devmode password tool if we want to explicitly test that as
    well.
    """


    SYSTEM_PATHS = ('/etc/shadow',)
    DEV_PATHS = ('/mnt/stateful_partition/etc/devmode.passwd',)


    def is_enabled(self):
        return self._check_enabled(DEV_FEATURE_SYSTEM_ROOT_PASSWORD_SET)


    def enable(self):
        # Save the devmode.passwd file to avoid affecting it.
        self._save_files(self.DEV_PATHS)
        try:
            _send_debugd_command(self._host, 'SetUserPassword',
                                 ('string:root', 'string:test0000'))
        finally:
            # Restore devmode.passwd
            self._restore_files(self.DEV_PATHS)


    def disable(self):
        self._host.run('passwd -d root')


    def save_state(self):
        self._save_files(self.SYSTEM_PATHS)


    def restore_state(self):
        self._restore_files(self.SYSTEM_PATHS)
