The workflow step that puts the arm64-efi GRUB modules on the runner read a
directory listing over plain HTTP, took the last name in lexical order, and
unpacked the whole deb into / as root. Nothing authenticated the artifact, and
the name chosen was neither tied to the runner's suite nor to the installed
grub-mkimage.
install-grub-arm64-modules.sh now reads grub-efi-arm64-bin through apt in a
private state tree: apt verifies the InRelease signature of the suite that
/etc/os-release names, and the deb hash against that signed index. The host dpkg
architecture and the host sources are not changed. The script stops when the
deb and the host grub-mkimage report different GRUB upstream versions, unpacks
under TMPDIR, and copies only the files of usr/lib/grub/arm64-efi. The
documentation and the prebuilt images under monolithic/ stay out.
t/install-grub-arm64-modules.bats drives the script with apt-get, dpkg-deb and
the image builder as shell functions. Four removals were each caught by the
assertion that names them: the version gate, the file-only copy, the apt
authentication options, and the missing-module-directory check.
Measured in an ubuntu:24.04 container with the workflow's own steps:
t/aarch64_target.t reports 4 skips before the step and 0 after it, with all 38
checks passing, and t/aarch64_cross_build.t passes 27 with 0 skips.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
t/aarch64_target.t was added with the aarch64 build target and no workflow step
ran it. Adding the step alone is not enough: the four checks that run the spec's
own grub2-mkimage command skip unless the arm64-efi grub modules are installed
and the tool is on PATH, and both were missing on the runner.
Debian and Ubuntu name the tool grub-mkimage, so looking only for the EL name
skips exactly where the suite runs. The test now resolves either name and
substitutes it into the spec's command.
grub-efi-arm64-bin is Architecture: arm64 and cannot be installed on the amd64
runner, but the modules in it are target code, so the workflow extracts the deb
from ports.ubuntu.com instead of enabling a foreign architecture, and fails when
the extraction yields no modules.
Measured in an ubuntu:24.04 container with the workflow's own steps: the
upstream test reports 4 skips, `# skip grub2-mkimage or the arm64-efi grub
modules are not installed`, and this one reports 0 with all four image checks
passing. The workflow also runs t/aarch64_cross_build.t.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
mock_chroot_uid reads the configuration files itself and processes each
include() after the file that names it. A configuration that includes a file
with chrootuid 1000 and then sets chrootuid 1001 returns 1000, but mock builds
as 1001. mockbuild-perl-packages.pl then gives the result directories to the
wrong uid, and mock cannot write its logs in them.
native/mock-chroot-uid.t compares mock_chroot_uid with that case, with a
wrapper that only includes, and with a configuration that sets no chrootuid.
Ubuntu ships no mock, so the workflow runs the test in a Fedora container.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
mockbuild-all.pl builds a perl package with mockbuild-perl-packages.pl when the
native catalog declares it an owner. That script runs as root and creates the
directories it gives mock as --resultdir. mock 6.8 reloads its uid manager from
chrootuid and opens state.log, build.log and root.log in --resultdir as that
uid, so each directory must be writable by it. No test reads the owner or the
mode of those directories.
The test checks the uid read from a mock configuration, then writes a state.log
in each result directory as that uid. The write runs in a forked child that
exits 2 when setuid fails, so a write made as root cannot read as a pass.
The result-directory checks need root, so the workflow runs the file under sudo.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
Every openEuler ppc64le native prerequisite after procenv itself fails before
rpmbuild starts:
FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/procenv'
raised from mock's procenv plugin prebuild hook. The plugin runs ["/usr/bin/procenv"]
through mockbuild.util.do with no chroot prefix, so it executes the BUILD HOST's copy,
and xcat-master-ppc has none. The plugin also appends procenv to the buildroot's
preexisting_deps itself, so the chroot already gets the package: a run that installed
it, with "Installing : procenv-0.60-1.ppc64le" in root.log, failed on the same line.
mock ships procenv_enable False. The overlays turn it on, which makes every native
build depend on a host package that neither repository declares, for a procenv.log
that nothing reads.
The overlay text was built inline in native_overlay, so there was nothing a unit test
could call. native_overlay_text in XCAT::NativeInputs now renders one overlay and
reproduces today's values exactly, and native_overlay writes what it returns.
openeuler_native_procenv_plugin.t asserts the plugin is left at its default in all
three overlays, that the prerequisite repository and the bind mount survive, and that
the uid split does not move. Two of its eleven checks fail on this commit, which is
the defect.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
ipxe-xcat/mockbuild.pl runs as root and calls make_path on $work_dir/srpm
and $work_dir/rpm, then gives each one to mock as --resultdir. The native
openEuler overlay sets chrootuid to the catalog's build_uid and chrootgid to
the native build gid, so mock reloads to that uid and opens state.log,
build.log and root.log in those directories. A root-made directory with the
default umask is root root 0755 and mock cannot write them. grub2-xcat,
ipmitool-xcat, syslinux-xcat and goconserver create their result directories
the same way.
What keeps those directories writable is the step wrapper, not the builder:
native_owner_command gives the step the native build gid and umask 0002, so
every directory the builder creates below it is group writable. No test
measured that, so removing either one is silent.
Move native_owner_command into MockBuildUtils so a test can call it in
process, and assert the wrapper carries setpriv --regid 1000,
--clear-groups and umask 0002, that setpriv precedes the umask and the umask
precedes the builder, and that the overlay is still bound over the target
config so chrootuid stays as the catalog declared it.
This commit is the move and the test only. Five of the six assertions fail
here, because the gid and the umask arrive in the next commit.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
An air-gapped EL service node reads BaseOS, AppStream, xcat-core and
xcat-dep, and no other repository. Nothing checked that xCATsn resolves
from that set, so a dependency that only CRB or EPEL carries was found on
the service node.
verify-xcatsn-install.sh runs dnf --installroot into an empty directory
with only those four local repositories. It disables every configured
repository, refuses a URL as input, and fails when dnf loads a repository
that is not file://. Package signatures are checked against the keys given
with -k. The installroot is removed on exit.
t/verify-xcatsn-install.bats tests the argument handling, the local
repository guard and the cleanup with dnf and rpm stubbed.
package-tests runs it.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
openeuler-20.03sp4-x86_64 and openeuler-22.03sp4-x86_64 build nothing. Both exit 3
at "Could not find included config file:
/etc/mock/templates/openeuler-20.03-sp4.tpl", and both targets report that every
build step failed. mock-core-configs names its openEuler templates by release
alone, openeuler-20.03.tpl and openeuler-22.03.tpl, and each already sets
releasever to the newest service pack. The two configurations spelled the service
pack into the template name, which matches no file in any mock package.
openeuler-24.03sp4-x86_64.cfg already includes openeuler-24.03.tpl, which is why
that target builds.
The ppc64le target fails before any package is built, for two further reasons.
rpmkeys --dbpath cannot import the publisher key: rpm takes an fcntl transaction
lock on <dbpath>/.rpm.lock, the staging directory is NFS mounted local_lock=none,
and that lock answers errno 524 there. The keyring database moves to local
temporary storage, keyed on the staging directory so two targets of one run do not
share it. The staged source RPMs and the gpg home do not move.
A verified publisher RPM is rejected as unreadable: reject_elf_payload read the
exit status of rpm2cpio as the verdict on the payload, and on rpm 4.19 rpm2cpio
writes the whole payload and still exits 1 with nothing on stderr. The cpio walk
moves into scan_cpio_for_elf, which returns its own answer. A truncated stream
never reaches the trailer and still dies, which is the case the exit status stood
in for, and verify_input has already matched the sha256 and run rpmkeys --checksig
before this point.
Each fix has a test that fails without it. openeuler_mock_template_include.t reads
the configurations only. openeuler_native_trust_dbpath.t and
openeuler_native_cpio_scan.t run no rpmkeys and no rpm2cpio: the second builds its
cpio streams in Perl and refuses an ELF member, a truncated stream, data after the
trailer and a stream that is not cpio, each by name.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The per-arch runs of one dep build share --repo-dep and each took
<repo-dep>/.lock. The first run won and the others died, so the
pipeline passed --force-unlock. That option removed any lock it found:
a rerun of the same refs could take a cell from a run still writing it,
and common recovery could remove the staging tree of a live publisher.
mockbuild-all.pl now takes XCAT::NFSLock locks: <output>/.lock, one
<repo-dep>/rh<N>/.<arch>.lock per target, and .common-publish.lock while
it recovers or publishes common. --finalize-xcat-dep locks the cells it
rewrites. --try-unlock-timeout N replaces --force-unlock. A run that is
not a dry run recovers an interrupted common publication when no other
run holds the common lock.
sbuild-all.pl takes its per-arch run lock and its apt publish lock as
XCAT::NFSLock locks instead of flock, which fails on the shared tree.
createrepo_c runs without --database. SQLite needs locks, which a client
of an NFS re-export cannot take.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
t/openeuler.t and five of the six native/ tests are never run by the
workflow, so the openEuler build targets, repository layout and
package signing they cover are untested on every pull request.
Run t/openeuler.t with the other package tests. Add a step that
relaxes the AppArmor restriction on unprivileged user namespaces,
installs rpm2cpio and cpio, and runs the five native tests that need
only the RPM tools. A native file that skips fails the step, because a
missing tool would otherwise pass silently. native/mock-configs.t
needs Fedora's Mock library and is left out.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The ddns plugin builds its update key with Net::DNS::RR->new(... IN KEY
...). The Net::DNS 0.80 that xcat-dep builds for riscv64 has no KEY
record, so the call dies and makedns returns non-zero.
t/net_dns_rr_types.t loads Net::DNS from the shipped tarball and builds
the KEY records that xCAT builds. It also requires the manifest pin to
be an exact version at 1.01 or newer. The package-tests workflow runs
the test.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The riscv64 goconserver build never finished. It installs a Go toolchain built FOR the
chroot architecture, so on riscv64 the compiler itself runs under qemu-user: three
xcat-dep-ubuntu-cd cells (jammy, noble, resolute) each burned the full 9000s budget, two
of them with no CPU ticks at all in the stall sample.
Nothing asserted which toolchain the build fetches, or which architecture it compiles for.
This test lifts the build shell out of goconserver/sbuild.pl and runs it with the commands
it calls shadowed, then asserts on what the run asked for: the toolchain tarball must name
the build host, and the real debian/rules must reach `go build` with GOARCH set to the
chroot architecture. The recorders refuse any write outside the scratch tree and report it,
so the build's `rm -rf /usr/local/go` is an assertion here rather than damage to the host.
It fails on the current builder: the toolchain is fetched for riscv64, GOARCH is unset and
two writes escape the build tree.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
master added the common repository gate to the workflow and rewrote the
riscv64 comment of packages-manifest.conf after this branch started.
The workflow keeps both new prove lines. The two tests are unrelated.
The riscv64 comment takes master's text. This branch said the x86 boot
components are not built for riscv64; master then listed elilo-xcat,
syslinux-xcat and xnba-undi in the cell, because a riscv64 management
node serves the x86 nodes of a mixed cluster, so the branch sentence is
no longer true. The last line keeps this branch's statement: the perl
set is the EL10 one plus perl-HTML-Form. The pin itself merged without
a conflict, and t/riscv64_perl_cell.t passes on the merged cell.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
master added the per-cell architecture rule (rpm_arch, rpm_in_cell) after
this branch started, so the two sides collide in three places.
The MockBuildUtils and t/mockbuild-all.t import lists take both sets of
names. Neither side removes a name the other needs.
MockBuildUtils.pm now held two definitions of rpm_arch, one from each
side, and Perl kept the later one. master's definition stands: it reads
the header of a file and falls back to the name suffix otherwise, which
is what its own tests and rpm_in_cell need. The branch definition is
removed. carry_over_rpms takes rpm_arch as an argument, so it keeps its
own architecture gate and its own message.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
t/mockbuild-all.t covers the manifest gate and the skip-run carry-over and
was not in the package test job. Its rpm fixtures skip where rpmbuild is
absent.
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
A riscv64 goconserver `go build` sat 26 minutes with zero CPU ticks across a
20-second sample, both Go pids in futex_wait and no socket open. Nothing bounds
a build step, so the cell did not fail -- it hung, and a hung run reads as
"still running" rather than as a defect.
t/build_timeout.t drives the bounded path with a command that hangs and asserts
that the call returns, reports a timeout, and prints the process tree, each
pid's wchan, the open socket count and a CPU-tick sample. A second case drives a
spinning command and asserts the report calls it slow, not deadlocked, so the
sample means something.
Each call under test runs in a forked child whose stdio is detached to a file,
and the parent bounds that child. An unbounded run must fail this test, not
block prove.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
PR #64 landed on master and added --genesis-release to build-apt-repo.sh -- the
very script this branch deletes, having absorbed the apt assembly + signing phase
into sbuild-all.pl. A plain merge would either resurrect the shell publisher or
silently drop the OpenEmbedded Genesis release from every apt suite, so the
feature is ported to where apt publication now lives.
sbuild-all.pl --genesis-release <dir>:
- The release is validated once at startup, before any build or publish, with the
same checksum-verify-checksum sequence mockbuild-all.pl uses on the rpm side, so
a release rewritten together with its SHA256SUMS while the verifier runs is
rejected. It must be complete (every supported architecture) and carry debs.
- During assemble_into, each release deb is copied into the codename's pool and the
flat per-version directory and re-checked against the verified checksums. That
happens with the publish lock held, between the pool wipe and apt-ftparchive, so
the bytes that are indexed and signed are the bytes that were verified -- the
separate re-verification pass build-apt-repo.sh ran before indexing has no
window left to cover here.
- Copies are plain copies, never link(): a pool file sharing an inode with the
release would let a write through either path change what the other holds.
- Anything staged under the OpenEmbedded Genesis package name is dropped when the
option is given; the verified release is the only source of those packages.
- XCAT::GenesisRelease is loaded on demand rather than imported at compile time. It
pulls in XCAT::BuildUtils, which needs File::Slurper, and xcat-master-ub does not
carry it: a compile-time import made every apt build -- including the ones that
never pass --genesis-release -- die with "Can't locate File/Slurper.pm".
Also here:
- --publish-lock-wait <seconds> makes the 1800s publish-lock wait settable, so a
caller that would rather fail fast than queue can, and so the lock is testable.
- t/genesis_openembedded_consumer.t: the four APT consumer tests now drive
sbuild-all.pl's real publish path (staging tree, publish lock, atomic swap)
instead of build-apt-repo.sh, including the new flock-based lock behaviour.
- The workflow compiles sbuild-all.pl and BuildUtils.pm instead of shellchecking
the removed script; BUILD.md and genesis-openembedded/README.md document the apt
invocation.
Full suite green on both build hosts: 345 tests on xcat-master-ub (Ubuntu 24.04,
where the APT and RPM consumer tests actually run) and 341 on xcat-master.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>