summaryrefslogtreecommitdiff
path: root/tests/cloud_tests/images
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2017-11-06 17:39:00 -0500
committerScott Moser <smoser@brickies.net>2017-11-06 17:39:00 -0500
commit8622491c29f30862a1a1d7ad2cba023981acc8ce (patch)
tree597b08c4ca66575cc9567263030876814999beeb /tests/cloud_tests/images
parentbe8e3d3c5b5d3d6a3d222383a58fd5feecead7b7 (diff)
downloadvyos-cloud-init-8622491c29f30862a1a1d7ad2cba023981acc8ce.tar.gz
vyos-cloud-init-8622491c29f30862a1a1d7ad2cba023981acc8ce.zip
tests: integration test cleanup and full pass of nocloud-kvm.
Integration test harness changes: * Enable collection of console log in nocloud-kvm and lxd. * Collect the console log to results for all test runs. * change 'tmpfile' to pick name locally instead of using 'mktemp'. * drop the 'instance' attribute from nocloud-kvm Image and demote LXDImage.instance to a private attribute. This is because Images do not actually have instances. (LXDImage internally uses a booted system to modify the image). * Add 'TargetBase' as a superclass of Image and Instance providing implementations of execute, read_data, write_data, pull_file, and push_file. These all depend on an implementation of _execute. * Improve '_execute' implementations to support accepting stdin. * execute supports 'rcs=False' meaning 'do not raise exception'. * Drop support for pylxd < 2.2. older versions cannot determine exit code of 'execute', which makes them unusable. * make NoCloudKVMInstance._execute run as root via sudo. This required some changes so that 'hostname' could be reverse-looked up in order to avoid sudo taking a long time (~20 seconds). * re-use existing ssh connection in nocloud-kvm. Test changes here: * do not use /tmp, but rather /var/tmp (LP: #1707222) * make keys_to_console assertions more strict. * change user test cases to always add default (ubuntu) user so that nocloud-kvm's execute which operates over ssh can work.
Diffstat (limited to 'tests/cloud_tests/images')
-rw-r--r--tests/cloud_tests/images/base.py19
-rw-r--r--tests/cloud_tests/images/lxd.py32
-rw-r--r--tests/cloud_tests/images/nocloudkvm.py42
3 files changed, 39 insertions, 54 deletions
diff --git a/tests/cloud_tests/images/base.py b/tests/cloud_tests/images/base.py
index 0a1e0563..d503108a 100644
--- a/tests/cloud_tests/images/base.py
+++ b/tests/cloud_tests/images/base.py
@@ -2,8 +2,10 @@
"""Base class for images."""
+from ..util import TargetBase
-class Image(object):
+
+class Image(TargetBase):
"""Base class for images."""
platform_name = None
@@ -43,21 +45,6 @@ class Image(object):
# NOTE: more sophisticated options may be requied at some point
return self.config.get('setup_overrides', {})
- def execute(self, *args, **kwargs):
- """Execute command in image, modifying image."""
- raise NotImplementedError
-
- def push_file(self, local_path, remote_path):
- """Copy file at 'local_path' to instance at 'remote_path'."""
- raise NotImplementedError
-
- def run_script(self, *args, **kwargs):
- """Run script in image, modifying image.
-
- @return_value: script output
- """
- raise NotImplementedError
-
def snapshot(self):
"""Create snapshot of image, block until done."""
raise NotImplementedError
diff --git a/tests/cloud_tests/images/lxd.py b/tests/cloud_tests/images/lxd.py
index fd4e93c2..5caeba41 100644
--- a/tests/cloud_tests/images/lxd.py
+++ b/tests/cloud_tests/images/lxd.py
@@ -24,7 +24,7 @@ class LXDImage(base.Image):
@param config: image configuration
"""
self.modified = False
- self._instance = None
+ self._img_instance = None
self._pylxd_image = None
self.pylxd_image = pylxd_image
super(LXDImage, self).__init__(platform, config)
@@ -38,9 +38,9 @@ class LXDImage(base.Image):
@pylxd_image.setter
def pylxd_image(self, pylxd_image):
- if self._instance:
+ if self._img_instance:
self._instance.destroy()
- self._instance = None
+ self._img_instance = None
if (self._pylxd_image and
(self._pylxd_image is not pylxd_image) and
(not self.config.get('cache_base_image') or self.modified)):
@@ -49,15 +49,19 @@ class LXDImage(base.Image):
self._pylxd_image = pylxd_image
@property
- def instance(self):
- """Property function."""
- if not self._instance:
- self._instance = self.platform.launch_container(
+ def _instance(self):
+ """Internal use only, returns a instance
+
+ This starts an lxc instance from the image, so it is "dirty".
+ Better would be some way to modify this "at rest".
+ lxc-pstart would be an option."""
+ if not self._img_instance:
+ self._img_instance = self.platform.launch_container(
self.properties, self.config, self.features,
use_desc='image-modification', image_desc=str(self),
image=self.pylxd_image.fingerprint)
- self._instance.start()
- return self._instance
+ self._img_instance.start()
+ return self._img_instance
@property
def properties(self):
@@ -144,20 +148,20 @@ class LXDImage(base.Image):
shutil.rmtree(export_dir)
shutil.rmtree(extract_dir)
- def execute(self, *args, **kwargs):
+ def _execute(self, *args, **kwargs):
"""Execute command in image, modifying image."""
- return self.instance.execute(*args, **kwargs)
+ return self._instance._execute(*args, **kwargs)
def push_file(self, local_path, remote_path):
"""Copy file at 'local_path' to instance at 'remote_path'."""
- return self.instance.push_file(local_path, remote_path)
+ return self._instance.push_file(local_path, remote_path)
def run_script(self, *args, **kwargs):
"""Run script in image, modifying image.
@return_value: script output
"""
- return self.instance.run_script(*args, **kwargs)
+ return self._instance.run_script(*args, **kwargs)
def snapshot(self):
"""Create snapshot of image, block until done."""
@@ -169,7 +173,7 @@ class LXDImage(base.Image):
# clone current instance
instance = self.platform.launch_container(
self.properties, self.config, self.features,
- container=self.instance.name, image_desc=str(self),
+ container=self._instance.name, image_desc=str(self),
use_desc='snapshot', container_config=conf)
# wait for cloud-init before boot_clean_script is run to ensure
# /var/lib/cloud is removed cleanly
diff --git a/tests/cloud_tests/images/nocloudkvm.py b/tests/cloud_tests/images/nocloudkvm.py
index a7af0e59..1e7962cb 100644
--- a/tests/cloud_tests/images/nocloudkvm.py
+++ b/tests/cloud_tests/images/nocloudkvm.py
@@ -2,6 +2,8 @@
"""NoCloud KVM Image Base Class."""
+from cloudinit import util as c_util
+
from tests.cloud_tests.images import base
from tests.cloud_tests.snapshots import nocloudkvm as nocloud_kvm_snapshot
@@ -19,24 +21,11 @@ class NoCloudKVMImage(base.Image):
@param img_path: path to the image
"""
self.modified = False
- self._instance = None
self._img_path = img_path
super(NoCloudKVMImage, self).__init__(platform, config)
@property
- def instance(self):
- """Returns an instance of an image."""
- if not self._instance:
- if not self._img_path:
- raise RuntimeError()
-
- self._instance = self.platform.create_image(
- self.properties, self.config, self.features, self._img_path,
- image_desc=str(self), use_desc='image-modification')
- return self._instance
-
- @property
def properties(self):
"""Dictionary containing: 'arch', 'os', 'version', 'release'."""
return {
@@ -46,20 +35,26 @@ class NoCloudKVMImage(base.Image):
'version': self.config['version'],
}
- def execute(self, *args, **kwargs):
+ def _execute(self, command, stdin=None, env=None):
"""Execute command in image, modifying image."""
- return self.instance.execute(*args, **kwargs)
+ return self.mount_image_callback(command, stdin=stdin, env=env)
- def push_file(self, local_path, remote_path):
- """Copy file at 'local_path' to instance at 'remote_path'."""
- return self.instance.push_file(local_path, remote_path)
+ def mount_image_callback(self, command, stdin=None, env=None):
+ """Run mount-image-callback."""
- def run_script(self, *args, **kwargs):
- """Run script in image, modifying image.
+ env_args = []
+ if env:
+ env_args = ['env'] + ["%s=%s" for k, v in env.items()]
- @return_value: script output
- """
- return self.instance.run_script(*args, **kwargs)
+ mic_chroot = ['sudo', 'mount-image-callback', '--system-mounts',
+ '--system-resolvconf', self._img_path,
+ '--', 'chroot', '_MOUNTPOINT_']
+ try:
+ out, err = c_util.subp(mic_chroot + env_args + list(command),
+ data=stdin, decode=False)
+ return (out, err, 0)
+ except c_util.ProcessExecutionError as e:
+ return (e.stdout, e.stderr, e.exit_code)
def snapshot(self):
"""Create snapshot of image, block until done."""
@@ -82,7 +77,6 @@ class NoCloudKVMImage(base.Image):
framework decide whether to keep or destroy everything.
"""
self._img_path = None
- self._instance.destroy()
super(NoCloudKVMImage, self).destroy()
# vi: ts=4 expandtab