import os, sys, subprocess, logging

from autotest_lib.client.common_lib import global_config, utils, error
from autotest_lib.server import utils as server_utils
from autotest_lib.server.hosts import remote


RPM_FRONTEND_URI = global_config.global_config.get_config_value('CROS',
        'rpm_frontend_uri', type=str, default='')


SiteHost = utils.import_site_class(
    __file__, "autotest_lib.server.hosts.site_host", "SiteHost",
    remote.RemoteHost)


class SerialHost(SiteHost):
    DEFAULT_REBOOT_TIMEOUT = SiteHost.DEFAULT_REBOOT_TIMEOUT
    HARD_RESET_CMD = 'hardreset'


    def _initialize(self, conmux_server=None, conmux_attach=None,
                    console_log="console.log", *args, **dargs):
        super(SerialHost, self)._initialize(*args, **dargs)

        self.__logger = None
        self.__console_log = console_log

        self.conmux_server = conmux_server
        self.conmux_attach = self._get_conmux_attach(conmux_attach)


    @classmethod
    def _get_conmux_attach(cls, conmux_attach=None):
        if conmux_attach:
            return conmux_attach

        # assume we're using the conmux-attach provided with autotest
        server_dir = server_utils.get_server_dir()
        path = os.path.join(server_dir, "..", "conmux", "conmux-attach")
        path = os.path.abspath(path)
        return path


    @staticmethod
    def _get_conmux_hostname(hostname, conmux_server):
        if conmux_server:
            return "%s/%s" % (conmux_server, hostname)
        else:
            return hostname


    def get_conmux_hostname(self):
        return self._get_conmux_hostname(self.hostname, self.conmux_server)


    @classmethod
    def host_is_supported(cls, hostname, conmux_server=None,
                          conmux_attach=None):
        """ Returns a boolean indicating if the remote host with "hostname"
        supports use as a SerialHost """
        return_value = False
        conmux_attach = cls._get_conmux_attach(conmux_attach)
        conmux_hostname = cls._get_conmux_hostname(hostname, conmux_server)
        cmd = "%s %s echo 2> /dev/null" % (conmux_attach, conmux_hostname)
        try:
            result = utils.run(cmd, ignore_status=True, timeout=10)
            return_value = result.exit_status == 0
        except error.CmdError:
            logging.warning("Timed out while trying to attach to conmux")
            return_value = False

        return return_value or SiteHost.check_for_rpm_support(hostname)


    def start_loggers(self):
        super(SerialHost, self).start_loggers()

        if self.__console_log is None:
            return

        if not self.conmux_attach or not os.path.exists(self.conmux_attach):
            return

        r, w = os.pipe()
        script_path = os.path.join(self.monitordir, 'console.py')
        cmd = [self.conmux_attach, self.get_conmux_hostname(),
               '%s %s %s %d' % (sys.executable, script_path,
                                self.__console_log, w)]

        self.__warning_stream = os.fdopen(r, 'r', 0)
        if self.job:
            self.job.warning_loggers.add(self.__warning_stream)

        stdout = stderr = open(os.devnull, 'w')
        self.__logger = subprocess.Popen(cmd, stdout=stdout, stderr=stderr)
        os.close(w)


    def stop_loggers(self):
        super(SerialHost, self).stop_loggers()

        if self.__logger:
            utils.nuke_subprocess(self.__logger)
            self.__logger = None
            if self.job:
                self.job.warning_loggers.discard(self.__warning_stream)
            self.__warning_stream.close()


    def run_conmux(self, cmd):
        """
        Send a command to the conmux session
        """
        if not self.conmux_attach or not os.path.exists(self.conmux_attach):
            return False
        cmd = '%s %s echo %s 2> /dev/null' % (self.conmux_attach,
                                              self.get_conmux_hostname(),
                                              cmd)
        result = utils.system(cmd, ignore_status=True)
        return result == 0


    def hardreset(self, timeout=DEFAULT_REBOOT_TIMEOUT, wait=True,
                  conmux_command=HARD_RESET_CMD, num_attempts=1, halt=False,
                  **wait_for_restart_kwargs):
        """
        Reach out and slap the box in the power switch.
        @params conmux_command: The command to run via the conmux interface
        @params timeout: timelimit in seconds before the machine is
                         considered unreachable
        @params wait: Whether or not to wait for the machine to reboot
        @params num_attempts: Number of times to attempt hard reset erroring
                              on the last attempt.
        @params halt: Halts the machine before hardresetting.
        @params **wait_for_restart_kwargs: keyword arguments passed to
                wait_for_restart()
        """
        conmux_command = "'~$%s'" % conmux_command

        # if the machine is up, grab the old boot id, otherwise use a dummy
        # string and NOT None to ensure that wait_down always returns True,
        # even if the machine comes back up before it's called
        try:
            old_boot_id = self.get_boot_id()
        except error.AutoservSSHTimeout:
            old_boot_id = 'unknown boot_id prior to SerialHost.hardreset'

        def reboot():
            if halt:
                self.halt()
            if self.HARD_RESET_CMD in conmux_command and RPM_FRONTEND_URI:
                self.power_cycle()
            elif not self.run_conmux(conmux_command):
                self.record("ABORT", None, "reboot.start",
                            "hard reset unavailable")
                raise error.AutoservUnsupportedError(
                    'Hard reset unavailable')
            self.record("GOOD", None, "reboot.start", "hard reset")
            if wait:
                warning_msg = ('Serial console failed to respond to hard reset '
                               'attempt (%s/%s)')
                for attempt in xrange(num_attempts-1):
                    try:
                        self.wait_for_restart(timeout, log_failure=False,
                                              old_boot_id=old_boot_id,
                                              **wait_for_restart_kwargs)
                    except error.AutoservShutdownError:
                        logging.warning(warning_msg, attempt+1, num_attempts)
                        # re-send the hard reset command
                        if (self.HARD_RESET_CMD in conmux_command and
                                RPM_FRONTEND_URI):
                            self.power_cycle()
                        else:
                            self.run_conmux(conmux_command)
                    else:
                        break
                else:
                    # Run on num_attempts=1 or last retry
                    try:
                        self.wait_for_restart(timeout,
                                              old_boot_id=old_boot_id,
                                              **wait_for_restart_kwargs)
                    except error.AutoservShutdownError:
                        logging.warning(warning_msg, num_attempts, num_attempts)
                        msg = "Host did not shutdown"
                        raise error.AutoservShutdownError(msg)

        if self.job:
            self.job.disable_warnings("POWER_FAILURE")
        try:
            if wait:
                self.log_reboot(reboot)
            else:
                reboot()
        finally:
            if self.job:
                self.job.enable_warnings("POWER_FAILURE")
