# Copyright 2017 The Chromium 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.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.site_utils.lxc import Container
from autotest_lib.site_utils.lxc import constants
from autotest_lib.site_utils.lxc import lxc
from autotest_lib.site_utils.lxc import utils as lxc_utils


class Zygote(Container):
    """A Container that implements post-bringup configuration.
    """

    def __init__(self, container_path, name, attribute_values, src=None,
                 snapshot=False, host_path=None):
        """Initialize an object of LXC container with given attribute values.

        @param container_path: Directory that stores the container.
        @param name: Name of the container.
        @param attribute_values: A dictionary of attribute values for the
                                 container.
        @param src: An optional source container.  If provided, the source
                    continer is cloned, and the new container will point to the
                    clone.
        @param snapshot: Whether or not to create a snapshot clone.  By default,
                         this is false.  If a snapshot is requested and creating
                         a snapshot clone fails, a full clone will be attempted.
        @param host_path: If set to None (the default), a host path will be
                          generated based on constants.DEFAULT_SHARED_HOST_PATH.
                          Otherwise, this can be used to override the host path
                          of the new container, for testing purposes.
        """
        # Check if this is a pre-existing LXC container.  Do this before calling
        # the super ctor, because that triggers container creation.
        exists = lxc.get_container_info(container_path, name=name)

        super(Zygote, self).__init__(container_path, name, attribute_values,
                                     src, snapshot)

        logging.debug(
                'Creating Zygote (lxcpath:%s name:%s)', container_path, name)

        # host_path is a directory within a shared bind-mount, which enables
        # bind-mounts from the host system to be shared with the LXC container.
        if host_path is not None:
            # Allow the host_path to be injected, for testing.
            self.host_path = host_path
        else:
            if exists:
                # Pre-existing Zygotes must have a host path.
                self.host_path = self._find_existing_host_dir()
                if self.host_path is None:
                    raise error.ContainerError(
                            'Container %s has no host path.' %
                            os.path.join(container_path, name))
            else:
                # New Zygotes use a predefined template to generate a host path.
                self.host_path = os.path.join(
                        os.path.realpath(constants.DEFAULT_SHARED_HOST_PATH),
                        self.name)

        # host_path_ro is a directory for holding intermediate mount points,
        # which are necessary when creating read-only bind mounts.  See the
        # mount_dir method for more details.
        #
        # Generate a host_path_ro based on host_path.
        ro_dir, ro_name = os.path.split(self.host_path.rstrip(os.path.sep))
        self.host_path_ro = os.path.join(ro_dir, '%s.ro' % ro_name)

        # Remember mounts so they can be cleaned up in destroy.
        self.mounts = []

        if exists:
            self._find_existing_bind_mounts()
        else:
            # Creating a new Zygote - initialize the host dirs.  Don't use sudo,
            # so that the resulting directories can be accessed by autoserv (for
            # SSP installation, etc).
            if not lxc_utils.path_exists(self.host_path):
                os.makedirs(self.host_path)
            if not lxc_utils.path_exists(self.host_path_ro):
                os.makedirs(self.host_path_ro)

            # Create the mount point within the container's rootfs.
            # Changes within container's rootfs require sudo.
            utils.run('sudo mkdir %s' %
                      os.path.join(self.rootfs,
                                   constants.CONTAINER_HOST_DIR.lstrip(
                                           os.path.sep)))
            self.mount_dir(self.host_path, constants.CONTAINER_HOST_DIR)


    def destroy(self, force=True):
        """Destroy the Zygote.

        This destroys the underlying container (see Container.destroy) and also
        cleans up any host mounts associated with it.

        @param force: Force container destruction even if it's running.  See
                      Container.destroy.
        """
        logging.debug('Destroying Zygote %s', self.name)
        super(Zygote, self).destroy(force)
        self._cleanup_host_mount()


    def install_ssp(self, ssp_url):
        """Downloads and installs the given server package.

        @param ssp_url: The URL of the ssp to download and install.
        """
        # The host dir is mounted directly on /usr/local/autotest within the
        # container.  The SSP structure assumes it gets untarred into the
        # /usr/local directory of the container's rootfs.  In order to unpack
        # with the correct directory structure, create a tmpdir, mount the
        # container's host dir as ./autotest, and unpack the SSP.
        if not self.is_running():
            super(Zygote, self).install_ssp(ssp_url)
            return

        usr_local_path = os.path.join(self.host_path, 'usr', 'local')
        os.makedirs(usr_local_path)

        with lxc_utils.TempDir(dir=usr_local_path) as tmpdir:
            download_tmp = os.path.join(tmpdir,
                                        'autotest_server_package.tar.bz2')
            lxc.download_extract(ssp_url, download_tmp, usr_local_path)

        container_ssp_path = os.path.join(
                constants.CONTAINER_HOST_DIR,
                constants.CONTAINER_AUTOTEST_DIR.lstrip(os.path.sep))
        self.attach_run('mkdir -p %s && mount --bind %s %s' %
                        (constants.CONTAINER_AUTOTEST_DIR,
                         container_ssp_path,
                         constants.CONTAINER_AUTOTEST_DIR))


    def copy(self, host_path, container_path):
        """Copies files into the Zygote.

        @param host_path: Path to the source file/dir to be copied.
        @param container_path: Path to the destination dir (in the container).
        """
        if not self.is_running():
            return super(Zygote, self).copy(host_path, container_path)

        logging.debug('copy %s to %s', host_path, container_path)

        # First copy the files into the host mount, then move them from within
        # the container.
        self._do_copy(src=host_path,
                      dst=os.path.join(self.host_path,
                                       container_path.lstrip(os.path.sep)))

        src = os.path.join(constants.CONTAINER_HOST_DIR,
                           container_path.lstrip(os.path.sep))
        dst = container_path

        # In the container, bind-mount from host path to destination.
        # The mount destination must have the correct type (file vs dir).
        if os.path.isdir(host_path):
            self.attach_run('mkdir -p %s' % dst)
        else:
            self.attach_run(
                'mkdir -p %s && touch %s' % (os.path.dirname(dst), dst))
        self.attach_run('mount --bind %s %s' % (src, dst))


    def mount_dir(self, source, destination, readonly=False):
        """Mount a directory in host to a directory in the container.

        @param source: Directory in host to be mounted.
        @param destination: Directory in container to mount the source directory
        @param readonly: Set to True to make a readonly mount, default is False.
        """
        if not self.is_running():
            return super(Zygote, self).mount_dir(source, destination, readonly)

        # Destination path in container must be absolute.
        if not os.path.isabs(destination):
            destination = os.path.join('/', destination)

        # Create directory in container for mount.
        self.attach_run('mkdir -p %s' % destination)

        # Creating read-only shared bind mounts is a two-stage process.  First,
        # the original file/directory is bind-mounted (with the ro option) to an
        # intermediate location in self.host_path_ro.  Then, the intermediate
        # location is bind-mounted into the shared host dir.
        # Replace the original source with this intermediate read-only mount,
        # then continue.
        if readonly:
            source_ro = os.path.join(self.host_path_ro,
                                     source.lstrip(os.path.sep))
            self.mounts.append(lxc_utils.BindMount.create(
                    source, self.host_path_ro, readonly=True))
            source = source_ro

        # Mount the directory into the host dir, then from the host dir into the
        # destination.
        self.mounts.append(
                lxc_utils.BindMount.create(source, self.host_path, destination))

        container_host_path = os.path.join(constants.CONTAINER_HOST_DIR,
                                           destination.lstrip(os.path.sep))
        self.attach_run('mount --bind %s %s' %
                        (container_host_path, destination))


    def _cleanup_host_mount(self):
        """Unmounts and removes the host dirs for this container."""
        # Clean up all intermediate bind mounts into host_path and host_path_ro.
        for mount in self.mounts:
            mount.cleanup()
        # The SSP and other "real" content gets copied into the host dir.  Use
        # rm -r to clear it out.
        if lxc_utils.path_exists(self.host_path):
            utils.run('sudo rm -r "%s"' % self.host_path)
        # The host_path_ro directory only contains intermediate bind points,
        # which should all have been cleared out.  Use rmdir.
        if lxc_utils.path_exists(self.host_path_ro):
            utils.run('sudo rmdir "%s"' % self.host_path_ro)


    def _find_existing_host_dir(self):
        """Finds the host mounts for a pre-existing Zygote.

        The host directory is passed into the Zygote constructor when creating a
        new Zygote.  However, when a Zygote is instantiated on top of an already
        existing LXC container, it has to reconnect to the existing host
        directory.

        @return: The host-side path to the host dir.
        """
        # Look for the mount that targets the "/host" dir within the container.
        for mount in self._get_lxc_config('lxc.mount.entry'):
            mount_cfg = mount.split(' ')
            if mount_cfg[1] == 'host':
                return mount_cfg[0]
        return None


    def _find_existing_bind_mounts(self):
        """Locates bind mounts associated with an existing container.

        When a Zygote object is instantiated on top of an existing LXC
        container, this method needs to be called so that all the bind-mounts
        associated with the container can be reconstructed.  This enables proper
        cleanup later.
        """
        for info in utils.get_mount_info():
            # Check for bind mounts in the host and host_ro directories, and
            # re-add them to self.mounts.
            if lxc_utils.is_subdir(self.host_path, info.mount_point):
                logging.debug('mount: %s', info.mount_point)
                self.mounts.append(lxc_utils.BindMount.from_existing(
                        self.host_path, info.mount_point))
            elif lxc_utils.is_subdir(self.host_path_ro, info.mount_point):
                logging.debug('mount_ro: %s', info.mount_point)
                self.mounts.append(lxc_utils.BindMount.from_existing(
                        self.host_path_ro, info.mount_point))
