# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Methods and classes to interact with a nebraska instance."""

import base64
import logging
import multiprocessing
import os
import shutil
import subprocess
import urllib.parse

from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import gob_util
from chromite.lib import osutils
from chromite.lib import path_util
from chromite.lib import remote_access
from chromite.lib import timeout_util


NEBRASKA_FILENAME = "nebraska.py"

# Error msg in loading shared libraries when running python command.
ERROR_MSG_IN_LOADING_LIB = "error while loading shared libraries"


class Error(Exception):
    """Base exception class of nebraska errors."""


class NebraskaStartupError(Error):
    """Thrown when the nebraska fails to start up."""


class NebraskaStopError(Error):
    """Thrown when the nebraska fails to stop."""


class RemoteNebraskaWrapper(multiprocessing.Process):
    """A wrapper for nebraska.py on a remote device.

    We assume there is no chroot on the device, thus we do not launch
    nebraska inside chroot.
    """

    NEBRASKA_TIMEOUT = 30
    KILL_TIMEOUT = 10

    # Keep in sync with nebraska.py if not passing these directly to nebraska.
    RUNTIME_ROOT = "/run/nebraska"
    PID_FILE_PATH = os.path.join(RUNTIME_ROOT, "pid")
    PORT_FILE_PATH = os.path.join(RUNTIME_ROOT, "port")
    LOG_FILE_PATH = "/tmp/nebraska.log"

    NEBRASKA_PATH = os.path.join("/usr/local/bin", NEBRASKA_FILENAME)

    def __init__(
        self,
        remote_device,
        nebraska_bin=None,
        update_payloads_address=None,
        update_metadata_dir=None,
        install_payloads_address=None,
        install_metadata_dir=None,
        ignore_appid=False,
    ) -> None:
        """Initializes the nebraska wrapper.

        Args:
            remote_device: A remote_access.RemoteDevice object.
            nebraska_bin: The path to the nebraska binary.
            update_payloads_address: The root address where the payloads will be
                served.  it can either be a local address (file://) or a remote
                address (http://)
            update_metadata_dir: A directory where json files for payloads
                required for update are located.
            install_payloads_address: Same as update_payloads_address for
                install operations.
            install_metadata_dir: Similar to update_metadata_dir but for install
                payloads.
            ignore_appid: True to tell Nebraska to ignore the update request's
                App ID. This allows mismatching the source and target version
                boards. One specific use case is updating between <board> and
                <board>-kernelnext images.
        """
        super().__init__()

        self._device = remote_device
        self._hostname = remote_device.hostname

        self._update_payloads_address = update_payloads_address
        self._update_metadata_dir = update_metadata_dir
        self._install_payloads_address = install_payloads_address
        self._install_metadata_dir = install_metadata_dir
        self._ignore_appid = ignore_appid

        self._nebraska_bin = nebraska_bin or self.NEBRASKA_PATH

        self._port_file = self.PORT_FILE_PATH
        self._pid_file = self.PID_FILE_PATH
        self._log_file = self.LOG_FILE_PATH

        self._port = None
        self._pid = None

    def _RemoteCommand(self, *args, **kwargs):
        """Runs a remote shell command.

        Args:
            *args: See remote_access.RemoteDevice documentation.
            **kwargs: See remote_access.RemoteDevice documentation.
        """
        kwargs.setdefault("debug_level", logging.DEBUG)
        return self._device.run(*args, **kwargs)

    def _PortFileExists(self):
        """Checks whether the port file exists in the remove device or not."""
        result = self._RemoteCommand(
            ["test", "-f", self._port_file], check=False
        )
        return result.returncode == 0

    def _ReadPortNumber(self) -> None:
        """Reads the port number from the port file on the remote device."""
        if not self.is_alive():
            raise NebraskaStartupError(
                "Nebraska is not alive, so no port file yet!"
            )

        try:
            timeout_util.WaitForReturnTrue(
                self._PortFileExists, period=5, timeout=self.NEBRASKA_TIMEOUT
            )
        except timeout_util.TimeoutError:
            self.terminate()
            raise NebraskaStartupError(
                "Timeout (%s) waiting for remote nebraska"
                " port_file" % self.NEBRASKA_TIMEOUT
            )

        self._port = int(
            self._RemoteCommand(
                ["cat", self._port_file], capture_output=True
            ).stdout.strip()
        )

    def IsReady(self):
        """Returns True if nebraska is ready to accept requests."""
        if not self.is_alive():
            raise NebraskaStartupError("Nebraska is not alive, so not ready!")

        url = "http://%s:%d/%s" % (
            remote_access.LOCALHOST_IP,
            self._port,
            "health_check",
        )
        # Running curl through SSH because the port on the device is not
        # accessible by default.
        result = self._RemoteCommand(
            ["curl", url, "-o", "/dev/null"], check=False
        )
        return result.returncode == 0

    def _WaitUntilStarted(self) -> None:
        """Wait until the nebraska has started."""
        if not self._port:
            self._ReadPortNumber()

        try:
            timeout_util.WaitForReturnTrue(
                self.IsReady, timeout=self.NEBRASKA_TIMEOUT, period=5
            )
        except timeout_util.TimeoutError:
            raise NebraskaStartupError("Nebraska did not start.")

        self._pid = int(
            self._RemoteCommand(
                ["cat", self._pid_file], capture_output=True
            ).stdout.strip()
        )
        logging.info("Started nebraska with pid %s", self._pid)

    def run(self) -> None:
        """Launches a nebraska process on the device.

        Starts a background nebraska and waits for it to finish.
        """
        logging.info("Starting nebraska on %s", self._hostname)

        if not self._update_metadata_dir:
            raise NebraskaStartupError(
                "Update metadata directory location is not passed."
            )

        cmd = [
            self._nebraska_bin,
            "--update-metadata",
            self._update_metadata_dir,
        ]

        if self._update_payloads_address:
            cmd += ["--update-payloads-address", self._update_payloads_address]
        if self._install_metadata_dir:
            cmd += ["--install-metadata", self._install_metadata_dir]
        if self._install_payloads_address:
            cmd += [
                "--install-payloads-address",
                self._install_payloads_address,
            ]
        if self._ignore_appid:
            cmd += ["--ignore-appid"]

        try:
            self._RemoteCommand(cmd, stdout=True, stderr=subprocess.STDOUT)
        except cros_build_lib.RunCommandError as err:
            msg = "Remote nebraska failed (to start): %s" % str(err)
            logging.error(msg)
            raise NebraskaStartupError(msg)

    def Start(self) -> None:
        """Starts the nebraska process remotely on the remote device."""
        if self.is_alive():
            logging.warning("Nebraska is already running, not running again.")
            return

        self.start()
        self._WaitUntilStarted()

    def Stop(self) -> None:
        """Stops the nebraska instance if its running.

        Kills the nebraska instance with SIGTERM (and SIGKILL if SIGTERM fails).
        """
        logging.debug("Stopping nebraska instance with pid %s", self._pid)
        if self.is_alive():
            self._RemoteCommand(["kill", str(self._pid)], check=False)
        else:
            logging.debug("Nebraska is not running, stopping nothing!")
            return

        self.join(self.KILL_TIMEOUT)
        if self.is_alive():
            logging.warning("Nebraska is unstoppable. Killing with SIGKILL.")
            try:
                self._RemoteCommand(["kill", "-9", str(self._pid)])
            except cros_build_lib.RunCommandError as e:
                raise NebraskaStopError("Unable to stop Nebraska: %s" % e)

    def GetURL(
        self,
        ip=remote_access.LOCALHOST_IP,
        critical_update=False,
        no_update=False,
    ):
        """Returns the URL which the devserver is running on.

        Args:
            ip: The ip of running nebraska if different from localhost.
            critical_update: Whether nebraska has to instruct the update_engine
                that the update is a critical one or not.
            no_update: Whether nebraska has to give a noupdate response even if
                it detected an update.

        Returns:
            An HTTP URL that can be passed to the update_engine_client in
                --omaha_url flag.
        """
        query_dict = {}
        if critical_update:
            query_dict["critical_update"] = True
        if no_update:
            query_dict["no_update"] = True
        query_string = urllib.parse.urlencode(query_dict)

        return "http://%s:%d/update/%s" % (
            ip,
            self._port,
            (("?%s" % query_string) if query_string else ""),
        )

    def PrintLog(self):
        """Print Nebraska log to stdout."""
        if (
            self._RemoteCommand(
                ["test", "-f", self._log_file], check=False
            ).returncode
            != 0
        ):
            logging.error(
                "Nebraska log file %s does not exist on the device.",
                self._log_file,
            )
            return

        result = self._RemoteCommand(
            ["cat", self._log_file], capture_output=True
        )
        output = "--- Start output from %s ---\n" % self._log_file
        output += result.stdout
        output += "--- End output from %s ---" % self._log_file
        return output

    def CollectLogs(self, target_log) -> None:
        """Copies the nebraska logs from the device.

        Args:
            target_log: The file to copy the log to from the device.
        """
        try:
            self._device.CopyFromDevice(self._log_file, target_log)
        except (
            remote_access.RemoteAccessException,
            cros_build_lib.RunCommandError,
        ) as err:
            logging.error(
                "Failed to copy nebraska logs from device, ignoring: %s",
                str(err),
            )

    def CheckNebraskaCanRun(self) -> None:
        """Checks to see if we can start nebraska.

        If the stateful partition is corrupted, Python or other packages needed
        for rootfs update may be missing on |device|.

        This will also use `ldconfig` to update library paths on the target
        device if it looks like that's causing problems, which is necessary
        for base images.

        Raise NebraskaStartupError if nebraska cannot start.
        """

        # Try to capture the output from the command, so we can dump it in the
        # case of errors. Note that this will not work if we were requested to
        # redirect logs to a |log_file|.
        cmd_kwargs = {"stdout": True, "stderr": subprocess.STDOUT}
        cmd = ["python", self._nebraska_bin, "--help"]
        logging.info("Checking if we can run nebraska on the device...")
        try:
            self._RemoteCommand(cmd, **cmd_kwargs)
        except cros_build_lib.RunCommandError as e:
            logging.warning("Cannot start nebraska.")
            logging.warning(e.stderr)
            if ERROR_MSG_IN_LOADING_LIB in str(e):
                logging.info("Attempting to correct device library paths...")
                try:
                    self._RemoteCommand(["ldconfig"], **cmd_kwargs)
                    self._RemoteCommand(cmd, **cmd_kwargs)
                    logging.info("Library path correction successful.")
                    return
                except cros_build_lib.RunCommandError as e2:
                    logging.warning("Library path correction failed:")
                    logging.warning(e2.stderr)
                    raise NebraskaStartupError(e.stderr)

            raise NebraskaStartupError(str(e))

    @staticmethod
    def GetNebraskaSrcFile(source_dir):
        """Returns path to nebraska source file.

        nebraska is copied to source_dir, either from a local file or by
        downloading from googlesource.com.
        """
        assert os.path.isdir(source_dir), (
            "%s must be a valid directory." % source_dir
        )

        nebraska_path = os.path.join(source_dir, NEBRASKA_FILENAME)
        checkout = path_util.DetermineCheckout()
        if checkout.type == path_util.CheckoutType.REPO:
            # ChromeOS checkout. Copy existing file to destination.
            local_src = os.path.join(
                constants.SOURCE_ROOT,
                "src",
                "platform",
                "dev",
                "nebraska",
                NEBRASKA_FILENAME,
            )
            assert os.path.isfile(local_src), "%s doesn't exist" % local_src
            shutil.copy2(local_src, source_dir)
        else:
            # Download from googlesource.
            nebraska_url_path = "%s/+/%s/%s?format=text" % (
                "chromiumos/platform/dev-util",
                "HEAD",
                "nebraska/nebraska.py",
            )
            contents_b64 = gob_util.FetchUrl(
                constants.EXTERNAL_GOB_HOST, nebraska_url_path
            )
            osutils.WriteFile(
                nebraska_path, base64.b64decode(contents_b64).decode("utf-8")
            )

        return nebraska_path
