Repository navigation
Run the ppc64le and s390x compose tests in containers - #83
Merged
Merged
Conversation
ci/container-guests.sh starts a container per name in $guests from an almalinux/<version>-init image, systemd as PID 1, of the given architecture: natively on a runner of that architecture, run by QEMU user-mode emulation on another one. It waits until systemd has booted each container and fixes what does not boot under emulation: units with credentials (ImportCredential=) fail there with 243/CREDENTIALS, so it runs systemd-sysusers and systemd-tmpfiles itself, gives journald (which imports credentials since AlmaLinux 10) a copy of its unit without them, and restarts what failed at boot, D-Bus with it. The services installed later fail the same way: libvirtd and virtsecretd load an encrypted credential since libvirt 12.8 (AlmaLinux Kitten), so under emulation a drop-in clears their credentials. Not a top-level drop-in for every service: under s390x emulation systemd reports a unit with a drop-in as changed on disk, and postgresql-setup then refuses to initialize the database. It lists the units that failed at boot and those still failed.
Run the compose tests in 4 AlmaLinux ppc64le containers (podman, systemd as PID 1, ci/container-guests.sh), split between them like on x86_64 and aarch64. The containers share the runner's kernel, so the tests run with the tmt context container=yes and CONTAINERTEST=1. In the AlmaLinux organization the containers run natively on a POWER runner, a POWER10 one for AlmaLinux 10 (ubuntu-26.04-ppc64le(-p10)). Elsewhere, e.g. in forks, they run on an x86_64 runner (ubuntu-26.04) under QEMU user-mode emulation, which needs QEMU 10.1 or newer (QEMU issue 1769) and the binfmt_misc C flag for setuid programs; the tests' time limits are scaled x8 there instead of x2, and they get emulated_guest=true. The containers are made more like an installed system: curl-minimal is swapped for curl and hostname installed, rsync (tmt from pip) on AlmaLinux 10 and initscripts (/sbin/service) on AlmaLinux 8. The runner's inotify instances limit, which the rootful containers share, is raised where the runner allows it, and its use shown.
Run the compose tests in 4 AlmaLinux s390x containers like the ppc64le
ones: natively in the AlmaLinux organization (ubuntu-26.04-s390x), under
QEMU user-mode emulation on an x86_64 runner elsewhere, e.g. in forks.
The native s390x runner is an Incus container with AppArmor and Ubuntu's
profiles, and podman runs the containers unconfined, so a program
started from a path a runner profile attaches to gets that profile:
anything started as /usr/bin/hostname or /usr/bin/gs failed to load
libc ("cannot apply additional memory protection after relocation:
Permission denied"), even with the profile in complain mode. Before
starting the containers unload these profiles, but not those flagged
unconfined: they confine nothing, they grant (user namespaces to podman,
crun, ...), the containers run under one of them, and reloaded in
complain mode they broke podman's overlay storage.
The ppc64le and s390x tests run in containers (tmt context container=yes, CONTAINERTEST=1), which share the runner's kernel. Disable for container=yes the tests a container cannot run: attr (no loop device mounts), libbpf-tools and perf (BPF programs and perf events of the runner's kernel), libvirt/net (no libvirt networks), podman (no nested containers), selinux (no SELinux), sysstat/iostat (no dropping the page cache). Skip with CONTAINERTEST=1 p_kvdo (a kernel module), the NIC check of p_tcpdump and p_osbuild (an image build needs loop devices and mounts). t_GetArch takes the architecture from uname when there is no kernel package. List the skipped tests, with the reason, in the run-page summary and the Mattermost message of the ppc64le and s390x workflows: they only count the tests that ran.
- p_bash: bash on s390x is built for the IBM vendor up to AlmaLinux 9 (s390x-ibm-linux-gnu), for redhat since 10 (s390x-redhat-linux-gnu). - libbpf-tools: bpf-numamove is not shipped for s390x. - libvirt/socket: libvirt reads the host's system information on s390x from /proc/sysinfo, which only an s390x kernel has: an emulated s390x container on another one has none, so skip the sysinfo check there. - p_gzip: s390x machines with DFLTCC (z15 and newer) compress in hardware, which gives the test file another compressed size: check the uncompressed size and name of 'gzip -l' only, not the md5sum of its whole output.
The ppc64le and s390x tests run emulated on forks (emulated_guest=true), several times slower than on the hardware the tests are meant for. - p_exim, p_openssh: the expect helpers wait 1 or 2 seconds for an answer, too short there: wait 30 seconds in an emulated guest. - p_osbuild: building an image takes more than an hour there: skip it in an emulated guest.
On the native s390x runner the containers could not resolve any name for a whole job, in 3 of 21 runs, while the runner itself could: "Update the system" waited 2.5 minutes for its first name in every container, then failed with "Could not resolve host: mirrors.almalinux.org". The containers reach the runner's network through podman's default one, 10.88.0.0/16, and such a runner's DNS server was 10.88.92.1: the containers sent their queries to the bridge, so no name resolved (HTTPS to an address still worked). Before starting the containers, take the first of 10.88.0.0/16, 10.89.0.0/16, ... that is none of the runner's routes nor nameservers. When that is not 10.88.0.0/16, start the containers on a network of their own with it, without DNS like podman's default network, so that they still use the runner's nameservers. After starting them check that each one resolves a name, for about a minute. If they still cannot, print what DNS goes through (the runner's and the containers' nameservers, podman's network, IP forwarding, whether a container reaches the internet by address), reload podman's network, which re-applies its firewall rules, and check again. Fail the step at once if that does not help.
The count of root's inotify instances in use logged after the containers start does not show how near the runner's limit a run gets: in the native ppc64le runs that failed, with the limit at 128, D-Bus and libvirtd ran out of them minutes into the tests and for the rest of them. Count root's inotify instances every 5 seconds while the tests run and log the largest count, with how many each process held and in which container, to tell what holds them when it happens again.
andrewlukoshko
approved these changes
Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Runs the compose tests for ppc64le and s390x in 4 AlmaLinux containers
(podman, systemd as PID 1), split between them the same way as on
x86_64 and aarch64.
(
ubuntu-26.04-ppc64le,-p10for AlmaLinux 10 and Kitten) and onubuntu-26.04-s390x.tests' time limits are scaled ×8 there instead of ×2, and the tests
get
emulated_guest=true.The containers share the runner's kernel, so the tests run with the tmt
context
container=yesandCONTAINERTEST=1.Changes
CI
ci/container-guests.shstarts the containers and waits for systemdto boot in each one.
243/CREDENTIALS. The script runs sysusers and tmpfiles itself,gives journald a copy of its unit without credentials, and clears
the credentials of libvirtd and virtsecretd (libvirt 12.8, Kitten).
prints what DNS goes through, reloads podman's network once, and
fails the step if that doesn't help.
overlaps the runner's routes or nameservers, the containers get a
network of their own on a free subnet. One native s390x runner's DNS
server was 10.88.92.1, so the containers' queries went into the
bridge and no name resolved.
program started from a path one of its profiles attaches to (e.g.
/usr/bin/hostname,/usr/bin/gs) failed to load libc, so theconfining profiles are unloaded. The unconfined ones are kept: podman
needs them.
instances. The limit is raised to 8192 where the runner allows it.
The native runners don't allow it and keep 128 or 1024.
ci/inotify-peak.shlogs the peak count while the tests run, andwhich process and container hold them. With 4 containers the peak is
46–48, against a limit of 128. In 2 earlier runs something held about
75 more for over 15 minutes, and D-Bus and libvirtd failed; this log
is there to catch it if it happens again.
installed, and so are rsync (AlmaLinux 10) and initscripts
(AlmaLinux 8), so the containers are closer to an installed system.
list the skipped tests with the reason.
Tests
container=yes:kernel.
CONTAINERTEST=1:ibmup to AlmaLinux 9and
redhatfrom 10.bpf-numamoveisn't shipped for s390x./proc/sysinfo.uncompressed size and the name are checked.
answer.
unamewhen there is nokernel package.
Testing
s390x. Jobs take 11–25 minutes.
architectures.
don't overlap 10.88.0.0/16, so they kept podman's default network as
before.