[ACT][PATCH 1/1] UBUNTU: SAUCE: ubuntu_lxc: improve test granularity and idempotency

Po-Hsu Lin po-hsu.lin at canonical.com
Wed Aug 18 12:34:21 UTC 2021


BugLink: https://bugs.launchpad.net/bugs/1939859

This test suite contains two tests:
  * setup - task to build the test
  * exercise - task to run 26~46 sub-tests

With all the sub-tests running in the exercise test, this makes it
hard to do the result review and hinting.

Improve the test idempotency by:
  * Move the task in setup() to initialize(), so that it can be
    restarted at any time

Improve the test granularity by:
  * Move the test build / configuration commands from the exercise
    script to initialize()
  * On older releases, run all tests installed by lxc-tests directly
  * On newer releases, instead of calling autopkgtest to build and run
    sub-tests, build them from source packages in initialize() then
    run all tests directly

Also, this patch can fix the missing python3 api test issue on Bionic
and above (bug 1844673).

Signed-off-by: Po-Hsu Lin <po-hsu.lin at canonical.com>
---
 ubuntu_lxc/control       |  56 +++++++++++++-
 ubuntu_lxc/exercise      | 158 ---------------------------------------
 ubuntu_lxc/ubuntu_lxc.py |  86 ++++++++++++++-------
 3 files changed, 112 insertions(+), 188 deletions(-)
 delete mode 100644 ubuntu_lxc/exercise

diff --git a/ubuntu_lxc/control b/ubuntu_lxc/control
index 11b563ab..f54349e3 100644
--- a/ubuntu_lxc/control
+++ b/ubuntu_lxc/control
@@ -12,7 +12,59 @@ DOC = "Test as much of the LXC kernel functionality as possible"
 
 name = 'ubuntu_lxc'
 
-results = job.run_test_detail('ubuntu_lxc', test_name='setup', tag='setup', timeout=60*30)
-results = job.run_test_detail('ubuntu_lxc', test_name='exercise', tag='exercise', timeout=60*60*2)
+result = job.run_test_detail('ubuntu_lxc', test_name='setup', tag='setup', timeout=60*30)
+if result == 'GOOD':
+    flist = os.listdir('/usr/bin/')
+    sub_tests = [fn for fn in flist if fn.startswith('lxc-test-')]
+    # For newer releases
+    if not sub_tests:
+        fpath = '/tmp/lxc-pkg-ubuntu/src/tests/'
+        flist = os.listdir(fpath)
+        for fn in flist:
+            fullpath = fpath + fn
+            if fn.startswith('lxc-test-') and os.access(fullpath, os.X_OK) and not fn.endswith('.in'):
+                sub_tests.append(fn)
+    sub_tests.sort()
+
+    # Python3 API test
+    fn = 'api_test.py'
+    fpath = '/usr/share/doc/python3-lxc/examples/'
+    if os.path.isfile(fpath + fn + '.gz'):
+        utils.system('gzip -d ' + fpath + fn + '.gz', ignore_status=True)
+    if os.path.isfile(fpath + fn):
+        sub_tests.append(fn)
+
+    if sub_tests:
+        for test in sub_tests:
+            # Some tests can't be run standalone
+            if test == 'lxc-test-may-control':
+                continue
+            # Skip some tests when running in a container
+            elif test in ['lxc-test-apparmor', 'lxc-test-device-add-remove', 'lxc-test-reboot']:
+                if os.path.isfile('/run/container_type') or (utils.system('type systemd-detect-virt &> /dev/null', ignore_status=True) == 0 and utils.system('systemd-detect-virt  --container &> /dev/null', ignore_status=True) == 0):
+                    continue
+            # Skip userns tests in unprivileged containers
+            elif test in ['lxc-test-unpriv', 'lxc-test-unpriv']:
+                if os.path.isfile('/proc/self/uid_map') and utils.system_output('! grep "4294967295$" /proc/self/uid_map', ignore_status=True) == 0:
+                    continue
+            # Skip some tests because of broken busybox, this is working on X/F/H but not B
+            elif test == 'lxc-test-state-server':
+                continue
+
+            # Skip some tests on old kernels, this must be in another if statement as we have lxc-test-unpriv checked above
+            if test in ['lxc-test-unpriv', 'lxc-test-usernic']:
+                if not os.path.isfile('/proc/self/uid_map') or not os.path.isfile('/etc/subuid') or not os.path.isfile('/etc/subgid'):
+                    continue
+
+            job.run_test_detail('ubuntu_lxc', test_name=test, tag=test, timeout=60*5)
+    else:
+        print('ERROR: no sub_tests found, please check test build if running on Bionic and later releases')
+
+    '''Cleanup the change made for broken gpg2'''
+    if os.environ.get('http_proxy') and os.path.isfile('/usr/bin/dirmngr') and os.path.isfile('/usr/bin/dirmngr.orig'):
+        os.remove('/usr/bin/dirmngr')
+        cmd = 'dpkg-divert --divert /usr/bin/dirmngr.orig --rename --remove /usr/bin/dirmngr'
+        utils.system(cmd, ignore_status=True)
+
 
 # vi:set ts=4 sw=4 expandtab syntax=python:
diff --git a/ubuntu_lxc/exercise b/ubuntu_lxc/exercise
deleted file mode 100644
index 5cbbe33b..00000000
--- a/ubuntu_lxc/exercise
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/bin/sh
-# Environment
-set -eu
-
-unset TMPDIR
-
-TEST_PASS=0
-TEST_FAIL=0
-TEST_IGNORED=0
-
-IGNORE_LIST=""
-
-# FIXME: This should be done in default adt environment
-# Detect the ubuntu-ci setup
-if echo "" | nc -w 2 squid.internal 3128 >/dev/null 2>&1; then
-    echo "Running in the Canonical CI environment"
-    export http_proxy="http://squid.internal:3128"
-    export https_proxy="http://squid.internal:3128"
-elif echo "" | nc -w 2 91.189.89.216 3128 >/dev/null 2>&1; then
-    echo "Running in the Canonical enablement environment"
-    export http_proxy="http://91.189.89.216:3128"
-    export https_proxy="http://91.189.89.216:3128"
-elif echo "" | nc -w 2 10.245.64.1 3128 >/dev/null 2>&1; then
-    echo "Running in the Canonical enablement environment"
-    export http_proxy="http://10.245.64.1:3128"
-    export https_proxy="http://10.245.64.1:3128"
-fi
-
-# Helper functions
-pass() {
-    TEST_PASS=$((${TEST_PASS}+1))
-    echo "PASS: $1"
-}
-
-fail() {
-    for entry in $IGNORE_LIST; do
-        if [ "$entry" = "$2" ]; then
-            ignore $1
-            return
-        fi
-    done
-
-    TEST_FAIL=$((${TEST_FAIL}+1))
-    echo "FAIL: $1"
-
-    if [ -f "$3" ]; then
-        echo "---"
-        cat $3
-        echo "---"
-    fi
-}
-
-ignore() {
-    TEST_IGNORED=$((${TEST_IGNORED}+1))
-    echo "IGNORED: $*"
-}
-
-summary() {
-    echo ""
-    echo "SUMMARY: pass=$TEST_PASS, fail=$TEST_FAIL, ignored=$TEST_IGNORED"
-}
-
-# Source distro information
-[ -e /etc/lsb-release ] && . /etc/lsb-release
-
-# Workaround for broken gpg2
-if [ "${http_proxy:-none}" != "none" ] && [ -e /usr/bin/dirmngr ]; then
-    dpkg-divert --divert /usr/bin/dirmngr.orig --rename --add /usr/bin/dirmngr
-    (
-    cat << EOF
-#!/bin/sh
-exec /usr/bin/dirmngr.orig --honor-http-proxy \$@
-EOF
-    ) > /usr/bin/dirmngr
-    chmod +x /usr/bin/dirmngr
-fi
-
-# Override the GPG server
-sed -i '/^DOWNLOAD_URL=$/a DOWNLOAD_KEYSERVER="hkp://keyserver.ubuntu.com:80"' /usr/share/lxc/templates/lxc-download
-
-# The actual tests
-## Default testsuite
-for testbin in /usr/bin/lxc-test-*; do
-    STRING="lxc-tests: $testbin"
-    [ ! -x "$testbin" ] && continue
-
-    # Some tests can't be run standalone
-    [ "$testbin" = "/usr/bin/lxc-test-may-control" ] && continue
-
-    # Skip some tests when running in a container
-    if [ -f /run/container_type ] || (type systemd-detect-virt >/dev/null 2>&1 && systemd-detect-virt  --container >/dev/null 2>&1); then
-        [ "$testbin" = "/usr/bin/lxc-test-apparmor" ] && \
-            ignore "$STRING" && continue
-
-        [ "$testbin" = "/usr/bin/lxc-test-device-add-remove" ] && \
-            ignore "$STRING" && continue
-
-        [ "$testbin" = "/usr/bin/lxc-test-reboot" ] && \
-            ignore "$STRING" && continue
-    fi
-
-    # Skip userns tests in unprivileged containers
-    if [ -f /proc/self/uid_map ] && \
-            ! grep -q "4294967295$" /proc/self/uid_map; then
-
-        [ "$testbin" = "/usr/bin/lxc-test-unpriv" ] && \
-            ignore "$STRING" && continue
-
-        [ "$testbin" = "/usr/bin/lxc-test-usernic" ] && \
-            ignore "$STRING" && continue
-    fi
-
-    # Skip some tests on old kernels
-    if [ ! -f /proc/self/uid_map ] || [ ! -f /etc/subuid ] || \
-       [ ! -f /etc/subgid ]; then
-        [ "$testbin" = "/usr/bin/lxc-test-unpriv" ] && \
-            ignore "$STRING" && continue
-
-        [ "$testbin" = "/usr/bin/lxc-test-usernic" ] && \
-            ignore "$STRING" && continue
-    fi
-
-    OUT=$(mktemp)
-    $testbin >$OUT 2>&1 && pass "$STRING" || fail "$STRING" "$testbin" "$OUT"
-    rm $OUT
-done
-
-## Python3 testsuite
-STRING="python3: API"
-if [ ! -f /usr/share/doc/python3-lxc/examples/api_test.py.gz ]; then
-    ignore "$STRING"
-else
-    OUT=$(mktemp)
-
-    PYTEST=$(mktemp)
-    cat /usr/share/doc/python3-lxc/examples/api_test.py.gz | gzip -d > $PYTEST
-    python3 $PYTEST >$OUT 2>&1 && pass "$STRING" || \
-        fail "$STRING" "python3" "$OUT"
-    rm $PYTEST
-
-    rm $OUT
-fi
-
-# Workaround for broken gpg2
-if [ "${http_proxy:-none}" != "none" ] && [ -e /usr/bin/dirmngr ]; then
-    rm /usr/bin/dirmngr
-    dpkg-divert --divert /usr/bin/dirmngr.orig --rename --remove /usr/bin/dirmngr
-fi
-
-# Test summary
-summary
-
-# Remove the reboot container if it got left behind (lp:1788574)
-sudo lxc-destroy reboot &>/dev/null || true
-
-[ "$TEST_FAIL" != "0" ] && exit 1
-
-exit 0
diff --git a/ubuntu_lxc/ubuntu_lxc.py b/ubuntu_lxc/ubuntu_lxc.py
index 2bfa5df9..41e586f0 100644
--- a/ubuntu_lxc/ubuntu_lxc.py
+++ b/ubuntu_lxc/ubuntu_lxc.py
@@ -1,8 +1,10 @@
 #
 #
 from autotest.client                        import test, utils
+import multiprocessing
 import os
 import platform
+import shutil
 
 class ubuntu_lxc(test.test):
     version = 1
@@ -15,44 +17,69 @@ class ubuntu_lxc(test.test):
             ]
         else:
             pkgs = [
-                'automake',
-                'autopkgtest',
+                'autoconf',
                 'build-essential',
-                'cloud-image-utils',
-                'debhelper',
-                'debootstrap',
-                'dh-apparmor',
-                'dh-autoreconf',
-                'docbook2x',
+                'dirmngr',
                 'libapparmor-dev',
                 'libcap-dev',
-                'libgnutls28-dev',
-                'libpam0g-dev',
-                'libseccomp-dev',
-                'libselinux1-dev',
+                'libtool',
                 'lxc',
-                'lxc1',
-                'lxc-dev',
                 'pkg-config',
-                'texinfo',
+                'python3-lxc',
             ]
             gcc = 'gcc' if arch in ['ppc64le', 'aarch64', 's390x', 'riscv64'] else 'gcc-multilib'
             pkgs.append(gcc)
 
         pkgs.append('liblxc1')
         cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
-        self.results = utils.system_output(cmd, retain_output=True)
+        utils.system_output(cmd, retain_output=True)
 
-    def initialize(self):
+    def initialize(self, test_name):
         try:
             self.series = platform.dist()[2]
         except AttributeError:
             import distro
             self.series = distro.codename()
-        pass
 
-    def setup(self):
+        if test_name != 'setup':
+            return
+
         self.install_required_pkgs()
+        if self.series not in ['precise', 'trusty', 'xenial']:
+            os.chdir('/tmp')
+            shutil.rmtree('lxc-pkg-ubuntu', ignore_errors=True)
+            cmd = 'git clone --depth=1 https://github.com/lxc/lxc-pkg-ubuntu.git -b dpm-{}'.format(self.series)
+            utils.system(cmd)
+            os.chdir('/tmp/lxc-pkg-ubuntu')
+            gcc_multiarch = utils.system_output('gcc -print-multiarch',  retain_output=False)
+            utils.system('autoreconf -f -i')
+            cmd = '--enable-tests --disable-rpath --disable-doc --with-distro=ubuntu \
+                   --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
+                   --libdir=\${{prefix}}/lib/{0} \
+                   --libexecdir=\${{prefix}}/lib/{0} \
+                    --with-rootfs-path=\${{prefix}}/lib/{0}/lxc'.format(gcc_multiarch)
+            utils.configure(cmd)
+            try:
+                nprocs = '-j' + str(multiprocessing.cpu_count())
+            except:
+                nprocs = ''
+            utils.make(nprocs)
+
+        # Override the GPG server
+        fn = '/usr/share/lxc/templates/lxc-download'
+        cmd = "grep -q 'DOWNLOAD_KEYSERVER=\"hkp://keyserver.ubuntu.com:80\"' {0} || sed -i '/^DOWNLOAD_URL=$/a DOWNLOAD_KEYSERVER=\"hkp://keyserver.ubuntu.com:80\"' {0}".format(fn)
+        utils.system(cmd)
+
+        # Workaround for broken gpg2
+        if os.environ.get('http_proxy') and os.path.isfile('/usr/bin/dirmngr'):
+            cmd = 'dpkg-divert --divert /usr/bin/dirmngr.orig --rename --add /usr/bin/dirmngr'
+            utils.system(cmd)
+            with open('/usr/bin/dirmngr', 'w') as f:
+                f.write('#!/bin/sh\n')
+                f.write('exec /usr/bin/dirmngr.orig --honor-http-proxy $@\n')
+            cmd = 'chmod +x /usr/bin/dirmngr'
+            utils.system(cmd)
+
 
     def run_once(self, test_name):
         if test_name == 'setup':
@@ -60,17 +87,20 @@ class ubuntu_lxc(test.test):
 
         # Destroy the "reboot" container which might have been left
         # behind (LP#1788574)
-        cmd = 'lxc-destroy reboot'
-        utils.system(cmd, ignore_status=True)
+        if test_name == 'lxc-test-api-reboot':
+            cmd = 'lxc-destroy reboot &> /dev/null'
+            utils.system(cmd, ignore_status=True)
 
-        if self.series in ['precise', 'trusty', 'xenial', 'artful']:
-            cmd = '/bin/sh %s/exercise' % self.bindir
+        if self.series in ['precise', 'trusty', 'xenial']:
+            fpath = '/usr/bin/'
         else:
-            proxy = ''
-            if os.environ.get('http_proxy'):
-                proxy = 'http_proxy=%s' % os.environ.get('http_proxy')
-            cmd = '%s autopkgtest lxc -- null' % proxy
+            fpath = '/tmp/lxc-pkg-ubuntu/src/tests/'
+
+        # Override the path for Python3 API test
+        if test_name == 'api_test.py':
+            fpath = 'python3 /usr/share/doc/python3-lxc/examples/'
 
-        self.results = utils.system_output(cmd, retain_output=True)
+        cmd = fpath + test_name
+        utils.system_output(cmd, retain_output=True)
 
 # vi:set ts=4 sw=4 expandtab syntax=python:
-- 
2.25.1




More information about the kernel-team mailing list