# 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 common
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.site_utils.lxc import constants
from autotest_lib.site_utils.lxc import container

try:
    from chromite.lib import metrics
except ImportError:
    metrics = utils.metrics_mock


class ContainerFactory(object):
    """A factory class for creating LXC container objects."""

    def __init__(self, base_container, container_class=container.Container,
                 snapshot=True, force_cleanup=False,
                 lxc_path=constants.DEFAULT_CONTAINER_PATH):
        """Initializes a ContainerFactory.

        @param base_container: The base container from which other containers
                               are cloned.
        @param container_class: (optional) The Container class to instantiate.
                                By default, lxc.Container is instantiated.
        @param snapshot: (optional) If True, creates LXC snapshot clones instead
                         of full clones.  By default, snapshot clones are used.
        @param force_cleanup: (optional) If True, if a container is created with
                              a name and LXC directory matching an existing
                              container, the existing container is destroyed,
                              and the new container created in its place. By
                              default, existing containers are not destroyed and
                              a ContainerError is raised.
        @param lxc_path: (optional) The default LXC path that will be used for
                         new containers.  If one is not provided, the
                         DEFAULT_CONTAINER_PATH from lxc.constants will be used.
                         Note that even if a path is provided here, it can still
                         be overridden when create_container is called.
        """
        self._container_class = container_class
        self._base_container = base_container
        self._snapshot = snapshot
        self._force_cleanup = force_cleanup
        self._lxc_path = lxc_path


    def create_container(self, cid=None, lxc_path=None):
        """Creates a new container.

        @param cid: (optional) A ContainerId for the new container.  If an ID is
                    provided, it determines both the name and the ID of the
                    container.  If no ID is provided, a random name is generated
                    for the container, and it is not assigned an ID.
        @param lxc_path: (optional) The LXC path for the new container.  If one
                         is not provided, the factory's default lxc_path
                         (specified when the factory was constructed) is used.
        """
        name = str(cid) if cid else None
        if lxc_path is None:
            lxc_path = self._lxc_path

        logging.debug('Creating new container (name: %s, lxc_path: %s)',
                      name, lxc_path)

        # If an ID is provided, use it as the container name.
        new_container = self._create_from_base(name, lxc_path)
        # If an ID is provided, assign it to the container.  When the container
        # is created just-in-time by the container bucket, this ensures that the
        # resulting container is correctly registered with the autoserv system.
        # If the container is being created by a container pool, the ID will be
        # assigned later, when the continer is bound to an actual test process.
        if cid:
            new_container.id = cid
        return new_container


    # create_from_base_duration is the original name of the metric.  Keep this
    # so we have history.
    @metrics.SecondsTimerDecorator(
            '%s/create_from_base_duration' % constants.STATS_KEY)
    def _create_from_base(self, name, lxc_path):
        """Creates a container from the base container.

        @param name: Name of the container.
        @param lxc_path: The LXC path of the new container.

        @return: A Container object for the created container.

        @raise ContainerError: If the container already exist.
        @raise error.CmdError: If lxc-clone call failed for any reason.
        """
        use_snapshot = constants.SUPPORT_SNAPSHOT_CLONE and self._snapshot

        try:
            return self._container_class.clone(src=self._base_container,
                                               new_name=name,
                                               new_path=lxc_path,
                                               snapshot=use_snapshot,
                                               cleanup=self._force_cleanup)
        except error.CmdError:
            if not use_snapshot:
                raise
            else:
                logging.debug(
                        'Creating snapshot clone failed.'
                        ' Attempting without snapshot...'
                        ' This forces cleanup of old cloned container.'
                )
                return self._container_class.clone(src=self._base_container,
                                                   new_name=name,
                                                   new_path=lxc_path,
                                                   snapshot=False,
                                                   cleanup=True)
