ipxe-xcat installs the release tree under /tftpboot/xcat/ipxe as it
is, with its relative symlinks, and installs the source archive and the
licence texts with the documentation. It is a noarch RPM and an
Architecture: all deb.
Both builders check the archives against SHA256SUMS before the build.
After the build they unpack the RPM or deb and compare its tree with
payload.sha256, entry for entry, before the package reaches the result
directory. The spec and the Debian rules do not strip or compress the
tree, so the signed EFI files keep their signatures.
The package does not obsolete, provide or conflict with xnba-undi.
ipxeboot-2.0.0.tar.gz is the ipxeboot.tar.gz asset of the iPXE v2.0.0
release, renamed, with the SHA-256 that the release publishes.
ipxe-2.0.0-source.tar.gz is the source archive of tag v2.0.0 (commit
12798ec). The loaders xCAT uses are GPLv2+ as a whole, so their source
ships with them.
licenses/ holds the iPXE licences from v2.0.0 and the notices of the
signed shim: its COPYRIGHT from ipxe/shim ipxe-16.1, the OpenSSL
1.0.2k licence, and gnu-efi README.efilib at the commit that tag pins.
An AlmaLinux host resolves to the alma config file, an id that names its
file resolves to it, the os-release id wins when both files exist, and a
release with no config file is an error that names the files it tried.
mockbuild-all.pl finds the mock config by its file in /etc/mock, and
knows that /etc/os-release says almalinux where mock names the file
alma. Move that resolver into MockBuildUtils, with the config directory
as an optional argument, so a per-package builder can use it. The
behavior of mockbuild-all.pl does not change.
xcat-dep-ubuntu-cd build 83 failed in its riscv64 branch. The goconserver build for
jammy, noble and resolute each ran the full 9000s budget and produced no deb. The stall
report found the Go processes parked in futex_wait, two of the three cells with no CPU
ticks at all during the sample.
riscv64 has no build host, so its chroot runs on the amd64 agent under qemu-user.
goconserver/sbuild.pl installed the Go toolchain for the chroot architecture, so the
compiler itself ran emulated, and `go build` did not return. The EL builder already avoids
this: goconserver/mockbuild.pl cross-compiles for a forcearch target rather than running
the toolchain in the emulated chroot.
sbuild.pl now stamps the build host architecture into the build script and fetches the
toolchain for that architecture, then sets GOARCH to the chroot architecture. A Go
toolchain is statically linked, so the host one runs inside the foreign chroot, and
goconserver is CGO-free, so it cross-compiles. The toolchain also unpacks into the build
tree instead of overwriting /usr/local/go. A native cell is unchanged: host and target
agree, and GOARCH names the architecture it already used.
t/goconserver_cross_build.t covers this and fails without the change: the toolchain was
fetched for riscv64 and `go build` ran with GOARCH unset.
Measured on xcat-master-ub, jammy riscv64: 380s, against a 9000s budget the emulated
build exhausted. The deb carries statically linked RISC-V binaries that run under binfmt.
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>
Five files under t/ call BAIL_OUT at eleven places: a missing command, a
manifest section that is not there, an extraction that stopped matching,
a run_bounded that never returned. prove stops every remaining file on a
bail-out, not only the file that called it, so one of these hides the
results of every test that would have run after it. die is just as loud
and costs only its own file.
The header of genesis_native_deb.t also retold how an EL image reached an
Ubuntu node. The fallback and its effect are one sentence.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
convert_genesis_rpm extracted xCAT-genesis-base-<arch>.noarch.rpm with rpm2cpio
and repackaged it as a deb. That rpm carries an EL kernel and EL kernel modules,
so every Ubuntu management node installed an image built for another
distribution. The pipeline took that path on every run, because GENESIS_BASE_RPM
is what it passes.
xcat-core builds the deb natively now, one per Ubuntu codename. Drop
--genesis-rpm, --genesis-rpm-ppc, --require-ppc-genesis, convert_genesis_rpm,
maintained_genesis_control and genesis_deb_control, and --xcat-source with them:
the maintained control and the maintainer scripts come from the real
dpkg-buildpackage now, not from a hand-assembled DEBIAN/control.
The images differ per release, so build_genesis stages each one into the suite it
was built for. genesis_debs_for_codename reads the codename back from the deb
version, and a run that publishes a codename with no image for it stops instead
of serving another release's image.
genesis_native_deb.t fails without this change.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
sbuild-all.pl gets its Genesis deb one of two ways. --genesis-deb ingests a
native deb. --genesis-rpm and --genesis-rpm-ppc convert the EL rpm with rpm2cpio,
and that is the path the pipeline takes, so an Ubuntu management node installs an
image built from an EL kernel.
xcat-core now builds one Genesis deb per Ubuntu codename, each carrying that
release's kernel, with the codename in the version. build_genesis stages every
Genesis deb it holds into every suite, so three images would land in each one and
apt would serve the newest, which belongs to another release.
genesis_native_deb.t asserts the deb each suite takes, and that the three rpm
options are gone. It fails on this commit.
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>
skipped_builder must place a source package with the builder required_pkgs
would skip and never claim the OpenEmbedded Genesis. carry_over_rpms must
keep every binary rpm of a skipped build whose source package the target
manifest still names, leave out whole any build the run already carries a
member of, and
die on an unreadable header, an unsigned or foreign-architecture member of
a selected build, or a package published at two versions. Paths with
spaces are covered. Both fail to import against the previous module.
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
Each run collects the rpms it built into its run repository, and deploy
stages the cell from that repository and gates it on the whole manifest,
which a skip run cannot satisfy: with --skip-perl there are no perl
packages, the gate reports them missing, and the deploy fails after the
build succeeded. The gate is right to check the whole manifest, since the
flags describe what this invocation built and not what the cell may lack.
After collection, the run repository now takes the binary rpms a skipped
builder published in the cell: whole builds, so subpackages the manifest
does not name stay too; only builds whose source package the target
manifest still names, so a dropped package is not republished; and only
builds of which the run carries no member yet, so generations of one build
never mix. The bump check, createrepo, the tarball and the deploy gate
then see the same complete set. The carry-over stops the run rather than
publish a partial or doubtful set: an rpm in the cell whose header cannot
be read, apart from the OpenEmbedded Genesis family that is pruned by
name, a member of a selected build the signing key did not sign, by signer
id and by rpmkeys --checksig, or whose digests do not verify when no key
is configured, a member of another architecture than the cell or noarch,
or a package published at more than one version. A package that was never
published is still reported missing, and a full run is unchanged. The
zero-artifact check applies only when a builder ran, so a run that skips
both package builders reaches the deploy.
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
verify_rpms_checksig built the isolated keyring and ran rpmkeys on every
rpm in one body. The keyring setup and the per-rpm verdict are now their
own helpers, so another caller can verify a single rpm against the signing
key. The gate behaves as before.
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
A noarch builder of a forcearch target runs in the native chroot of the
release, but its cleanup step was registered against the target
configuration. The step scrubbed a chroot that did not exist and left the
native bootstrap behind on every run, one per noarch step.
Compute the configuration once per step and scrub the same one it built in.
collect_rpms copied every binary rpm a builder produced. The syslinux builder
also produces syslinux, syslinux-extlinux and their debug rpms for the chroot
it runs in, so a forcearch target that builds the noarch boot loaders in the
native x86_64 chroot would have published x86_64 rpms in the riscv64 cell.
The completeness gate checks names and pins only, so it would have passed.
Keep an rpm only when it is noarch or carries the cell's architecture, read
from the rpm header. The rule lives in MockBuildUtils as rpm_in_cell.
The riscv64 cell must carry elilo-xcat, grub2-xcat, syslinux-xcat and
xnba-undi at the pins of the EL10 ppc64le cell. 3 assertions fail against
the previous manifest.
The forcearch riscv64 profile built grub2-xcat but not elilo-xcat,
syslinux-xcat or xnba-undi, and the rocky-10-riscv64-xcat cell did not list
them, so a riscv64 management node could not serve the x86 nodes of a mixed
cluster, unlike a ppc64le one.
Add the three to the profile and the cell, at the pins the EL10 ppc64le cell
uses. They are noarch and are built in the native x86_64 chroot, like
grub2-xcat. syslinux-xcat is marked noarch in the builder table, as its spec
declares, so the forcearch target does not try it in the emulated chroot,
where its ExclusiveArch excludes it. The target is now cross-built on x86_64
only, which the mock config states: a native riscv64 host could not build
syslinux-xcat either.
The manifest consistency check covered the amd64 and ppc64el sections. It
now covers the riscv64 sections too, so the 4 boot components must be listed
there. 12 assertions fail against the previous manifest.
The riscv64 sections of debs-manifest.conf listed grub2-xcat only. A riscv64
management node serves the x86 nodes of a mixed cluster, so its repository
must carry syslinux-xcat, elilo-xcat and xnba-undi, as the ppc64el sections
already require.
List the three in every riscv64 section. They are Architecture: all, built
once on amd64 and assembled into every index, so the build phase is
unchanged and the publish gate now verifies the riscv64 index carries them.
The assertion fails against the previous manifest, naming perl-HTML-Form as
the package the cell lacked. It reads the set from the builder, so a package
added to the builder later fails here until the cell names it.
perl-xCAT hard-requires perl(HTML::Form). EPEL supplies it on x86_64 and
ppc64le, so the EL9 and EL10 cells omit it, and the riscv64 cell copied that
omission. There is no EPEL for riscv64 and Rocky 10 riscv64 carries no
perl-HTML-Form in BaseOS, AppStream, CRB or extras, so dnf install xCAT could
not resolve on a riscv64 management node.
--list-packages prints the set a run selects, after --epel-gap and --packages,
and exits before the root and mock checks. The riscv64 manifest cell has no
other repository behind it, so a test can now hold the cell to this list
without a build host.
The probe starts a descendant, kills the leader with SIGKILL, and asserts the
descendant is gone when the call returns. It fails against the previous
run_bounded, where the descendant survived.
run_bounded signalled the process group on a timeout and on a cancellation, but
not when the leader itself died. A SIGKILL, or the OOM killer, takes the shell
and leaves schroot and qemu in the group, holding the chroot and writing into
staging after the call reports the build finished.
Those processes are not children of this one, so there is nothing to wait for.
Signal the group on the way out.
The assertions cover a normal exit, the highest exit code, and death by TERM,
KILL and a core-dumping signal. run_bounded is driven through the same helper,
so the decoding and its caller cannot disagree.
A child killed by a signal leaves 0 in the high byte of its wait status. The
per-codename worker loop read only that byte, so a cancelled or OOM-killed
codename was counted as built, and the run could reach validation with the
staging tree that worker never finished.
One helper decodes a wait status for both the worker loop and run_bounded, and
reports 128 plus the signal for a child the kernel killed.
ForkManager records a worker in run_on_start, which runs after the fork, so a
signal arriving in between reached a handler that did not know the worker. Both
worker pools now hold INT, TERM and HUP across start() and release them once the
parent has the pid.
The wait for a free slot happens before the mask is taken, or a cancellation
would stay pending for as long as the pool is full. With a single worker
ForkManager does not fork at all, so only a real child drops the inherited
forwarder, whose copy names siblings the parent already signals.
The probe sends itself a signal while the mask is held and asserts it arrives
only once the mask is restored, which is what makes the fork and the pid
registration a single uninterruptible step.