Conversation
A riscv64 build of xcat-core fails at xCAT-genesis-scripts:
ERROR: Cannot find/open srpm: dist/rocky-10-riscv64-xcat/rpms/SRPMS/
xCAT-genesis-scripts-riscv64-2.19.0-snap202609020458.src.rpm
The srpm on disk is named xCAT-genesis-scripts-%{tarch}-2.19.0-....src.rpm.
xCAT-genesis-scripts.spec and xCAT-genesis-base.spec take the package name from
%{tarch}, which an %ifarch ladder sets. That ladder has no riscv64 branch, so
%{tarch} stays literal and rpm builds a package with a macro in its name.
The test expands both specs with rpmspec for every arch xCAT supports and
asserts the Name carries that arch. It fails on riscv64 for both specs.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit 07a0e79)
… stays literal
A riscv64 build of xcat-core dies at xCAT-genesis-scripts with "Cannot find/open
srpm: ...xCAT-genesis-scripts-riscv64-2.19.0-<release>.src.rpm", because the srpm
rpm produced is named xCAT-genesis-scripts-%{tarch}-2.19.0-<release>.src.rpm.
xCAT-genesis-scripts.spec and xCAT-genesis-base.spec take their package name from
%{tarch}, which an %ifarch ladder sets for x86, x86_64, ppc64 and aarch64. riscv64
is absent, so rpm leaves the macro unexpanded and builds a package whose NAME
contains it. buildrpms.pl then looks for the name it asked for and cannot find it.
Add the riscv64 branch to both specs. An arch that is still missing from the
ladder now stops the build with %{error:} instead of naming a package after a
macro.
xCAT-test/unit/genesis_spec_target_arch.t covers this: it fails on riscv64
without this change.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit c9de89c)
Installing xCAT on a riscv64 Ubuntu management node fails before it starts: E: Unable to locate package xcat E: Unable to locate package xcat-test xCAT/debian/control and xCATsn/debian/control name their architectures explicitly, as "amd64 ppc64el". riscv64 is absent, so no riscv64 deb is ever produced and apt has nothing to install -- while the rest of the tree already carries riscv64 install templates, DHCP boot policy, mknb support and a Genesis machine configuration. The test reads both control files and asserts the explicit list covers every Debian architecture xCAT ships. It fails on both files today. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 059c234)
apt on a riscv64 Ubuntu management node cannot find xCAT at all: E: Unable to locate package xcat xCAT/debian/control and xCATsn/debian/control list "Architecture: amd64 ppc64el", so the build produces no riscv64 deb and the published apt repository serves only those two architectures. Everything else riscv64 needs is already in the tree -- the rocky10/rhels10 riscv64 install templates, the grub2 boot policy, mknb, the OpenEmbedded Genesis machine -- and the xcat-dep riscv64 repository is built, signed and complete; only the core packages are missing. Add riscv64 to both lists. xCAT-test/unit/debian_control_arch_coverage.t covers this: it fails on both files without the change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 13492f5)
builddebs.pl replaced build-ubunturepo as the Ubuntu builder, and the arch support riscv64 has in build-ubunturepo did not come with it. The pipeline prefers builddebs.pl whenever the ref carries it, so on this branch the switch silently stops producing riscv64 debs: no xcat_*_riscv64.deb in the pool, and a published Release that says 'Architectures: amd64 ppc64el'. apt on a riscv64 management node then reports 'Unable to locate package xcat', which is the same failure build-ubunturepo was fixed for. builddebs.pl reads its architectures from BuildUtils, so unlike build-ubunturepo -- which hardcoded the pair in three places -- riscv64 goes in one: @DEB_ARCHES. xcat-genesis-scripts is the exception and needs its own rule. Its per-arch deb Depends on xcat-genesis-base-<arch>, and no riscv64 genesis-base deb exists, because riscv64 takes the OpenEmbedded Genesis image from the shared xcat-dep pool. Built for riscv64 it would be uninstallable, so deb_package_arches excludes it. build_utils.t covers both: removing riscv64 from @DEB_ARCHES fails four assertions, including the reprepro Architectures line, and removing the genesis-scripts exclusion fails its own. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 90f9156)
mknb stages the Genesis payload before building a netboot image, and those copies are the only point at which it learns that an installed Genesis image is unusable. The legacy branch runs two of them and keeps only the second exit status, so an unreadable root tree is invisible: mknb exits 0 having built an initramfs from nothing, and the node never boots with no error naming the cause. When the kernel copy is the one that fails, the message blames the root tree instead. Extract the staging decision as stage_genesis_payload, preserving today's behaviour exactly, so the outcome can be driven with an injected runner instead of a real Genesis tree. The test fails on this commit, 2 of 10: 'an unreadable root tree fails the step' and 'the failure names the kernel, not the root tree'. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 989deaa)
The legacy branch ran both copies and kept only the second exit status, so an unreadable Genesis root tree left mknb exiting 0 with an initramfs built from nothing -- the node then never boots and nothing names the cause. A failing kernel copy was reported as a failure of the root tree, because the message was chosen from a flag set before either copy ran. Return on the first failing copy, carrying the name of the file that could not be read. mknb_genesis_staging.t goes from 2 failures to green on this commit. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit d46ca3e)
…olving nodepurge/cases0 asserted that testnode1 and testnode2 no longer resolve by running 'ping' with no count and expecting a non-zero exit. When the name does not resolve the ping fails immediately, which is the passing path -- but when it DOES resolve, which is the regression the case exists to catch, the ping never returns. The cell stops there and is killed by the pipeline timeout, taking the whole run's JUnit with it, so the one case that finds a real defect is also the one that hides every other result. Bound both with -c 1 -w 2. The assertion is unchanged: a name that does not resolve, or resolves to something that does not answer, still exits non-zero. autotest_ping_bounded.t goes green on this commit. Closes xcat2#59. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 187daab)
A node with arch=riscv64 got an x86_64 libvirt domain from mkvm. The node took a DHCP lease, received the riscv64 GRUB binary that nodeset staged, and could not run it. The firmware fell through to the empty disk and stopped, so both flat provisioning cases of the riscv64 cell failed with a node that never installed. build_xmldesc and build_diskstruct in xCAT-server/lib/xcat/plugins/kvm.pm read the architecture from the hypervisor cpumodel. The arch of the node was never read while the domain XML was built, so on an x86_64 hypervisor every guest was an x86_64 guest, whatever the node said. guest_arch_profile now takes the arch of the node as well, and returns the domain type, the <os> arch and machine, the firmware and the device settings that follow from them. A riscv64 node becomes a qemu domain with the virt machine type and UEFI firmware. It drops the parts the riscv64 virt machine has no controller for, or that libvirt refuses there: the pae, acpi and apic features, the SeaBIOS serial option, the ich6 sound card, the USB tablet, and the ide disk and hd* optical drive. libvirt resolves the emulator and the UEFI firmware files itself. POWER and x86_64 domains do not change. kvm_guest_arch.t drives build_xmldesc and build_diskstruct in a scratch package, stubbing only the routines that reach libvirt or the xCAT database, and asserts the domain and the disks of each architecture. Ten of its twenty assertions fail without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 8d149c8)
dhilst
force-pushed
the
release/2.19-rc1
branch
from
September 4, 2026 15:20
8d149c8 to
349658d
Compare
builddebs.pl replaced build-ubunturepo, and both CD pipelines prefer it: the fallback to build-ubunturepo fires only for refs that predate builddebs.pl, and such a ref carries its own copy. Nothing on this branch runs the script, so its presence only invites edits that never reach a build. The developer guide said it was kept as a differential oracle until the CD pipelines moved over. They have. Remove the script, and record the removal in the build guide beside the buildcore.sh, makerpm and buildlocal.sh entries. xcat_probe_package_payload.t asserted the Debian staging by matching a `cp -f` line in build-ubunturepo. builddebs.pl stages the helpers through XCAT::BuildUtils::stage_probe_helpers, so the test now calls that function and checks the files it produced. Verified by making stage_probe_helpers skip a helper: the assertion fails. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
A node whose vmstorage is a libvirt storage pool (dir://, nfs:// or lvm://) got a <disk> element with no bus attribute. libvirt then chose the controller from the name of the device alone, so the disk of a riscv64 node worked only while its volume was named sd*. build_diskstruct in xCAT-server/lib/xcat/plugins/kvm.pm matched the pool entry, a hash reference, against /^vd/, /^hd/ and /^sd/. A reference in a match is its address as a string, so no branch ran and the bus was never set. The name of the device is in the device field of that entry. The three tests now read that field. The bus each one sets is the bus libvirt gives an hd*, sd* or vd* name, so no domain changes: a riscv64 node keeps the sd* name its volume has, and keeps the scsi controller the riscv64 virt machine provides. libvirt stores the domain built before this change with bus="scsi" on that disk, which is what the domain built after it states. kvm_diskstruct_bus.t drives build_diskstruct in a scratch package, with a stub storage pool in place of the one routine that reaches libvirt, and asserts the bus of an hd*, an sd* and a vd* volume. It also asserts that a riscv64 node keeps the sd* name of its volume. Four of its seven assertions fail without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The name of the volume of a node, and the bus of a file-backed disk, could come from a match made by a routine on the call path. A riscv64 node breaks on it: a leaked value that is neither scsi nor virtio gives the node an hd* volume, and the riscv64 virt machine has no IDE controller for that disk. createstorage and build_diskstruct in xCAT-server/lib/xcat/plugins/kvm.pm read the model of the disk out of the vmstorage value with s/=(.*)//, then read $1. The substitution is allowed to fail, because most vmstorage values state no model, and a failed match leaves $1 as the last successful capture. dohyp gives every node the storage model scsi before mkvm runs, and a captured value takes priority over it, so a leaked value can only replace the default that keeps a riscv64 node on sd*. The leak follows the call path, not the history of the process. Perl restores $1 when the block that set it ends, so a match made in a routine that has returned cannot reach createstorage; only a match still live in an enclosing block can, and a later successful match without a group empties $1 again. A long-running xcatd is not what makes this happen, and looking for one is a wrong turn. Both routines now read $1 only when their own substitution matches. A vmstorage value that states a model, and vmstoragemodel, name the volume as before. The default itself moves into default_storagemodel, which dohyp calls, so a test can hold it. It sat inline with a comment, and changing it to ide left every assertion passing. kvm_createstorage_model.t runs each node twice, once with a capture left live in the calling block, because a case that leaves $1 empty passes against the defect. Five of its eleven assertions fail without this change, and a sixth fails if the default changes. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
A failing case named one failed check and no result at all for the checks after it, although the commands of the case kept running. The first [Failed] line was read as the cause of the failure three times this week, and each time the real fault was a later check: a riscv64 cell reported a makedns check 160 lines before rpower could not start the domain. run_case in xCAT-test/xcattest used one variable, $failflag, for two facts: the result of the case, and the result of the check being reported. Every branch read $failflag to decide whether to print [Pass] or [Failed], so a check that ran after a failed one always read as failed. The guard "last if ($failflag)" at the top of the check loop hid that, and hid every later check with it. The result of a check is now $checkfail, set and read inside one iteration. A continue block carries it into $failflag, which keeps the result of the case. The guard and the per-branch "last" statements are gone, so each check reports what it found. The output ~~ branch no longer clears $failflag on a match, which without the guard would have turned a failed case into a passing one. xCAT-test/unit/xcattest_report_every_check.t runs the harness over a fixture case and asserts on the CHECK lines it writes. Without this change it reports two of four checks, and one of two failed checks. A case whose checks all pass logs the same text before and after: no truncation could happen while $failflag stayed 0. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
Three case files ship a check line the harness cannot use. pscp/cases0 asks for "$$CN: done" with no operator, and load_case drops a check whose content does not start with a word character, so the two lines go without a message and the case asserts less than it reads. rscan/cases0 writes a command as a check, and ngpfb/cases0 compares rc against a pattern, which no operator accepts, so both cases report "Unrecognized testcase syntax" and fail on every run. Each line is repaired to what the case around it says it means. pscp prints "<node>: done" for each node it copied, in xCAT-client/bin/pscp, so the two lines become "output=~$$CN: done". rscan runs its check against the definitions that "rscan -z -w" wrote, so "check:lsdef -l $$CN" becomes a cmd and keeps the two checks that follow it. rmhwconn is asked for output without "state=LINE UP", which is what the lshwconn checks in the same case assert the other way round. xCAT-test/unit/autotest_check_lines_are_understood.t reads every check line under xCAT-test/autotest/testcase and asserts the harness reports one result for each of them, and that none uses an operator it does not know. Without this change it names all five: two lines from ngpfb, one from rscan, and pscp reporting 37 results for the 39 check lines it ships. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…node boots a shell A compute node fetches the legacy Genesis kernel and initramfs, the kernel starts, and then nothing else happens: doxcat never runs, the node acquires no address, sshd refuses every connection and the node stays at status=powering-on. The five genesis test cases in xCAT-test/autotest/testcase/genesis have never passed. VersatusHPC/xcat-internal#78. Three holes in the image, each fatal on its own. dracut_105/el/xcat-cmdline.sh ends in `while :; do tmux attach-session -t doxcat || tmux new-session -s doxcat doxcat; done`, and the image carries no locale data, so tmux exits with "need UTF-8 locale" and the loop spins without ever reaching doxcat. module-setup.sh does not install /usr/libexec/openssh/sshd-session, which OpenSSH 9.8 and later exec for every connection and which EL9 now ships. xCAT-genesis-base.spec does not BuildRequire dhcp-client, so dhclient is absent from the build chroot; dracut_install reports the missing binary and returns, and the module install function keeps going, so the image ships without it. xcat-cmdline.sh now resolves xcat_console_mode() once and runs doxcat directly when the terminal multiplexer cannot start a session; the same shape replaces the screen loop on Ubuntu. module-setup.sh installs the OpenSSH session helpers and the C.utf8 locale where they exist. The spec BuildRequires dhcp-client on the releases that package it, and runs the new xCAT-genesis-builder/verify-genesis-payload over the extracted payload, which fails the build when sshd needs a helper the image lacks, when tmux has no UTF-8 locale, or when a binary the caller named is missing. The same runs exposed four defects in the test cases themselves. test.sh defined its synthetic node as ppc64le whatever the management node was, so nodeset could not find a genesis kernel on x86_64. genesistest.pl get_os() matched neither AlmaLinux nor Rocky and reported the OS as unsupported. The -g check read $? instead of check_genesis_file()'s return value, so it could never fail. And testxdsh() met "REMOTE HOST IDENTIFICATION HAS CHANGED" from the second boot on, because Genesis makes new host keys every boot and nothing dropped the stale known_hosts entry. test.sh now derives the node arch from uname and takes the tftp root from TFTPDIR, get_os() recognises the redhat family, report_genesis_files() carries the result to an exit status, and forget_host_keys() runs makeknownhosts -r before each probe. Tests: genesis_console_mode.t drives xcat_console_mode() with the multiplexer shadowed; genesis_payload_verification.t drives the verifier over payload trees carrying each hole; genesis_testcase_helpers.t drives get_os(), check_genesis_file(), report_genesis_files() and testxdsh(); genesis_incorrectmasterip_check.t runs test.sh against a scratch tftp root. Each fails on the parent commit. The verifier also reports all three holes against the released xCAT-genesis-base-x86_64-2.19.0-snap202609021858 payload. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit cb6021e) Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…ps it doxcat names dhclient at six call sites. AlmaLinux 10 and EPEL 10 package no ISC dhcp-client, so the legacy Genesis image for el10 carries no dhclient binary. A node that boots that image reports "dhclient: command not found" on its console and never acquires an address. The test lifts the client selection out of doxcat and runs it with the clients shadowed by stubs that record their own argv. doxcat cannot be sourced, so the routines are extracted and driven on their own. It also reads the spec and the dracut module, which decide what client reaches the image. It fails on the current source for nine reasons: doxcat carries no selection routine and no runner, it still starts command lines with dhclient and still chains into dhclient from the secondary NIC loop, the spec build-requires no client on the releases that drop the ISC one and does not check the payload for one, and the dracut module installs dhclient alone. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 5d2801f)
A compute node that boots the legacy Genesis image on el10 x86_64 never acquires an address. Its serial console reports "/usr/bin/doxcat: line 293: dhclient: command not found" and then "It seems to be taking a while to acquire an IPv4 address". The DHCP server side is sound: Kea leases the address and the node never asks for it. AlmaLinux 10 and EPEL 10 package no ISC dhcp-client. dracut_install reports a missing binary and returns, so module-setup.sh named dhclient, the build kept going and the image shipped without a client. doxcat then named dhclient at six call sites with no alternative. doxcat now chooses its client at run time. genesis_dhcp_command() returns the command line for one interface and one address family, and genesis_start_dhcp() runs it and reports when the image carries none. The ISC client keeps its command line where a release packages it, so el8 and el9 are unchanged. Where it is absent, dhcpcd stands in: AlmaLinux 10 baseos packages it at 236 KB, and it carries its own resolv.conf, hostname and ntp hooks, so it needs no dhclient-script. dhcpcd on a single interface exits when its 30 second timeout expires and de-configures the interface as it goes, so it is asked for -t 0 and -p. The dracut module installs whichever client the build root carries, together with the hooks dhcpcd runs on every lease. The spec build-requires dhcpcd from rhel 10 on, and verify-genesis-payload now requires usr/sbin/dhcpcd there, so an image that ships with no client fails the build instead of reaching a node. genesis_dhcp_client.t drives both routines with the clients shadowed by recording stubs. It fails on the parent commit, and deleting the dhcpcd branch turns five of its assertions red. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit b932999)
The nodeset_shell_incorrectmasterip case ran "nodeset testnode shell", the command failed with "/tftpboot/boot/grub2/grub2.x86_64 does not exits", and the case still passed. check_destiny in xCAT-test/autotest/testcase/genesis/test.sh discards the return value of runcmd and greps the boot configuration file, which grub2.pm writes before it stops on the missing boot loader. The sub-case asserts nothing. wait_for_boot in xCAT-test/autotest/testcase/genesis/genesistest.pl waits for nodelist.status "booted". A Genesis node reports its destiny with getdestiny and xcatd writes "shell", "configuring" or "booting" from it, never "booted". Every caller discards the return value, so each case rests on its xdsh probes alone. genesis_incorrectmasterip_check.t now runs the check with a nodeset that fails, and reads whether the grub2 boot loader for the node arch is present when nodeset runs. genesis_testcase_helpers.t drives the status wait with lsdef shadowed, and drives the shell case with every command it runs shadowed. genesis_payload_verification.t reads a payload without mktemp, which getdestiny needs to make its request file. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 3597760)
…nd a node that never booted The nodeset_shell_incorrectmasterip case passed while "nodeset testnode shell" failed with "/tftpboot/boot/grub2/grub2.x86_64 does not exits". The grub2 sub-case asserted nothing. Every genesis case reported "After 30 iterations node status: powering-on" and passed anyway. check_destiny in xCAT-test/autotest/testcase/genesis/test.sh discarded the return value of runcmd and read the boot configuration file, which grub2.pm writes before it stops on the missing boot loader. xCAT builds no grub2 boot loader for x86_64, so the file is absent on a correctly built management node. wait_for_boot in genesistest.pl waited for nodelist.status "booted"; a Genesis node reports its destiny with getdestiny and xcatd writes "shell", "configuring" or "booting" from it. Every caller discarded the return value. The node did not reach even those statuses, because getdestiny makes its request file with mktemp and the dracut module never installed it. check_destiny now returns the status of nodeset, and the grub2 check stages an empty grub2.<arch> when the management node has none and removes it after. wait_for_node_status takes the status the destiny implies and each caller fails when the node does not reach it; the shell case moved into run_nodeset_shell_test so its result can be read. clearenv no longer waits, because "rinstall <node> boot" boots a disk with no operating system and reports nothing. The dracut modules install mktemp and verify-genesis-payload requires it. Tests: genesis_incorrectmasterip_check.t runs the check with a failing nodeset and reads whether the boot loader is present when nodeset runs; genesis_testcase_helpers.t drives the status wait and the shell case; genesis_payload_verification.t reads a payload without mktemp. Each fails on the parent commit. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 8ecf0a8) The Release hunk of the original commit is dropped. buildrpms.pl writes Release from SOURCE_DATE_EPOCH at build time, so the committed snap stamp is build debris.
…rchitecture The ppc64el and riscv64 xcat debs depend on xcat-genesis-scripts-amd64, and xcat-genesis-scripts-ppc64 depends on xcat-genesis-base-ppc64, a package no repository publishes. Nothing reports either one: the amd64 scripts package is Architecture: all, so it installs on any architecture, and the broken ppc64 dependency is never reached because nothing pulls that package. Extend debian_control_arch_coverage.t. It now reads the Depends field of xCAT/debian/control and xCATsn/debian/control, applies each architecture restriction the way dpkg-gencontrol does, and asserts that the genesis scripts a given architecture receives are that architecture's own. It also asserts that xCAT-genesis-scripts/debian/control-<arch> builds xcat-genesis-scripts-<arch> and depends on xcat-genesis-base-<arch>. Eight of the eighteen assertions fail on this tree. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…ecture
A ppc64el or riscv64 management node installs the amd64 Genesis. xCAT and
xCATsn declare Architecture: amd64 ppc64el riscv64 and one unrestricted
Depends: xcat-genesis-scripts-amd64, so every architecture gets it. That
package is Architecture: all, so apt reports no error. It lays down
/opt/xcat/share/xcat/netboot/genesis/x86_64 and pulls the 128 MB
xcat-genesis-base-amd64, and the node receives no Genesis for its own
architecture. xcat-genesis-scripts-ppc64, the package that would carry it, is
uninstallable: it depends on xcat-genesis-base-ppc64, and builddeb-genesis-base
names the ppc64el base deb xcat-genesis-base-ppc64el.
xCAT/debian/control and xCATsn/debian/control now restrict the dependency by
architecture, the way xCAT.spec does with
%{?genesistarch:Requires: xCAT-genesis-scripts-%{genesistarch}}. amd64 gets
xcat-genesis-scripts-amd64, ppc64el gets xcat-genesis-scripts-ppc64el, and
riscv64 gets neither, because its Genesis is the OpenEmbedded image.
xCAT-genesis-scripts/debian/control-ppc64el builds xcat-genesis-scripts-ppc64el
and depends on xcat-genesis-base-ppc64el. It conflicts with and replaces the
old name, which shares the same files.
debian_control_arch_coverage.t asserts the genesis scripts an architecture
receives are that architecture's own, and that control-<arch> builds
xcat-genesis-scripts-<arch> against xcat-genesis-base-<arch>. Eight of its
assertions fail without this change.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…ry has go-xcat keeps one package list per packaging format. Its dpkg list names xcat-genesis-scripts-ppc64 and xcat-genesis-base-ppc64. The Debian architecture is ppc64el, so apt cannot find either package and both "go-xcat install" and "go-xcat uninstall" stop on ppc64el. The test evaluates the two arrays of go-xcat, one run per branch, and compares them with the packaging: the deb names against the Package and Depends fields of the xCAT-genesis-scripts control files, the rpm names against the Genesis target architectures of xCAT-genesis-base.spec. It fails on the four deb assertions today. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
On ppc64el "go-xcat install" and "go-xcat uninstall" stop with E: Unable to locate package xcat-genesis-scripts-ppc64 apt refuses the whole transaction, so no package of the list is installed or removed. The dpkg branch of GO_XCAT_INSTALL_LIST in xCAT-server/share/xcat/tools/go-xcat names xcat-genesis-scripts-ppc64 and xcat-genesis-base-ppc64. Those are rpm architecture names. GO_XCAT_UNINSTALL_LIST is derived from the same array, so both actions carry the wrong names. The Debian architecture is ppc64el. This change renames the two entries of the dpkg branch. The rpm branch keeps ppc64, which is the Genesis target architecture of the spec. go_xcat_genesis_package_names.t fails the four deb assertions without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
debuild-xcat-genesis-base maps only x86_64 to amd64. For the ppc64 rpm it leaves every name at ppc64, so it builds xcat-genesis-base-ppc64 and writes "Breaks: xcat-genesis-scripts-ppc64". The Debian architecture is ppc64el, and the packages xCAT-genesis-scripts builds for it are named ppc64el, so the Breaks names a package no repository publishes. This change replaces the single x86_64 test with an architecture map: x86_64 to amd64, ppc64 and ppc64le to ppc64el. The map now drives the source tree rename, the control and changelog rewrite, and the Breaks field. PACKAGE_ARCH keeps the rpm value, because the preinst removes the Genesis tree under that name. genesis_base_deb_arch.t drives the script with alien shadowed. It fails the three ppc64el assertions without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The legacy Genesis image built on el10 carries no openssl command. getcert waits for one
with no bound, so the node reports no destiny and never boots. Nothing in the build or in
the suite sees the hole.
genesis_base_spec_buildrequires.t reads the spec and requires an unconditional
BuildRequires on openssl, and requires that no %{_target_cpu} is read after
BuildArch: noarch, where rpm has already set it to noarch.
genesis_payload_verification.t drives verify-genesis-payload with a dracut module and a
payload, and requires every command the module installs at the top level of install() to be
present. A name installed under a condition is not required, and a module the verifier
reads no names from is a usage error.
genesis_getcert_missing_openssl.t runs getcert with a PATH that holds stubs and no openssl,
under a harness timeout. Ten assertions fail on this commit: getcert never stops, and the
verifier and the spec do not know about openssl.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
… never returns
A compute node that boots the legacy Genesis image built on el10 stops after
"Getting initial certificate --> <mn>:3001". /etc/xcat is empty, getdestiny never runs and
the node reports no destiny, so xcatd leaves nodelist.status at powering-on. On the node,
openssl reports "command not found" and the getcert process stays alive.
xCAT-genesis-base.spec never build-requires openssl. el8 and el9 hold /usr/bin/openssl in
the build root as a dependency of another package, and el10 does not, so dracut_install in
dracut_105/el/module-setup.sh installed nothing and reported nothing. getcert line 8 waits
for openssl with no bound, which turns the missing command into a wait instead of an error.
The spec now build-requires openssl on every release. verify-genesis-payload reads the
command names back from the dracut module with --commands-from and requires each one in the
payload, so the next name the build root does not supply fails the build. getcert reports a
missing openssl and stops, and bounds the wait for /etc/xcat/certkey.pem at 600 seconds,
which is far longer than the background 4096 bit key needs.
The spec read %{_target_cpu} after BuildArch: noarch, where rpm has already set it to
noarch, so the dmidecode and efibootmgr build-requires never applied and a sed deleted their
dracut_install line on every architecture. Every shipped image lacks both. The spec now
reads %{tarch}, and the dracut module installs whichever of the two the build root carries,
because ppc64le packages neither.
xCAT-test/unit/genesis_getcert_missing_openssl.t, genesis_payload_verification.t and
genesis_base_spec_buildrequires.t fail on the test commit before this one.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
mknb writes the management node key to /.ssh/authorized_keys for the legacy Genesis image. sshd reads that file only while the home directory of root is /. The dracut cmdline hook makes it / by deleting the root entry the image ships and appending its own. The test runs that rewrite against both root entry shapes dracut writes, for all three hooks, and reads back /etc/passwd. It also keeps a user name that starts with root in the file, so a wider delete cannot pass unnoticed. Six of the eighteen assertions fail today. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…/root Every case that boots a node into the el10 legacy Genesis image fails with "root@<cn>: Permission denied (publickey,password,keyboard-interactive)". mknb writes the management node key to /.ssh/authorized_keys, and sshd looks for it under the home directory of root. The dracut cmdline hook deletes the root entry the image ships with "sed -i '/^root:x/d'" and appends its own entry with the home directory /. dracut 99base writes that entry, and from dracut 060 the password field holds x only when the image is built --hostonly. The Genesis image is built with -N, so el10 (dracut 107) ships "root::0:0::/root:/bin/sh". The delete does not match, two root entries survive, and getpwnam returns the first one. el8 (dracut 049) and el9 (dracut 057) always ship the x and are not affected. The delete now matches the user name only. All three cmdline hooks carry the same statement and all three change. genesis_root_home.t runs the rewrite against both entry shapes and fails on the empty password field without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
… image nodeset_shell_lzma asserts "output=~genesis" on "ls -l /tftpboot/xcat/genesis.fs.*.lzma". The path in the command holds the string the check looks for, so the error "ls: cannot access '/tftpboot/xcat/genesis.fs.*.lzma'" matches too. The check is green whether mknb wrote the lzma image or not. Removing the "xz --format=lzma" fallback from genesis_lzma_command in mknb.pm makes mknb write only the gz image, and this check still passes. The same case starts with a "yum install" of xz-lzma-compat from a rpmfind.net CentOS 8-Stream PowerTools URL. No check follows it. The URL returns 404 since CentOS 8-Stream went end of life, so the step has done nothing for a long time. The check is now "rc==0". ls returns 2 when the glob matches no file, so the check is red exactly when mknb wrote no lzma image. The dead install and its paired "yum remove" are deleted rather than gated, because genesis_lzma_command falls back to "xz --format=lzma" and xz is present on every EL management node: the lzma image the case tests is produced without the package. Verified with the runcmd and check-evaluation code lifted out of xCAT-test/xcattest. With the lzma image present both checks are green. With only the gz image present the old check stays green and "rc==0" is red. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 942729a)
A sweep of xCAT-test/autotest/testcase for the shape found in
nodeset_shell_lzma -- a check whose expected pattern also appears in its own
command -- returns 274 matches. In six of them the self-matching check is the
only proof of the property the case exists to test, so the case is green when
the property is absent.
xdcp_RP and xdcp_R write "test1" into /tmp/xdcp/test1/test1.txt, then read it
back and assert "output=~test1". The path repeats the content, so "cat:
/tmp/xdcp/test1/test1.txt: No such file or directory" matches. These are the
only checks that read the copied bytes; the earlier ls checks prove the name
arrived, not the content. updatenode_diskful_syncfiles_dir has the same shape
for the files updatenode -F syncs.
lsxcatd_null asserts "output=~lsxcatd" on "lsxcatd", which the shell's
"lsxcatd: command not found" satisfies.
export_import_multiple_osimages_by_dir asserts "output=~site" on "ls -R
/opt/inventory/site", which "ls: cannot access '/opt/inventory/site'"
satisfies.
The copied and synced files now carry a content marker that the path does not
repeat, so the check reads the bytes and not the file name. lsxcatd_null
asserts a line of the usage text, and the two inventory listings assert the
exported osimage name.
Verified with the runcmd and check-evaluation code lifted out of
xCAT-test/xcattest. Every replaced check is green both when the behaviour is
present and when it is removed. Every new check is green with the behaviour
present and red without it.
Seven further self-matching checks in xdcp/cases0 ("ls -l /tmp/test1.txt"
with "output=~test1") measure nothing but sit behind a sound "ls -l /tmp"
check, so a real failure is already caught. They are left for a decision.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit 194dd4e)
viniciusferrao
requested changes
Sep 10, 2026
viniciusferrao
left a comment
Member
There was a problem hiding this comment.
Hi @dhilst, two points here:
-
The
ppc64elnaming cleanup makes sense given xCAT’s historical
Power naming. Could we also add replacement/conflict metadata for
the oldxcat-genesis-base-ppc64package, as we do for the scripts
package, so existing installations can upgrade cleanly? Keeping
the legacygenesis/ppc64/directory is fine; this is only about
the package-name transition. -
In
verify-genesis-payload,grep -v '^[/-]'also drops absolute
command paths, so missing binaries such as/usr/bin/awkcan pass
verification. Could we check required absolute paths relative to
the payload root as well, and add a test for a missing one?
Thanks!
dhilst
marked this pull request as ready for review
September 11, 2026 18:54
…ase/2.19-rc1 master moved 149 commits ahead of the branch point and four files needed a decision. xCAT/debian/control and xCATsn/debian/control: master moved nmap and ipmitool-xcat into Depends, raised the ipmitool version and added the s390x OpenEmbedded Genesis recommendation. The branch made the genesis-scripts dependency per architecture. Both are kept, so the ppc64el metapackage depends on xcat-genesis-scripts-ppc64el and no longer on the amd64 package. build-utils/lib/XCAT/BuildUtils.pm and xCAT-test/unit/build_utils.t: master replaced @DEB_ARCHES plus the branch's %NO_RISCV64 exception list with %ARCH_PACKAGES, which carries the architecture list per package. deb_package_arches returns the same answer for every package, so master's form is kept and %NO_RISCV64 is dropped. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…tion verify-genesis-payload reads the names the dracut module installs back out of module-setup.sh and checks each one against the extracted payload. It drops every name that starts with "/", so the 609 absolute paths the EL module names are checked by nothing. An image built without /usr/bin/awk, /etc/services or /lib64/libnss_dns.so.2 passes. The Genesis debs carry the architecture in the package name. 2.19 renames the ppc64 debs to ppc64el, and neither builddeb-genesis-base nor debuild-xcat-genesis-base names the deb the new package supersedes. dpkg keeps xcat-genesis-base-ppc64 installed beside xcat-genesis-base-ppc64el, and the old package owns the same files under /opt/xcat/share/xcat/netboot/genesis. genesis_payload_verification.t drives the verifier against a payload missing /usr/bin/awk and one missing /etc/services. genesis_base_deb_arch.t asserts the Replaces and Breaks the alien path writes. genesis_base_deb_control_rewrite.t lifts rewrite_control() out of builddeb-genesis-base and runs it over the control file in the tree. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
… and name the deb the rename supersedes verify-genesis-payload dropped every name that started with "/" before checking the payload, so the 609 absolute paths the EL dracut module installs were checked by nothing. An image with no /usr/bin/awk passed. The filter now drops only option words, and an absolute name is read back under the payload root. The ppc64 to ppc64el rename left the new Genesis base deb without a relation to the deb it replaces, so dpkg kept xcat-genesis-base-ppc64 installed beside it with its own copy of the files under /opt/xcat/share/xcat/netboot/genesis. builddeb-genesis-base and debuild-xcat-genesis-base now write Replaces and Breaks for the superseded package, as the genesis-scripts control file already does. The native path takes the architecture rewrite into rewrite_control() so the superseded name is derived in one place. genesis_payload_verification.t, genesis_base_deb_arch.t and genesis_base_deb_control_rewrite.t fail without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
xcat_riscv64_genesis_dependency.t pins the deb dependency on the legacy Genesis scripts as a single xcat-genesis-scripts-amd64 entry qualified [!riscv64]. That entry gives a ppc64el management node the amd64 scripts package, which pulls the amd64 Genesis base with it, and this branch replaces it with one entry per architecture. The test now asserts that every xcat-genesis-scripts entry names an architecture that has a legacy Genesis, and that the ppc64el reduction asks for xcat-genesis-scripts-ppc64el. The riscv64 assertions are unchanged: no entry applies there. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
… whole suite Thirteen test files this branch adds call BAIL_OUT at fifty-one places: an extraction that stopped matching, a fixture that is not there, a harness that wrote no log. prove stops every remaining file on a bail-out, not only the file that called it, so one of them hides the results of every test that would have run after it. die is just as loud and costs only its own file. Fifteen comments the branch added also carried the incident rather than the constraint. Three pasted an error transcript, five traced a failure from a macro or a missing file out to a node that never boots, and the rest counted call sites, package sizes or dracut build numbers. Each now states the one fact the reader cannot re-derive from the code. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…t was replaced The comment above the /usr/bin/awk case in genesis_payload_verification.t said what the verifier used to do with an absolute path. The rule the reader needs is what dracut_install does with one. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
Eight unit tests measure shell code: the Genesis dracut cmdline hooks, doxcat, getcert, the two Genesis deb builders, go-xcat and the genesis test case. The Perl in each one is scaffolding. It reads the script, lifts a block out with a regular expression, writes a wrapper, shells out and reads the files back. A reader follows two languages to reach one assertion, and the scaffolding is longer than the assertion. xCAT-test/bats already states this kind of assertion in the language of the thing under test, and the xcat_test workflow runs it. The eight files move there. Each one keeps what it proved: the rpm architecture becomes the Debian architecture and names the deb it supersedes, the dracut hook picks the console mode the multiplexer can provide, the hook gives root the home directory /, getcert stops when the image ships no openssl, the genesis case defines its node with the architecture of the management node and fails when nodeset fails, doxcat picks dhcpcd where the release drops the ISC client, and go-xcat names the Genesis packages the packaging builds. helpers/shell_source.bash gains refute_grep. bash ignores errexit for a command inverted with "!", so "! grep" anywhere but the last line of a test can never fail it. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
…t fail genesis_base_deb_arch.t stopped with a die when debuild-xcat-genesis-base was absent, because a checkout without the converter has no deb rename to measure. The BATS file skipped there instead, and a skip reads green. setup() now asserts the script is readable. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
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.
Fixes for the problems regarding RC1 of 2.19 captured by the CI