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


# Cleaning up the bind mount can sometimes be blocked if a process is active in
# the directory.  Give cleanup operations about 10 seconds to complete.  This is
# only an approximate measure.
_RETRY_MAX_SECONDS = 10


class SharedHostDir(object):
    """A class that manages the shared host directory.

    Instantiating this class sets up a shared host directory at the specified
    path.  The directory is cleaned up and unmounted when cleanup is called.
    """

    def __init__(self,
                 path = constants.DEFAULT_SHARED_HOST_PATH,
                 force_delete = False):
        """Sets up the shared host directory.

        @param shared_host_path: The location of the shared host path.
        @param force_delete: If True, the host dir will be cleared and
                             reinitialized if it already exists.
        """
        self.path = os.path.realpath(path)

        # If the host dir exists and is valid and force_delete is not set, there
        # is nothing to do.  Otherwise, clear the host dir if it exists, then
        # recreate it.  Do not use lxc_utils.path_exists as that forces a sudo
        # call - the SharedHostDir is used all over the place, and
        # instantiatinng one should not cause the user to have to enter their
        # password if the host dir already exists.  The host dir is created with
        # open permissions so it should be accessible without sudo.
        if os.path.isdir(self.path):
            if not force_delete and self._host_dir_is_valid():
                return
            else:
                self.cleanup()

        utils.run('sudo mkdir "%(path)s" && '
                  'sudo chmod 777 "%(path)s" && '
                  'sudo mount --bind "%(path)s" "%(path)s" && '
                  'sudo mount --make-shared "%(path)s"' %
                  {'path': self.path})


    def cleanup(self, timeout=_RETRY_MAX_SECONDS):
        """Removes the shared host directory.

        This should only be called after all containers have been destroyed
        (i.e. all host mounts have been disconnected and removed, so the shared
        host directory should be empty).

        @param timeout: Unmounting and deleting the mount point can run into
                        race conditions vs the kernel sometimes.  This parameter
                        specifies the number of seconds for which to keep
                        waiting and retrying the umount/rm commands before
                        raising a CmdError.  The default of _RETRY_MAX_SECONDS
                        should work; this parameter is for tests to substitute a
                        different time out.

        @raises CmdError: If any of the commands involved in unmounting or
                          deleting the mount point fail even after retries.
        """
        if not os.path.exists(self.path):
            return

        # Unmount and delete everything in the host path.
        for info in utils.get_mount_info():
            if lxc_utils.is_subdir(self.path, info.mount_point):
                utils.run('sudo umount "%s"' % info.mount_point)

        # It's possible that the directory is no longer mounted (e.g. if the
        # system was rebooted), so check before unmounting.
        if utils.run('findmnt %s > /dev/null' % self.path,
                     ignore_status=True).exit_status == 0:
            self._try_umount(timeout)
        self._try_rm(timeout)


    def _try_umount(self, timeout):
        """Tries to unmount the shared host dir.

        If the unmount fails, it is retried approximately once a second, for
        <timeout> seconds.  If the command still fails, a CmdError is raised.

        @param timeout: A timeout in seconds for which to retry the command.

        @raises CmdError: If the command has not succeeded after
                          _RETRY_MAX_SECONDS.
        """
        @retry.retry(error.CmdError, timeout_min=timeout/60.0,
                     delay_sec=1)
        def run_with_retry():
            """Actually unmounts the shared host dir.  Internal function."""
            utils.run('sudo umount %s' % self.path)
        run_with_retry()


    def _try_rm(self, timeout):
        """Tries to remove the shared host dir.

        If the rm command fails, it is retried approximately once a second, for
        <timeout> seconds.  If the command still fails, a CmdError is raised.

        @param timeout: A timeout in seconds for which to retry the command.

        @raises CmdError: If the command has not succeeded after
                          _RETRY_MAX_SECONDS.
        """
        @retry.retry(error.CmdError, timeout_min=timeout/60.0,
                     delay_sec=1)
        def run_with_retry():
            """Actually removes the shared host dir.  Internal function."""
            utils.run('sudo rm -r "%s"' % self.path)
        run_with_retry()


    def _host_dir_is_valid(self):
        """Verifies that the shared host directory is set up correctly."""
        logging.debug('Verifying existing host path: %s', self.path)
        host_mount = list(utils.get_mount_info(mount_point=self.path))

        # Check that the host mount exists and is shared
        if host_mount:
            if 'shared' in host_mount[0].tags:
                return True
            else:
                logging.debug('Host mount not shared (%r).', host_mount)
        else:
            logging.debug('Host mount not found.')

        return False
