2
0
mirror of https://github.com/xcat2/xcat-dep.git synced 2026-09-30 23:05:17 +00:00
Commit Graph

140 Commits

Author SHA1 Message Date
Daniel Hilst 56631f8f36 test(xcat-dep): publish and finalize take locks of cells they do not own
The apt publish reads staging/<codename>/<arch> of every expected arch,
but takes only the run lock of the host arch. A ppc64el run can refill
its staging while the publish assembles from it.

Finalize runs on one host and takes the cell locks of both arches. If it
dies, only that host can reclaim the locks of the other arch's cells,
and the builds that own those cells wait on them and fail.

These tests fail until the fix: the publish must refuse while any
expected arch holds its run lock, and finalize --finalize-arch must
write and lock only the cells of that arch.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-28 11:28:47 -03:00
Daniel Hilst f23a4e8786 fix(xcat-dep): lock takeover relies on rename and on lock.break
XCAT::NFSLock recovered a dead owner's lock under a second lock,
lock.break. A process that died after it created lock.break left it in
place, and every later acquire timed out even when both processes were
dead. The lock and its record were also put in place with rename, which
replaces an empty directory, so acquire took over a lock.d that had no
owner record.

The lock now follows the NFS lock protocol at the top of NFSLock.pm. It
uses mkdir, rmdir, unlink and plain writes, and no rename. lock.d/metadata
holds the owner identity and a hash, and invalid metadata only causes a
retry. Takeover and release both hold lock.borrow, beside lock.d. Only a
process on the owner's machine takes over a lock, after it reads the
same identity twice and proves that owner dead. acquire retries R times
with a wait of T +/- jitter, and --try-unlock-timeout maps to R.

Records written by the previous format are invalid metadata and are not
taken over. A process that dies while it holds lock.borrow still blocks
the lock. The protocol assumes that this does not happen.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-28 10:06:35 -03:00
Daniel Hilst bd7312690d Merge master into fix/repo-lock-force-unlock-race
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-28 08:41:19 -03:00
Vinícius Ferrão a35bb1037b test(ipxe-xcat): check the payload with the shims in place
payload.sha256 differs from the bare release tree in the two shims, and
matches the tree once the committed ipxe/shim shims replace them, as the
builders install them. SHA256SUMS covers the shims with the archives.
2026-09-27 12:01:46 -03:00
Vinícius Ferrão 0ff70ab9a6 test(ipxe-xcat): stop comparing the payload with the bare release tree
The next commit installs the ipxe/shim 16.1 shims over the shims of the
release tree, so payload.sha256 no longer describes the bare tree. The
commit after it checks the tree with the shims in place.
2026-09-27 12:01:19 -03:00
Daniel Hilst 429c573626 fix(xcat-dep): per-arch dep builds share one repository lock
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>
2026-09-26 08:39:49 -03:00
Daniel Hilst e2bc5493de feat(xcat-dep): add XCAT::NFSLock, a lock for the shared NFS tree
The dep builds lock trees on a shared NFS tree that the hypervisors
re-export. The kernel refuses flock and fcntl locks to clients of a
re-export, so every such lock fails with errno 524.

XCAT::NFSLock builds a lock as a directory under a private name, with an
owner record and the caller's metadata, and renames it into place. The
record holds the machine id, boot id, pid, process start time and a
random token. The owner removes the lock, or a process on the owner's
host that proves the owner dead: another boot, no such pid, or a pid
with another start time. That process takes a breaker lock and proves
the owner dead again before it removes the lock. Removal renames the
lock away first. Any other acquire waits up to a timeout, retrying every
3 s by default, then fails with the mv command that moves the lock away.
A lock left by mockbuild-all.pl before this module is taken when its
pid is gone on this host.

t/nfslock.t covers each rule without NFS.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-26 08:39:49 -03:00
Vinícius Ferrão 35ffbd5c21 test(xcat-dep): expect ipxe-xcat with the x86 boot loaders
Require ipxe-xcat in every EL target that lists xnba-undi, at the same pin
on riscv64 as on ppc64le, and on every Debian target. Hold its Debian pin
to its changelog, and check that its control file keeps it an
Architecture: all package built on amd64 only.
2026-09-25 13:15:50 -03:00
Vinícius Ferrão 6d37819cec test(ipxe-xcat): cover the payload check
Damage a copy of a fixture tree one way at a time: a changed byte, a
missing file, an extra file or directory, a symlink with another target,
and a symlink replaced by a copy of its target. Each must fail the check
and name the path. Also hold the committed payload.sha256 and SHA256SUMS
to the committed archives.
2026-09-25 13:15:50 -03:00
Vinícius Ferrão 0ba9df8dc8 test(xcat-dep): cover the shared mock config resolver
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.
2026-09-25 02:25:44 -03:00
Daniel Hilst 329856a6cd Merge pull request #76 from VersatusHPC/fix/riscv64-goconserver-cross-build
fix(xcat-dep): the riscv64 goconserver build deadlocks running the Go compiler under emulation
2026-09-24 15:26:00 -03:00
Daniel Hilst 8e2fbbf277 test(goconserver): cover the Go toolchain the Ubuntu build installs
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>
2026-09-15 07:09:48 -03:00
Daniel Hilst f4d453dd46 test(xcat-dep): a bail-out in one test file stops the whole suite
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>
2026-09-14 08:38:12 -03:00
Daniel Hilst eae2147a8c fix(xcat-dep): the Ubuntu Genesis image is converted from the EL rpm
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>
2026-09-12 08:50:48 -03:00
Daniel Hilst b38df7e63e test(xcat-dep): the Ubuntu Genesis image is converted from the EL rpm
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>
2026-09-12 08:47:57 -03:00
Daniel Hilst fc5c6d0375 Merge pull request #71 from VersatusHPC/fix/mockbuild-skip-perl-gate
fix(mockbuild-all): keep the published rpms of a skipped builder
2026-09-11 19:20:49 -03:00
Daniel Hilst 5ebc570288 Merge branch 'master' of xcat2/xcat-dep into fix/riscv64-perl-html-form
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>
2026-09-11 19:15:33 -03:00
Daniel Hilst 1d95b31285 Merge branch 'master' of xcat2/xcat-dep into fix/mockbuild-skip-perl-gate
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>
2026-09-11 19:13:42 -03:00
Daniel Hilst 201a6b1a6d Merge pull request #70 from VersatusHPC/fix/riscv64-deb-loaders
fix(xcat-dep): carry the x86 boot loaders in the riscv64 repositories
2026-09-11 18:57:58 -03:00
Daniel Hilst acb7311d0b Merge pull request #68 from VersatusHPC/feat/genesis-s390x
feat(genesis): package s390x images
2026-09-11 18:52:19 -03:00
Vinícius Ferrão 5ee949cc9a test(mockbuild-all): cover the skipped package carry-over
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>
2026-09-10 01:12:20 -03:00
Vinícius Ferrão a17df594c9 test(mockbuild-all): cover the per-cell rpm architecture rule 2026-09-08 17:19:40 -03:00
Vinícius Ferrão 76ec6e081a test(mockbuild-all): pin the riscv64 boot loaders to the ppc64le pins
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.
2026-09-08 17:19:40 -03:00
Vinícius Ferrão aef1d117d5 test(xcat-dep): require the boot loaders on the riscv64 deb sections
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.
2026-09-08 16:39:20 -03:00
Vinícius Ferrão ad97129dd5 test(xcat-dep): hold the riscv64 cell to the builder's package set
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.
2026-09-07 02:54:11 -03:00
Vinícius Ferrão 5ed8fd5799 test(xcat-dep): capture a descendant outliving its killed leader
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.
2026-09-06 15:55:23 -03:00
Vinícius Ferrão afffcf39c9 test(xcat-dep): pin the exit status of a signalled child
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.
2026-09-06 15:39:04 -03:00
Vinícius Ferrão 043a7f6039 test(genesis): correct packager skip counts 2026-09-06 11:43:10 -03:00
Vinícius Ferrão 55a9a6968e test(genesis): cover early manifest rejection 2026-09-06 11:30:42 -03:00
Vinícius Ferrão 09e068419b test(genesis): cover release capability ordering 2026-09-06 11:15:33 -03:00
Vinícius Ferrão c8def3dc02 test(genesis): cover release compatibility 2026-09-06 10:54:29 -03:00
Vinícius Ferrão 412b556449 test(xcat-dep): capture a signal delivered inside the critical section
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.
2026-09-06 03:21:53 -03:00
Vinícius Ferrão 04a2b677cb test(xcat-dep): follow the debs through the private build directory
The stub session now leaves its deb where a real one would, so the assertions
read what reaches the result directory: nothing until the smoke passes.
2026-09-06 03:21:53 -03:00
Vinícius Ferrão 0c99bc8e51 test(xcat-dep): pin the signal mask around a bounded build
The race itself is not reproducible without a hook in the production path, so
the assertions pin the invariants the fix establishes: the build starts with the
handled signals unblocked, and the caller keeps them unblocked afterwards.
2026-09-06 02:44:58 -03:00
Vinícius Ferrão 796f7c174b test(xcat-dep): capture a rejected deb left in staging
Both assertions fail against the previous build_deb_in_chroot, which left the
deb in the result directory after the smoke rejected it.
2026-09-06 02:44:58 -03:00
Vinícius Ferrão 3c6ec97417 test(xcat-dep): capture workers surviving a signalled orchestrator
Two real processes stand in for a worker and the build it runs. The probe fails
when the handler forwards to nobody, which is what the orchestrators did.
2026-09-06 01:52:17 -03:00
Vinícius Ferrão 3223963af2 test(xcat-dep): capture an unbounded build outliving its orchestrator
The probe fails against the previous helper, where terminating the wrapper
left the build running.
2026-09-06 01:52:17 -03:00
Vinícius Ferrão 8961ce1441 test(xcat-dep): capture a cross-built deb whose binary never runs
Six of the assertions fail against the previous build_deb_in_chroot, which
accepted a smoke argument it never acted on: a wrong version, a binary that
exits non-zero, and a smoke naming a deb the build never produced all passed.
2026-09-06 00:33:47 -03:00
Vinícius Ferrão 5651e75875 test(xcat-dep): capture --install-deps skipping the emulation packages
The two assertions fail against the previous package list and pass with it,
so a later edit cannot drop the binfmt handler that a foreign chroot needs.
2026-09-06 00:26:59 -03:00
Vinícius Ferrão 3c137bd133 test(xcat-dep): capture a cancelled build outliving its orchestrator
The command records its own pid and sleeps well inside the budget, so the
bound cannot be what ends it; the wrapper is then terminated and the pid
probed. Without the forwarding the build survives.
2026-09-06 00:24:13 -03:00
Vinícius Ferrão 66af6b368f test(xcat-dep): capture a foreign build with no binfmt handler
Drives the check extracted from sbuild-all.pl with the handler node
redirected into a temporary tree, covering the native case, a foreign
target with no handler, and the same target once one is registered.
2026-09-06 00:24:12 -03:00
Vinícius Ferrão e6ee2f9d4a test(xcat-dep): capture the riscv64 build demanding a Genesis deb
Drives the manifest lookup extracted from sbuild-all.pl for a target that
names the legacy Genesis deb and one that does not.
2026-09-06 00:24:12 -03:00
Vinícius Ferrão 4b29ad5db5 test(xcat-dep): capture the staged riscv64 tree being dropped
Drives the scan extracted from sbuild-all.pl against a staged tree holding
every supported architecture plus an unsupported one, so the assertions
read the set publish would carry forward rather than a copy of the rule.
2026-09-06 00:24:12 -03:00
Daniel Hilst b4034cd01c test(xcat-dep): a build that deadlocks under emulation hangs the pipeline
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>
2026-09-05 16:42:42 -03:00
Daniel Hilst 67ab6f1fad test(xcat-dep): capture a manifest pin drifting from its changelog
The Ubuntu build fails at the end, after compiling every package:

  FATAL: manifest validation failed:
    [noble-amd64] grub2-xcat: built 2.12-2, manifest pins 2.12-1

debs-manifest.conf pins the exact deb version each package must produce, and that
version comes from the package's own debian/changelog. Bumping the changelog
without the pin costs a whole build to discover a one-line edit.

The test compares every non-glob pin with the first line of that package's
debian/changelog. Globbed pins are deliberate -- goconserver's revision is the CD
stamp and xcat-genesis-base is not versioned by xcat-dep -- and are skipped. It
fails on grub2-xcat today.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-05 16:42:41 -03:00
Daniel Hilst 341f4650ab fix(xcat-dep): the new control-file test ran after done_testing
The architecture-coverage block was appended at the end of t/sbuild-all.t, past
done_testing. Test::More had already declared the plan, so the run ended with
"planned 194 tests but ran 197" and the three assertions counted for nothing.

Move the block above done_testing.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-05 16:42:41 -03:00
Daniel Hilst 19c8d72340 test(xcat-dep): capture debian/control excluding an architecture
ipmitool-xcat fails to build on riscv64:

  dh: warning: No packages to build. Possible architecture mismatch:
      riscv64, want: i386 amd64 ia64 ppc64el
  make: ./configure: No such file or directory

Its debian/control names architectures explicitly, and riscv64 is not in the
list, so debhelper builds nothing and the build dies at configure. conserver and
goconserver say Architecture: any and are unaffected.

The test reads each compiled dep's debian/control and asserts that an explicit
architecture list covers every arch BuildUtils::supported_arches names. It fails
on ipmitool today.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-05 16:42:41 -03:00
Vinícius Ferrão c1aaba4cd4 test(genesis): cover publisher compatibility gates 2026-09-04 18:02:03 -03:00
Vinícius Ferrão f522398456 test(genesis): cover repository downgrades 2026-09-04 17:15:24 -03:00
Vinícius Ferrão ed1b7661e2 test(genesis): update builder fixtures 2026-09-04 16:55:45 -03:00