130 lines
5.3 KiB
Python
130 lines
5.3 KiB
Python
# 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);
|