# 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 tempfile 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. """ super(Zygote, self).__init__(container_path, name, attribute_values, src, snapshot) # Initialize host dir and mount if host_path is None: self.host_path = os.path.join( os.path.realpath(constants.DEFAULT_SHARED_HOST_PATH), self.name) else: self.host_path = host_path if src is not None: # If creating a new zygote, initialize the host dir. if not lxc_utils.path_exists(self.host_path): utils.run('sudo mkdir %s' % self.host_path) self.mount_dir(self.host_path, constants.CONTAINER_AUTOTEST_DIR) def destroy(self, force=True): super(Zygote, self).destroy(force) if lxc_utils.path_exists(self.host_path): self._cleanup_host_mount() def set_hostname(self, hostname): """Sets the hostname within the container. @param hostname The new container hostname. """ if self.is_running(): self.attach_run('hostname %s' % (hostname)) self.attach_run(constants.APPEND_CMD_FMT % { 'content': '127.0.0.1 %s' % (hostname), 'file': '/etc/hosts'}) else: super(Zygote, self).set_hostname(hostname) 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. tmpdir = None autotest_tmp = None try: tmpdir = tempfile.mkdtemp(dir=self.container_path, prefix='%s.' % self.name, suffix='.tmp') autotest_tmp = os.path.join(tmpdir, 'autotest') os.mkdir(autotest_tmp) utils.run( 'sudo mount --bind %s %s' % (self.host_path, autotest_tmp)) download_tmp = os.path.join(tmpdir, 'autotest_server_package.tar.bz2') lxc.download_extract(ssp_url, download_tmp, tmpdir) finally: if autotest_tmp is not None: try: utils.run('sudo umount %s' % autotest_tmp) except error.CmdError: logging.exception('Failure while cleaning up SSP tmpdir.') if tmpdir is not None: utils.run('sudo rm -rf %s' % tmpdir) def install_control_file(self, control_file): """Installs the given control file. The given file will be moved into the container. @param control_file: Path to the control file to install. """ # Compute the control temp path relative to the host mount. dst_path = os.path.join( self.host_path, os.path.relpath(constants.CONTROL_TEMP_PATH, constants.CONTAINER_AUTOTEST_DIR)) utils.run('sudo mkdir -p %s' % dst_path) utils.run('sudo mv %s %s' % (control_file, dst_path)) def _cleanup_host_mount(self): """Unmount and remove the host dir for this container.""" lxc_utils.cleanup_host_mount(self.host_path);