[autotest] Implement zygote configuration.
Override the install_ssp and install_control_file implementations for
the Zygote class, to enable configuration of zygotes.
Add tests.
BUG=chromium:720219
TEST=sudo python container_unittest.py
TEST=sudo python container_bucket_unittest.py
TEST=sudo python zygote_unittest.py
TEST=sudo python lxc_functional_test.py
Change-Id: I2a2b8cc42a5d46b983d3149c57c686ab8aec4a89
Reviewed-on: https://chromium-review.googlesource.com/572509
Commit-Ready: Ben Kwa <kenobi@chromium.org>
Tested-by: Ben Kwa <kenobi@chromium.org>
Reviewed-by: Ben Kwa <kenobi@chromium.org>
diff --git a/site_utils/lxc/container_unittest.py b/site_utils/lxc/container_unittest.py
index c18696b..bea733b 100644
--- a/site_utils/lxc/container_unittest.py
+++ b/site_utils/lxc/container_unittest.py
@@ -147,7 +147,7 @@
def testInstallSsp(self):
"""Verifies that installing the ssp in the container works."""
- # Hard-codedpath to some golden data for this test.
+ # Hard-coded path to some golden data for this test.
test_ssp = os.path.join(
common.autotest_dir,
'site_utils', 'lxc', 'test', 'test_ssp.tar.bz2')
diff --git a/site_utils/lxc/zygote.py b/site_utils/lxc/zygote.py
index b939e54..21b5f2b 100644
--- a/site_utils/lxc/zygote.py
+++ b/site_utils/lxc/zygote.py
@@ -2,12 +2,16 @@
# 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
@@ -72,6 +76,55 @@
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);
diff --git a/site_utils/lxc/zygote_unittest.py b/site_utils/lxc/zygote_unittest.py
index e84f325..5668556 100644
--- a/site_utils/lxc/zygote_unittest.py
+++ b/site_utils/lxc/zygote_unittest.py
@@ -15,6 +15,8 @@
import common
from autotest_lib.client.bin import utils
from autotest_lib.site_utils import lxc
+from autotest_lib.site_utils.lxc import constants
+from autotest_lib.site_utils.lxc import unittest_http
from autotest_lib.site_utils.lxc import unittest_logging
from autotest_lib.site_utils.lxc import utils as lxc_utils
@@ -152,6 +154,49 @@
self.assertEqual(test_string, test_output)
+ def testInstallSsp(self):
+ """Verifies that installing the ssp in the container works."""
+ # Hard-coded path to some golden data for this test.
+ test_ssp = os.path.join(
+ common.autotest_dir,
+ 'site_utils', 'lxc', 'test', 'test_ssp.tar.bz2')
+ # Create a container, install the self-served ssp, then check that it is
+ # installed into the container correctly.
+ with self.createZygote() as zygote:
+ # Note: start the zygote first, then install the SSP. This mimics
+ # the way things would work in the production environment.
+ zygote.start(wait_for_network=False)
+ with unittest_http.serve_locally(test_ssp) as url:
+ zygote.install_ssp(url)
+
+ # The test ssp just contains a couple of text files, in known
+ # locations. Verify the location and content of those files in the
+ # container.
+ cat = lambda path: zygote.attach_run('cat %s' % path).stdout
+ test0 = cat(os.path.join(constants.CONTAINER_AUTOTEST_DIR,
+ 'test.0'))
+ test1 = cat(os.path.join(constants.CONTAINER_AUTOTEST_DIR,
+ 'dir0', 'test.1'))
+ self.assertEquals('the five boxing wizards jumped quickly',
+ test0)
+ self.assertEquals('the quick brown fox jumps over the lazy dog',
+ test1)
+
+
+ def testInstallControlFile(self):
+ """Verifies that installing a control file in the container works."""
+ _unused, tmpfile = tempfile.mkstemp()
+ with self.createZygote() as zygote:
+ # Note: start the zygote first. This mimics the way things would
+ # work in the production environment.
+ zygote.start(wait_for_network=False)
+ zygote.install_control_file(tmpfile)
+ # Verify that the file is found in the zygote.
+ zygote.attach_run(
+ 'test -f %s' % os.path.join(lxc.CONTROL_TEMP_PATH,
+ os.path.basename(tmpfile)))
+
+
@contextmanager
def createZygote(self,
name = None,
@@ -214,7 +259,7 @@
# Hack: python unittest also processes args. Construct an argv to pass to
# it, that filters out the options it won't recognize.
if args.verbose:
- argv.append('-v')
+ argv.insert(0, '-v')
argv.insert(0, sys.argv[0])
return args, argv