2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-25 17:24:07 +00:00
Commit Graph

6335 Commits

Author SHA1 Message Date
Daniel Hilst 2f715ac371 Merge pull request #7818 from VersatusHPC/release/2.19-rc1
ci(xcat-core): Fixes to get CI running for all 2.19 targets
2026-09-17 18:18:48 -03:00
Daniel Hilst 2e6ca07172 Merge pull request #7841 from VersatusHPC/fix/ubuntu-power-diskful-installer-loop
fix(xcat-core): the Ubuntu POWER diskful install never leaves the installer
2026-09-17 12:38:17 -03:00
Daniel Hilst d694456244 Merge pull request #7855 from VersatusHPC/fix/ddns-tsig-algorithm-downgrade
fix(xcat-core): makedns leaves records behind because named cannot verify its own TSIG key
2026-09-17 11:39:44 -03:00
Daniel Hilst 6a41acf2db fix(xcat-core): the retried DNS update carries two TSIG records
makedns reports "error was FORMERR" for an update that named rejected with
NOTAUTH. The FORMERR is the answer to the retry, not to the first attempt.

send_ddns_update in ddns.pm signs the packet the caller built, and signs that
same packet again on each attempt. Net::DNS::Packet::sign_tsig appends the TSIG
to the additional section, so the second attempt sends two TSIG records and
named answers FORMERR. FORMERR is neither NOTAUTH nor SERVFAIL, so the routine
stops and reports it. The NOTAUTH and SERVFAIL retry can never be accepted, on
any algorithm.

Each attempt now signs a request of its own. A packet cannot be unsigned again,
so ddns_update_request copies the prerequisite and update records into a new
Net::DNS::Update instead, and the caller keeps the unsigned original.

ddns_update_retry.t fails before this change: the second attempt carries two
TSIG records, and an update that the retry answers with NOERROR still reports
failure.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-15 20:43:58 -03:00
Daniel Hilst 4eb9718548 fix(xcat-core): makedns rewrites its own TSIG key and then fails against it
makedns exits 1 on a management node that has Net::DNS below 1.36 and an
hmac-sha256 key, and reports "Failure encountered updating <zone> with entry
'', error was FORMERR".

update_namedconf in ddns.pm rewrites the named.conf key stanza to hmac-md5
whenever Net::DNS is below 1.36, and ddns_tsig_algorithm returns hmac-md5 for
the same reason. ddns_sign_update signs with site.dhcpomapialgorithm, which
xcatconfig sets to hmac-sha256 on EL9 and later. named matches a TSIG key by
name and by algorithm, so it answers NOTAUTH. The retry signs the same packet
a second time, and named answers FORMERR to the two signatures.

The version test protected the two-argument sign_tsig($name, $secret), which
produces an HMAC-MD5 signature only. ddns_sign_update signs every other
algorithm through a KEY RR, so the Net::DNS version no longer selects the
algorithm. This change deletes the rewrite and the version test, and signs with
the algorithm the key stanza declares. OmapiPolicy->algorithm_rr_type maps that
algorithm to its KEY RR number.

ddns_named_key_algorithm.t fails before this change: it reads the stanza as
hmac-md5 where the key was hmac-sha256.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-15 20:43:58 -03:00
Daniel Hilst 5570a4c64a fix(xcat-core): the Ubuntu POWER diskful install never leaves the installer
reg_linux_diskfull_installation_flat fails on ubuntu-22-ppc64le-devel and
ubuntu-24-ppc64le-devel in build #121 of xcat-core-devel-ubuntu-cd. The
Subiquity installer starts, errors in its early-commands, tars
/var/log/installer to port 8080 and reboots, nine times in 75 minutes. No
system is ever installed, so the address answers from the live installer and
the case ends on
"root@xcat25-cn: Permission denied (publickey,password)".

mkinstall in xCAT-server/lib/xcat/plugins/debian.pm selected
pre.ubuntu.subiquity and then replaced it with pre.ubuntu.ppc64 for every
ppc64 node, whichever installer was in use. pre.ubuntu.ppc64 writes a partman
recipe, and the early-commands append it to /autoinstall.yaml, which Subiquity
cannot parse.

pre.ubuntu.subiquity offered a UEFI branch and a BIOS branch, so a ppc64el node
took the BIOS branch and was given a bios_grub partition. POWER firmware loads
the boot loader from a PReP partition.

install_prescript now returns the script from the installer and the
architecture together, and the ppc64 script is reached only on the
debian-installer path. pre.ubuntu.subiquity gains a PReP branch, taken when
uname reports a POWER machine, which flags an 8M first partition prep and makes
that partition the grub device.

debian_install_prescript.t and the PReP case of ubuntu_subiquity_storage.t fail
without these changes.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-14 07:27:58 -03:00
Daniel Hilst 24e22671b4 Merge branch 'master' of https://github.com/xcat2/xcat-core into release/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>
2026-09-11 15:59:58 -03:00
Daniel Hilst 0c27708c0f fix(xcat-core): nodeset cannot boot an Ubuntu POWER install from live media
nodeset stops the diskful install on every ppc64le cell of
xcat-core-devel-ubuntu-cd (build #119, ubuntu-24-ppc64le-devel):

    xcat25-cn: The network boot initrd.gz is not found in
    /install/ubuntu24.04.4/ppc64el/install/netboot.

The Ubuntu ppc64el live-server ISO carries no netboot tree. The installer
kernel and initrd sit under casper. Two places in
xCAT-server/lib/xcat/plugins/debian.pm reject that media: %INSTALL_BOOT_FILES
describes no casper layout for POWER, and mkinstall applies a second,
POWER-only precondition on install/netboot/initrd.gz before it calls the
resolver.

The POWER table now carries casper/hwe-vmlinux + casper/hwe-initrd and
casper/vmlinux + casper/initrd, after the netboot entries so a netboot tree
still wins. install_media_is_bootable replaces the POWER-only precondition, so
one routine decides what media can boot.

debian_install_boot_files.t resolves the POWER casper layouts and drives
install_media_is_bootable. It fails without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-11 15:09:27 -03:00
Vinícius Ferrão ac50225541 feat(Template): render the osimage pkglist into the autoinstall package list
A Subiquity autoinstall installs what its user-data packages list names,
and the templates could only name a fixed set, so the osimage pkglist
reached an Ubuntu node through ospkgs after the first boot. The preseed
token has no autoinstall form: the package list is YAML, one item per
line.

A list line that carries #INCLUDE_DEFAULT_PKGLIST_AUTOINSTALL# is now
replaced by one item per pkglist package at the same indentation, with
includes followed and without repeating the items the template lists
above it. The line is replaced in the include pass of subvars, so a site
template that includes the stock one is served too. A plain name and a task are
installed this way, and a comment after them ends the record. A version
pin or a target release stays with ospkgs, because the installer runs
apt-get without --allow-downgrades and a pin can require one, and so does
a name with an architecture qualifier, because a foreign architecture is
enabled by a postscript that runs later. A record that begins with
a removal or a group is left out whole, as ospkgs removes or installs it
whole, and so are a removal written with a trailing hyphen, markers and
preseed directives. A list that carries a #ENV: setting or an unreadable
include is left to ospkgs whole. So is the list of an osimage with
environvar, which mkinstall now hands over, and such an image's pkgdir
mirrors stay out of the installer's sources as well: those variables
reach apt-get only through ospkgs, and a mirror may need them. An osimage
without a pkglist loses only the token line.

The installer's apt configuration turns recommended packages off, as
ospkgs installs the list without them; curtin writes that setting into
the target, where the template removes it with the installer's sources.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-11 11:38:15 -03:00
Vinícius Ferrão 539486b7c8 feat(Template): give the Subiquity installer the pkgdir mirrors
An osimage pkgdir can name mirrors after the install media, and ospkgs
installs from all of them, but the autoinstall apt configuration offered
the installer only the archive mirror and the otherpkgs repositories. A
package that only a pkgdir mirror carries could not be installed before
the first boot.

The mirrors now join the installer's apt sources, next to the otherpkgs
ones, in every form the configuration takes. An entry written as URL,
suite and components is an apt source line, as ospkgs writes it, and a
suite that is an exact path needs no component. A local directory that
is a flat repository is served by the management node and trusted, as an
otherpkgdir is. An entry that names an Ubuntu archive mirror the
installer already has a source for, the configured one or a default one,
carries that source's signing key, the archive keyring on the Deb822
releases and none before them, because apt rejects a second source for
the same suite whose signing key differs. For the same reason a
repository is offered once, whether pkgdir names it twice, as a directory
and as its URL, or the otherpkgdir names it too. Anything
else is no apt source for ospkgs either and is left out.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-11 11:38:15 -03:00
Vinícius Ferrão a6e69e88a4 fix(debian): stop reporting riscv64 as an unknown install architecture
mkinstall mapped x86_64 and x86 to their Debian names and accepted ppc64le
and ppc64el. Every other architecture, riscv64 included, was logged as
"Unknown arch" on each diskful install, although the install went on with
the name unchanged, which is right for riscv64.

Move the mapping into install_darch, which takes the Debian name from
xCAT::Utils::debian_arch and knows the architectures xCAT installs Ubuntu
on. riscv64 is one of them.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-08 22:01:34 -03:00
Vinícius Ferrão c32c941ed7 fix(mknb): say where the riscv64 loader comes from on Ubuntu
The note shown when boot/grub2/grub2.<arch> is missing told the
administrator it comes from grub2-xcat or the EL installation media. On
Ubuntu neither is true: copycd builds the loader from the grub2 package on
the media, because the image the media carry cannot boot over the network.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-08 22:01:31 -03:00
Vinícius Ferrão 5b6120a182 fix(template): take the install mirror from the ports archive off amd64
archive.ubuntu.com publishes amd64 and i386 only, so a ppc64el or riscv64
node was given an apt mirror carrying no package for it and the installer
could not fetch what the minimal live media lacks. The default is now the
ports archive for those architectures, chosen from the osimage's
architecture rather than the package directory, which is whatever path the
administrator configured. site.ubuntu_apt_mirror still overrides it.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-08 22:01:27 -03:00
Vinícius Ferrão 52e468884e fix(grub2): keep the whole kernel command line past a grub2 separator
grub2 reads its configuration as a script, so an unquoted command separator
ends the linux command and everything after it is lost. The Ubuntu
installer seed is written as ds=nocloud-net;s=<url>, so the node booted
without the seed URL and without the arguments that followed it, including
BOOTIF. The installer then found no autoinstall configuration and waited
for someone to answer its questions. A separator that is neither escaped
nor inside a quoted span is now escaped where it stands, which grub2
removes before it hands the line to the kernel. A value the caller escaped
or quoted keeps exactly the form the caller gave it.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-08 22:01:27 -03:00
Vinícius Ferrão 01e9ea5152 feat(copycds): build the riscv64 grub2 loader from the Ubuntu media
riscv64 nodes have no boot loader unless one reaches /tftpboot/boot/grub2,
and nothing on an Ubuntu management node puts one there. The grub2 image
the media carry cannot serve: it holds a built-in configuration that looks
for the live filesystem, so a node that loads it drops to a grub prompt
instead of reading the configuration nodeset writes. copycd now builds a
netboot image from the grub2 package the media ship, and warns when it
cannot, because the node has no other source for one. An image already in
place is kept only when it is a whole executable image for the
architecture the firmware loads and carries the prefix this boot path
needs; one that is not is removed, so a rebuild that cannot run leaves
nodeset reporting a missing loader rather than serving an unusable one.
The media of every other architecture are untouched.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-08 17:02:03 -03:00
Vinícius Ferrão 4e36e1a9f2 feat(debian): recognize riscv64 Ubuntu media
The riscv64 live-server image keeps its kernel at casper/vmlinux, where every
other live image keeps casper/vmlinuz, so the probe found no kernel and mkinstall
reported that the install image was missing.

Add the riscv64 candidate pair and let copycd name the architecture the media
reports. Verified against Ubuntu-Server 24.04.4 riscv64, which carries
casper/vmlinux, casper/initrd and casper/install-sources.yaml.

Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-08 17:02:02 -03:00
Daniel Hilst 8a77a645af Merge pull request #7816 from VersatusHPC/fix/sudoer-postscript-password
fix(sudoer): take the password from the passwd table
2026-09-08 10:29:50 -03:00
Vinícius Ferrão 4ad9db20a4 refactor(genesis): follow mknb perl style 2026-09-04 18:03:05 -03:00
Vinícius Ferrão 288ca8b78a fix(genesis): install s390x configs safely 2026-09-04 17:41:08 -03:00
Vinícius Ferrão a8c6bd2a4a fix(genesis): harden s390x configurations 2026-09-04 17:15:23 -03:00
Vinícius Ferrão 9d30f127b5 fix(genesis): simplify s390x network IPL 2026-09-04 16:20:38 -03:00
Vinícius Ferrão a1e9948997 fix(genesis): limit s390x boot to validated path 2026-09-04 15:31:33 -03:00
Daniel Hilst 506069061b fix(xcat-core): a match made elsewhere can name a KVM volume
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>
2026-09-04 15:20:57 -03:00
Daniel Hilst 0a858b60f4 fix(xcat-core): a pool-backed KVM disk reaches libvirt with no bus
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>
2026-09-04 15:20:47 -03:00
Vinícius Ferrão 77ada41319 refactor(genesis): keep s390x Perl policy neutral 2026-09-04 14:55:21 -03:00
Vinícius Ferrão f549f46b51 fix(genesis): harden s390x boot handoff 2026-09-04 14:42:35 -03:00
Vinícius Ferrão 5203c17a87 refactor(genesis): clean s390x Perl code 2026-09-04 13:39:50 -03:00
Vinícius Ferrão a4109f6865 feat(genesis): add s390x network boot 2026-09-04 12:48:32 -03:00
Daniel Hilst 349658d3d7 fix(xcat-core): mkvm builds a riscv64 node as an x86_64 domain
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 8d149c856302c8016fb0ead31e9859fd5a1e9dff)
2026-09-04 12:20:34 -03:00
Daniel Hilst 0136c51a18 fix(mknb): a Genesis copy that fails must fail mknb
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 d46ca3e09bf52827bf0b8fa9cb94279a9da2c97b)
2026-09-04 12:20:34 -03:00
Daniel Hilst 445b755d8e test(mknb): capture a Genesis copy failing without failing mknb
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 989deaa31eb1f3979a8db030d3ae8c404abda2fb)
2026-09-04 12:20:34 -03:00
Daniel Hilst fd580b901f Merge pull request #7817 from VersatusHPC/refactor/debian-arch-map
refactor(debian): map media architectures through a shared table
2026-09-04 11:07:16 -03:00
Vinícius Ferrão a712ec33d9 fix(credentials): serve the passwd hash of a node's configured sudoer
getcredentials answered xcat_secure_pw only for root, so a postscript
had no way to get the password of another node account from the passwd
table.

xcat_secure_pw:<user> now returns the password field of the passwd row
key=system,username=<user> when <user> is root or a sudoer named in the
postscripts or postbootscripts of the requesting node, its osimage, or
xcatdefaults. A sudoer without a row or without a password gets the
locked field "!", so the node applies the reply as is. Any other user,
an invalid user name, or a failed hash answers with an error instead of
an empty reply. The root request reads the same row as before and keeps
the error reply for a missing row.
2026-09-03 20:39:08 -03:00
Daniel Hilst e08fe95959 Merge pull request #7799 from VersatusHPC/fix/ipmi-ipv4-literal-guardrail
fix(ipmi): reject ambiguous IPv4 literals
2026-09-03 20:27:14 -03:00
Vinícius Ferrão bf56116732 refactor(debian): map media architectures through a shared table
copycd translated the architecture the Ubuntu media reports with its own
if/elsif chain, and genimage translates the same names back for debootstrap with
another one. Neither can be reused, so a new architecture has to be added to
both.

Put both directions in xCAT::Utils and have copycd read from there. The names
and the fallback do not change: media that xCAT has no name for still leave the
architecture as the media reported it.
2026-09-03 19:44:13 -03:00
Daniel Hilst 9f4e53e380 Merge pull request #7800 from VersatusHPC/refactor/dhcp-omapi-command-runner
refactor(dhcp): share OMAPI command runner
2026-09-03 19:34:10 -03:00
Vinícius Ferrão 4312fe8337 refactor(debian): resolve the install kernel and initrd from a table
The probe spelled out every candidate path twice inside one nested condition,
once to test it and once to assign it, so adding an architecture meant adding
another branch of the same shape. Move the candidates into a table keyed by
architecture family and walk it in order.

Same paths, same precedence, same failure behaviour: a media tree that matches
nothing leaves the caller on the "install image not found" path as before.
2026-09-03 18:49:07 -03:00
Vinícius Ferrão d1bd0fe576 refactor(dhcp): share OMAPI command runner 2026-09-03 18:13:59 -03:00
Daniel Hilst 362bf5eb9f Merge pull request #7760 from VersatusHPC/fix/ubuntu-mn-ntp-daemon
fix(xcat-core): makentp fails on a stock Ubuntu MN (timesyncd cannot serve time)
2026-09-03 17:54:02 -03:00
Daniel Hilst 7003e0c0b6 Merge pull request #7761 from VersatusHPC/fix/ubuntu-subiquity-diskful-install
fix(xcat-core): the Ubuntu Subiquity diskful install never completes
2026-09-03 17:51:50 -03:00
Daniel Hilst a82d77fbc4 Merge pull request #7758 from VersatusHPC/fix/makedhcp-ubuntu-backend-and-query
fix(dhcp): makedhcp fails on a stock Ubuntu MN, and host-block scans match the wrong node
2026-09-03 16:57:42 -03:00
Daniel Hilst 39eb6ce532 Merge pull request #7767 from VersatusHPC/refactor/commandutils-executable-finder
refactor(utils): centralize executable lookup
2026-09-03 14:55:14 -03:00
Daniel Hilst eff0399a7b Merge pull request #7794 from VersatusHPC/refactor/ipmi-ipv4-command-encoding
fix(ipmi): centralize IPv4 command encoding
2026-09-03 14:53:21 -03:00
Daniel Hilst 05fc81f7b5 fix(subiquity): three values the Ubuntu install path accepts and cannot use
The boot flip in compute.subiquity.tmpl addressed port 3002. xcatd's install
monitor listens on site.xcatiport, so a cluster that moves the port loses the
flip and every node PXE-loops back into the installer. The flip now reads
site.xcatiport and keeps 3002 as the default. TABLEBLANKOKAY, because the key is
optional and a plain TABLE lookup of an absent key fails the whole template.

The flip also counted any reply as an accepted request. It now requires the
monitor's "ready" greeting before it sends "next", and "done" afterwards, so a
different service on that port is not read as a flipped node.

subiquity_nfsroot_server in debian.pm called getipaddr without a family. A
dual-stack management node answers with its IPv6 address, and casper takes
everything after the first colon in nfsroot= as the path, so the live filesystem
never mounts. It now asks for IPv4, as dhcp.pm and mknb.pm do.

The DNS setup wrote the xcatmaster name as a nameserver when getent found no
address, which is the case the step exists to prevent. It now keeps the
resolv.conf DHCP gave the live installer.

ubuntu_subiquity_boot_flip.t, debian_subiquity_boot_params.t and
ubuntu_resolvconf_ip.t fail on the parent commit and pass here.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-03 14:52:49 -03:00
Daniel Hilst 947c624b3c fix(xcat-core): makedhcp -q hides a dhcpd.conf read failure and loses InfiniBand addresses
`makedhcp -q <node>` on Ubuntu's ISC-limited releases answers "no DHCP reservation
found" when it cannot read dhcpd.conf. The operator reads that as a node without a
reservation. An InfiniBand node also gets an answer with no hardware address.

_query_isc_static_host in dhcp.pm read the file with an -r test and dropped a failed
open. It also matched only a "hardware ethernet" line, while _add_isc_static_host
writes "hardware infiniband" for an InfiniBand node and adds a twin declaration
between the same markers.

_read_isc_conf_lines now returns the read error, _query_isc_static_host returns it to
listnode, and listnode answers the caller with an error. The parser accepts any
hardware type and keeps the first declaration of the block. The path of dhcpd.conf and
the distribution name are package variables, so a test can drive the query and
listnode.

dhcp_isc_static_host_query.t covers the InfiniBand address, the twin declaration, the
unreadable file and the listnode answer. It fails without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-03 14:42:51 -03:00
Daniel Hilst a6212e8384 fix(xcat-core): makentp and the NTP selector disagree on when chrony is usable
xCAT::NTP::Backend->available reported chrony as available on chronyd alone, while makentp
configured chrony only where systemctl was present too. On a host with chronyd and no systemctl
the selector returned chrony with no downgrade, makentp fell through to the ntpd path, and the
admin saw either a silent switch or "Please make sure ntpd is installed".

available now requires chronyd and systemctl for chrony, so the selector answers on the same
terms makentp acts on, and makentp branches on the name alone. choose therefore downgrades to
ntpd, or reports install, in the case it used to pass over. A commands argument injects the
command probe, in the same shape as the existing available argument.

ntp_backend_selection.t covers both commands. Six of its assertions fail without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-03 14:40:31 -03:00
Vinícius Ferrão 77c1694b03 refactor(utils): centralize executable lookup 2026-09-02 22:57:05 -03:00
Daniel Hilst a11bd9e43d fix(xcat-core): make makedhcp work on a stock Ubuntu management node
Fall back to an available DHCP backend on auto-selection. When the request is "auto"
and the backend chosen for this OS is not installed, use the other one if it is,
recording fallback_from so process_request can tell the operator which preferred
backend is missing. A backend the admin forced through site.dhcpbackend still fails
hard when absent, and "neither installed" still errors clearly. Fixes #7710.

Answer makedhcp -q from the static host block on Ubuntu's ISC-limited releases.
listnode now branches on _isc_static_host_fallback() before any omapi work and reads
the node's fixed-address and hardware ethernet straight out of dhcpd.conf, so the
query path never spawns the omshell its own write paths already avoid. A node with no
reservation is now reported rather than answered with silence.

Match the host-block markers exactly. _add_isc_static_host writes a fully determined
pair -- "#xCAT host declaration for <node> aka host <hostname> start" and the "}"
line carrying the matching end -- so both scans anchor on that whole shape through
shared _isc_host_start_re/_isc_host_end_re helpers. The previous /\Q$node\E\b.*/ also
matched at a hyphen, letting node "compute" act on "compute-01"'s block: the query
could return another node's address and the delete could remove another node's
reservation. _delete_isc_static_host also accepts an explicit line list now, so the
scan is unit testable without file-scoped state.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-09-02 21:29:33 -03:00
Vinícius Ferrão 17f5b06106 refactor(confluent): share first-row attribute flattening
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
2026-09-02 19:32:29 -03:00
Daniel Hilst b4579ef459 Merge pull request #7802 from VersatusHPC/refactor/networkutils-ip-validation
refactor(networkutils): remove the legacy validate_ip helper
2026-09-02 15:04:20 -03:00