# Copyright (c) 2013 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.

"""
Sonic host.

This host can perform actions either over ssh or by submitting requests to
an http server running on the client. Though the server provides flexibility
and allows us to test things at a modular level, there are times we must
resort to ssh (eg: to reboot into recovery). The server exposes the same stack
that the chromecast extension needs to communicate with the sonic device, so
any test involving an sonic host will fail if it cannot submit posts/gets
to the server. In cases where we can achieve the same action over ssh or
the rpc server, we choose the rpc server by default, because several existing
sonic tests do the same.
"""

import logging
import os

import common

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import autotemp
from autotest_lib.client.common_lib import error
from autotest_lib.server import site_utils
from autotest_lib.server.cros import sonic_client_utils
from autotest_lib.server.cros.dynamic_suite import constants
from autotest_lib.server.hosts import abstract_ssh


class SonicHost(abstract_ssh.AbstractSSHHost):
    """This class represents a sonic host."""

    # Maximum time a reboot can take.
    REBOOT_TIME = 360

    COREDUMP_DIR = '/data/coredump'
    OTA_LOCATION = '/cache/ota.zip'
    RECOVERY_DIR = '/cache/recovery'
    COMMAND_FILE = os.path.join(RECOVERY_DIR, 'command')
    PLATFORM = 'sonic'
    LABELS = [sonic_client_utils.SONIC_BOARD_LABEL]


    @staticmethod
    def check_host(host, timeout=10):
        """
        Check if the given host is a sonic host.

        @param host: An ssh host representing a device.
        @param timeout: The timeout for the run command.

        @return: True if the host device is sonic.

        @raises AutoservRunError: If the command failed.
        @raises AutoservSSHTimeout: Ssh connection has timed out.
        """
        try:
            result = host.run('getprop ro.product.device', timeout=timeout)
        except (error.AutoservRunError, error.AutoservSSHTimeout,
                error.AutotestHostRunError):
            return False
        return 'anchovy' in result.stdout


    def _initialize(self, hostname, *args, **dargs):
        super(SonicHost, self)._initialize(hostname=hostname, *args, **dargs)

        # Sonic devices expose a server that can respond to json over http.
        self.client = sonic_client_utils.SonicProxy(hostname)


    def enable_test_extension(self):
        """Enable a chromecast test extension on the sonic host.

        Appends the extension id to the list of accepted cast
        extensions, without which the sonic device will fail to
        respond to any Dial requests submitted by the extension.

        @raises CmdExecutionError: If the expected files are not found
            on the sonic host.
        """
        extension_id = sonic_client_utils.get_extension_id()
        tempdir = autotemp.tempdir()
        local_dest = os.path.join(tempdir.name, 'content_shell.sh')
        remote_src = '/system/usr/bin/content_shell.sh'
        whitelist_flag = '--extra-cast-extension-ids'

        try:
            self.run('mount -o rw,remount /system')
            self.get_file(remote_src, local_dest)
            with open(local_dest) as f:
                content = f.read()
                if extension_id in content:
                    return
                if whitelist_flag in content:
                    append_str = ',%s' % extension_id
                else:
                    append_str = ' %s=%s' % (whitelist_flag, extension_id)

            with open(local_dest, 'a') as f:
                f.write(append_str)
            self.send_file(local_dest, remote_src)
            self.reboot()
        finally:
            tempdir.clean()


    def get_boot_id(self, timeout=60):
        """Get a unique ID associated with the current boot.

        @param timeout The number of seconds to wait before timing out, as
            taken by base_utils.run.

        @return A string unique to this boot or None if not available.
        """
        BOOT_ID_FILE = '/proc/sys/kernel/random/boot_id'
        cmd = 'cat %r' % (BOOT_ID_FILE)
        return self.run(cmd, timeout=timeout).stdout.strip()


    def get_platform(self):
        return self.PLATFORM


    def get_labels(self):
        return self.LABELS


    def ssh_ping(self, timeout=60, base_cmd=''):
        """Checks if we can ssh into the host and run getprop.

        Ssh ping is vital for connectivity checks and waiting on a reboot.
        A simple true check, or something like if [ 0 ], is not guaranteed
        to always exit with a successful return value.

        @param timeout: timeout in seconds to wait on the ssh_ping.
        @param base_cmd: The base command to use to confirm that a round
            trip ssh works.
        """
        super(SonicHost, self).ssh_ping(timeout=timeout,
                                         base_cmd="getprop>/dev/null")


    def verify_software(self):
        """Verified that the server on the client device is responding to gets.

        The server on the client device is crucial for the sonic device to
        communicate with the chromecast extension. Device verify on the whole
        consists of verify_(hardware, connectivity and software), ssh
        connectivity is verified in the base class' verify_connectivity.

        @raises: SonicProxyException if the server doesn't respond.
        """
        self.client.check_server()


    def get_build_number(self, timeout_mins=1):
        """
        Gets the build number on the sonic device.

        Since this method is usually called right after a reboot/install,
        it has retries built in.

        @param timeout_mins: The timeout in minutes.

        @return: The build number of the build on the host.

        @raises TimeoutError: If we're unable to get the build number within
            the specified timeout.
        @raises ValueError: If the build number returned isn't an integer.
        """
        cmd = 'getprop ro.build.version.incremental'
        timeout = timeout_mins * 60
        cmd_result = utils.poll_for_condition(
                        lambda: self.run(cmd, timeout=timeout/10),
                        timeout=timeout, sleep_interval=timeout/10)
        return int(cmd_result.stdout)


    def get_kernel_ver(self):
        """Returns the build number of the build on the device."""
        return self.get_build_number()


    def reboot(self, timeout=5):
        """Reboot the sonic device by submitting a post to the server."""

        # TODO(beeps): crbug.com/318306
        current_boot_id = self.get_boot_id()
        try:
            self.client.reboot()
        except sonic_client_utils.SonicProxyException as e:
            raise error.AutoservRebootError(
                    'Unable to reboot through the sonic proxy: %s' % e)

        self.wait_for_restart(timeout=timeout, old_boot_id=current_boot_id)


    def cleanup(self):
        """Cleanup state.

        If removing state information fails, do a hard reboot. This will hit
        our reboot method through the ssh host's cleanup.
        """
        try:
            self.run('rm -r /data/*')
            self.run('rm -f /cache/*')
        except (error.AutotestRunError, error.AutoservRunError) as e:
            logging.warning('Unable to remove /data and /cache %s', e)
            super(SonicHost, self).cleanup()


    def _remount_root(self, permissions):
        """Remount root partition.

        @param permissions: Permissions to use for the remount, eg: ro, rw.

        @raises error.AutoservRunError: If something goes wrong in executing
            the remount command.
        """
        self.run('mount -o %s,remount /' % permissions)


    def _setup_coredump_dirs(self):
        """Sets up the /data/coredump directory on the client.

        The device will write a memory dump to this directory on crash,
        if it exists. No crashdump will get written if it doesn't.
        """
        try:
            self.run('mkdir -p %s' % self.COREDUMP_DIR)
            self.run('chmod 4777 %s' % self.COREDUMP_DIR)
        except (error.AutotestRunError, error.AutoservRunError) as e:
            error.AutoservRunError('Unable to create coredump directories with '
                                   'the appropriate permissions: %s' % e)


    def _setup_for_recovery(self, update_url):
        """Sets up the /cache/recovery directory on the client.

        Copies over the OTA zipfile from the update_url to /cache, then
        sets up the recovery directory. Normal installs are achieved
        by rebooting into recovery mode.

        @param update_url: A url pointing to a staged ota zip file.

        @raises error.AutoservRunError: If something goes wrong while
            executing a command.
        """
        ssh_cmd = '%s %s' % (self.make_ssh_command(), self.hostname)
        site_utils.remote_wget(update_url, self.OTA_LOCATION, ssh_cmd)
        self.run('ls %s' % self.OTA_LOCATION)

        self.run('mkdir -p %s' % self.RECOVERY_DIR)

        # These 2 commands will always return a non-zero exit status
        # even if they complete successfully. This is a confirmed
        # non-issue, since the install will actually complete. If one
        # of the commands fails we can only detect it as a failure
        # to install the specified build.
        self.run('echo --update_package>%s' % self.COMMAND_FILE,
                 ignore_status=True)
        self.run('echo %s>>%s' % (self.OTA_LOCATION, self.COMMAND_FILE),
                 ignore_status=True)


    def machine_install(self, update_url):
        """Installs a build on the Sonic device.

        @returns A tuple of (string of the current build number,
                             {'job_repo_url': update_url}).
        """
        old_build_number = self.get_build_number()
        self._remount_root(permissions='rw')
        self._setup_coredump_dirs()
        self._setup_for_recovery(update_url)

        current_boot_id = self.get_boot_id()
        self.run_background('reboot recovery')
        self.wait_for_restart(timeout=self.REBOOT_TIME,
                              old_boot_id=current_boot_id)
        new_build_number = self.get_build_number()

        # TODO(beeps): crbug.com/318278
        if new_build_number ==  old_build_number:
            raise error.AutoservRunError('Build number did not change on: '
                                         '%s after update with %s' %
                                         (self.hostname, update_url()))

        return str(new_build_number), {constants.JOB_REPO_URL: update_url}
