summaryrefslogtreecommitdiff
path: root/tests/cloud_tests
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2018-01-25 12:26:34 -0700
committerChad Smith <chad.smith@canonical.com>2018-01-25 12:26:34 -0700
commitbc84f5023f795c261e32cf0690b2d29e12cfaedd (patch)
tree273896aca6e94badb3390aa87cfd240fe161d528 /tests/cloud_tests
parentbccee93d398ab26a3ee3b427b8f26a7de8375af3 (diff)
downloadvyos-cloud-init-bc84f5023f795c261e32cf0690b2d29e12cfaedd.tar.gz
vyos-cloud-init-bc84f5023f795c261e32cf0690b2d29e12cfaedd.zip
tests: Collect script output as binary, collect systemd journal, fix lxd.
This adds collection a gzip compressed systemd journal on systemd systems. The file can later be reviewed with:   zcat system.journal.gz > system.journal   journalctl --file=system.journal [-o short-monotonic ..] To support this:   * modify test harness infrastructure to not assume content is utf-8.   * fix lxd platform to support make '_execute' return bytes rather     than a string. https://github.com/lxc/pylxd/issues/268 Also switched the base collectors to use /bin/sh as others already did.
Diffstat (limited to 'tests/cloud_tests')
-rw-r--r--tests/cloud_tests/collect.py7
-rw-r--r--tests/cloud_tests/platforms/lxd/instance.py43
-rw-r--r--tests/cloud_tests/testcases.yaml27
-rw-r--r--tests/cloud_tests/testcases/base.py6
-rw-r--r--tests/cloud_tests/verify.py2
5 files changed, 52 insertions, 33 deletions
diff --git a/tests/cloud_tests/collect.py b/tests/cloud_tests/collect.py
index 33acbb1e..5ea88e50 100644
--- a/tests/cloud_tests/collect.py
+++ b/tests/cloud_tests/collect.py
@@ -24,6 +24,13 @@ def collect_script(instance, base_dir, script, script_name):
(out, err, exit) = instance.run_script(
script.encode(), rcs=False,
description='collect: {}'.format(script_name))
+ if err:
+ LOG.debug("collect script %s had stderr: %s", script_name, err)
+ if not isinstance(out, bytes):
+ raise util.PlatformError(
+ "Collection of '%s' returned type %s, expected bytes: %s" %
+ (script_name, type(out), out))
+
c_util.write_file(os.path.join(base_dir, script_name), out)
diff --git a/tests/cloud_tests/platforms/lxd/instance.py b/tests/cloud_tests/platforms/lxd/instance.py
index 0d697c05..d2d2a1fd 100644
--- a/tests/cloud_tests/platforms/lxd/instance.py
+++ b/tests/cloud_tests/platforms/lxd/instance.py
@@ -6,6 +6,8 @@ import os
import shutil
from tempfile import mkdtemp
+from cloudinit.util import subp, ProcessExecutionError
+
from ..instances import Instance
@@ -29,6 +31,7 @@ class LXDInstance(Instance):
platform, name, properties, config, features)
self.tmpd = mkdtemp(prefix="%s-%s" % (type(self).__name__, name))
self._setup_console_log()
+ self.name = name
@property
def pylxd_container(self):
@@ -55,33 +58,25 @@ class LXDInstance(Instance):
if env is None:
env = {}
- if stdin is not None:
- # pylxd does not support input to execute.
- # https://github.com/lxc/pylxd/issues/244
- #
- # The solution here is write a tmp file in the container
- # and then execute a shell that sets it standard in to
- # be from that file, removes it, and calls the comand.
- tmpf = self.tmpfile()
- self.write_data(tmpf, stdin)
- ncmd = 'exec <"{tmpf}"; rm -f "{tmpf}"; exec "$@"'
- command = (['sh', '-c', ncmd.format(tmpf=tmpf), 'stdinhack'] +
- list(command))
+ env_args = []
+ if env:
+ env_args = ['env'] + ["%s=%s" for k, v in env.items()]
# ensure instance is running and execute the command
self.start()
- # execute returns a ContainerExecuteResult, named tuple
- # (exit_code, stdout, stderr)
- res = self.pylxd_container.execute(command, environment=env)
-
- # get out, exit and err from pylxd return
- if not hasattr(res, 'exit_code'):
- # pylxd 2.1.3 and earlier only return out and err, no exit
- raise RuntimeError(
- "No 'exit_code' in pylxd.container.execute return.\n"
- "pylxd > 2.2 is required.")
-
- return res.stdout, res.stderr, res.exit_code
+
+ # Use cmdline client due to https://github.com/lxc/pylxd/issues/268
+ exit_code = 0
+ try:
+ stdout, stderr = subp(
+ ['lxc', 'exec', self.name, '--'] + env_args + list(command),
+ data=stdin, decode=False)
+ except ProcessExecutionError as e:
+ exit_code = e.exit_code
+ stdout = e.stdout
+ stderr = e.stderr
+
+ return stdout, stderr, exit_code
def read_data(self, remote_path, decode=False):
"""Read data from instance filesystem.
diff --git a/tests/cloud_tests/testcases.yaml b/tests/cloud_tests/testcases.yaml
index 7183e017..8e0fb62f 100644
--- a/tests/cloud_tests/testcases.yaml
+++ b/tests/cloud_tests/testcases.yaml
@@ -7,22 +7,37 @@ base_test_data:
#cloud-config
collect_scripts:
cloud-init.log: |
- #!/bin/bash
+ #!/bin/sh
cat /var/log/cloud-init.log
cloud-init-output.log: |
- #!/bin/bash
+ #!/bin/sh
cat /var/log/cloud-init-output.log
instance-id: |
- #!/bin/bash
+ #!/bin/sh
cat /run/cloud-init/.instance-id
result.json: |
- #!/bin/bash
+ #!/bin/sh
cat /run/cloud-init/result.json
status.json: |
- #!/bin/bash
+ #!/bin/sh
cat /run/cloud-init/status.json
cloud-init-version: |
- #!/bin/bash
+ #!/bin/sh
dpkg-query -W -f='${Version}' cloud-init
+ system.journal.gz: |
+ #!/bin/sh
+ [ -d /run/systemd ] || { echo "not systemd."; exit 0; }
+ fail() { echo "ERROR:" "$@" 1>&2; exit 1; }
+ journal=""
+ for d in /run/log/journal /var/log/journal; do
+ for f in $d/*/system.journal; do
+ [ -f "$f" ] || continue
+ [ -z "$journal" ] ||
+ fail "multiple journal found: $f $journal."
+ journal="$f"
+ done
+ done
+ [ -f "$journal" ] || fail "no journal file found."
+ gzip --to-stdout "$journal"
# vi: ts=4 expandtab
diff --git a/tests/cloud_tests/testcases/base.py b/tests/cloud_tests/testcases/base.py
index 1c5b5405..20e95955 100644
--- a/tests/cloud_tests/testcases/base.py
+++ b/tests/cloud_tests/testcases/base.py
@@ -30,12 +30,14 @@ class CloudTestCase(unittest.TestCase):
raise AssertionError('Key "{}" not in cloud config'.format(name))
return self.cloud_config[name]
- def get_data_file(self, name):
+ def get_data_file(self, name, decode=True):
"""Get data file failing test if it is not present."""
if name not in self.data:
raise AssertionError('File "{}" missing from collect data'
.format(name))
- return self.data[name]
+ if not decode:
+ return self.data[name]
+ return self.data[name].decode('utf-8')
def get_instance_id(self):
"""Get recorded instance id."""
diff --git a/tests/cloud_tests/verify.py b/tests/cloud_tests/verify.py
index fc1efcfc..2a9fd520 100644
--- a/tests/cloud_tests/verify.py
+++ b/tests/cloud_tests/verify.py
@@ -29,7 +29,7 @@ def verify_data(base_dir, tests):
data = {}
test_dir = os.path.join(base_dir, test_name)
for script_name in os.listdir(test_dir):
- with open(os.path.join(test_dir, script_name), 'r') as fp:
+ with open(os.path.join(test_dir, script_name), 'rb') as fp:
data[script_name] = fp.read()
# get test suite and launch tests