blob: 21b5f2b8dc60b61d54e2a5590c38e911b195fd50 [file] [log] [blame]
# 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);