2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-22 07:38:08 +00:00
Commit Graph

28643 Commits

Author SHA1 Message Date
Daniel Hilst 7594786fcf fix(kvm): an aarch64 guest gets vga when the hypervisor offers no usable model
preferred_video_model returned vga whenever no preferred model was
found, also when the hypervisor did not offer vga, did not support video,
or the capability query failed. Under native aarch64 KVM, vga and the
other PCI framebuffer models do not display correctly.

An aarch64 guest now takes the first offered model of virtio and ramfb
under KVM, or of virtio, vga and ramfb under TCG. When video is
unsupported or no wanted model is offered, build_xmldesc writes no
<video> and no <graphics>, and the guest uses its serial console. When
the capabilities are unavailable, build_xmldesc returns an error that
names the query error and vm.vidmodel.

vm.vidmodel still overrides the choice. Other architectures do not
query the capabilities and keep their fixed model.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-14 05:40:19 -03:00
Daniel Hilst ffc616972e test(kvm): an aarch64 guest gets vga when the hypervisor offers no usable model
preferred_video_model returns vga whenever no preferred model is found.
That includes a hypervisor that offers vga only, a hypervisor with
<video supported="no">, and a failed capability query. On a native
aarch64 KVM hypervisor, vga is not a usable model.

Add cases for each input: no usable model offered, video unsupported,
capabilities unavailable, and capabilities with no video element. A
native aarch64 guest now expects ramfb instead of vga when virtio is
not offered. The vm.vidmodel override and the architecture cases stay.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-14 05:39:31 -03:00
Daniel Hilst 84f693f493 refactor(kvm): move guest XML decisions into xCAT::KVMUtils
build_xmldesc, build_diskstruct and createstorage made their domain
decisions inline, so the unit tests could reach them only by loading the
whole plugin. kvm.pm now calls xCAT::KVMUtils for each decision and keeps
the libvirt calls, the table updates and the globals. $updatetable,
$confdata, $hypconn and $node are lexicals again.

The domain XML, the disk list and the volume names are unchanged.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-13 11:59:53 -03:00
Daniel Hilst e9ff86126c test(kvm): kvm unit tests load the whole kvm plugin through a shim
The kvm unit tests loaded xCAT-server/lib/xcat/plugins/kvm.pm with a fake
Sys::Virt and monitorctrl in %INC, an XCATROOT redirect, and package
variables made public only so that a test could set them.

Add xCAT::KVMUtils, a module that loads no xCAT module and no libvirt
binding. It holds the guest architecture profile, the CPU, emulator and
video model choices, and the disk model, prefix and bus choices, each as
a sub that takes its inputs and returns its answer. The three tests call
these subs directly and assert that the module loads no other xCAT
module. XCAT::Test::KvmPlugin is deleted.

A new case covers the video model of an aarch64 guest on an aarch64
hypervisor.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-13 11:59:53 -03:00
Daniel Hilst a879013367 test(kvm): kvm unit tests exercise a copy of the kvm.pm routines
kvm_createstorage_model.t and kvm_diskstruct_bus.t cut createstorage,
build_diskstruct and their helpers out of kvm.pm with a regex and ran
them with eval in a scratch package. The tests passed when kvm.pm
changed in a way the regex did not see, and they failed when kvm.pm
was reformatted.

The new XCAT::Test::KvmPlugin module loads kvm.pm from the checkout
and returns the modules that came from /opt/xcat. The two tests and
kvm_guest_arch.t use it and call xCAT_plugin::kvm routines in-process.
They replace only the routines that reach libvirt, with local.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-13 09:03:26 -03:00
Daniel Hilst fc6668d972 test(kvm): kvm_guest_arch.t tests a copy of the kvm.pm routines
kvm_guest_arch.t cut build_xmldesc and five other routines out of
kvm.pm with a regex and ran them with eval in a scratch package. The
test passed when kvm.pm changed in a way the regex did not see, and
it failed when kvm.pm was reformatted.

The test now loads kvm.pm with require and calls
xCAT_plugin::kvm::build_xmldesc and build_diskstruct. Sys::Virt and
the monitoring plugin are stubbed in %INC. kvm.pm declares
$updatetable, $confdata, $hypconn and $node with our instead of my,
so that the test can set them with local. The test sets XCATROOT to
the checkout and asserts that no module loads from /opt/xcat.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-12 13:45:53 -03:00
Daniel Hilst ff4fb0d660 fix(kvm): an ARM guest asks its hypervisor for a video model it has
The aarch64 profile named one video model for every hypervisor. A model is not
a property of the architecture: the emulator build decides it. On a host whose
aarch64 emulator carries no virtio-gpu device, libvirt answers "domain
configuration does not support video model 'virtio'" and mkvm cannot define the
node, while the riscv64 emulator of the same host offers virtio.

build_xmldesc() now reads the domain capabilities of the hypervisor and
preferred_video_model() returns the first model the profile wants that the
hypervisor offers. An aarch64 guest wants virtio and falls back to vga, which
is what an emulator with no virtio-gpu device offers. vm.vidmodel still
overrides both, and an architecture with no preference list makes no libvirt
call.

Measured on a hypervisor whose aarch64 emulator has no virtio-gpu device: the
builder picks vga and virsh define accepts the domain. The same builder asking
for virtio is refused there.

Three assertions in kvm_guest_arch.t fail without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-08 12:31:29 -03:00
Daniel Hilst 40cd19b72e test(kvm): the video model of an ARM guest comes from the hypervisor
The video models of a machine type come from the emulator build, not from the
architecture. On one host libvirt reports virtio for a riscv64 virt machine and
not for an aarch64 one, because that aarch64 emulator carries no virtio-gpu
device, and `virsh define` on an aarch64 virt domain answers "domain
configuration does not support video model 'virtio'".

A hard-coded model is therefore wrong on one host or the other. The test gives
the domain builder a hypervisor connection that answers a domain capabilities
document, and asserts the model it picks: virtio when the hypervisor offers it,
vga when it does not, and vga when there is no connection or no video section.
vm.vidmodel keeps its own answer.

Three of the new assertions fail on the unfixed tree.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-08 12:30:27 -03:00
Daniel Hilst f59aceb0df fix(kvm): an ARM guest takes the accelerator and CPU of its hypervisor
guest_arch_profile() gave every aarch64 guest domain type qemu and the
cortex-a57 CPU model, so an aarch64 hypervisor ran its own guests under
emulation. The profile now reads both architectures: an aarch64 guest on an
aarch64 hypervisor is a kvm domain with CPU mode host-passthrough, which is the
only CPU KVM runs on ARM, and every other hypervisor keeps the emulated case
with the custom cortex-a57 model.

build_xmldesc() read the hypervisor cpumodel alone for the CPU model, the CPU
topology and the qemu-system-ppc64 emulator, so an aarch64 guest on a POWER
hypervisor received a POWER CPU model, a pseries topology and a ppc64 emulator.
The profile now marks a pseries guest and those three settings follow the mark.
libvirt resolves the emulator of an ARM guest from its own capabilities.

A cpumode from vm.othersettings reached a domain of either type. Both
host-passthrough and host-model read the host CPU, which an emulated guest does
not run, and libvirt reports both as unsupported for an emulated aarch64
domain. An explicit mode now reaches a kvm domain only.

The video model is virtio, as it is for a riscv64 virt guest. The aarch64 virt
machine supports virtio video; the earlier refusal came from an emulator build
with no virtio-gpu device.

kvm_guest_arch.t covers the four host and guest pairs and the explicit CPU
modes. Ten of its assertions fail without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-08 12:18:01 -03:00
Daniel Hilst 1c91237cfc test(kvm): cover the accelerator and CPU policy of an ARM guest
The aarch64 domain of the branch was measured on one host and guest pair, an
x86_64 hypervisor emulating aarch64. Three other pairs are not covered.

An aarch64 guest on an aarch64 hypervisor must be a kvm domain that takes the
host CPU, not a qemu domain pinned to cortex-a57. An aarch64 guest on a POWER
hypervisor must take neither the POWER CPU model, nor the pseries CPU topology,
nor the qemu-system-ppc64 emulator. A CPU mode from vm.othersettings must not
reach an emulated domain, because TCG has no host CPU.

The video assertion stated that the aarch64 virt machine has no virtio video
model. libvirt reports virtio for a riscv64 virt machine and not for an aarch64
one on the same host, and the aarch64 emulator there has no virtio-gpu device,
so the refusal came from that build and not from the machine type. The test now
expects the virtio model, as it does for riscv64.

The POWER controls now pass a hypervisor cputype, which is what builds the CPU
model and the topology element.

Ten of the new assertions fail on the unfixed tree.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-08 12:14:41 -03:00
Daniel Hilst 02a266c236 fix(kvm): mkvm builds an aarch64 node as an x86_64 domain
guest_arch_profile() in the kvm plugin has an arm for riscv64 and an arm for
POWER, and none for aarch64. A node whose nodetype.arch is aarch64 therefore
keeps the x86 defaults, and mkvm defines a domain with os/type/@arch x86_64 and
machine pc-i440fx. The compute node gets its lease, loads the x86 iPXE ROM,
fetches the grub2.aarch64 image that nodeset staged, and answers "Could not
boot image: Exec format error". It then falls through to the empty disk.

guest_arch_profile() now returns an aarch64 profile: domain type qemu, os arch
aarch64, machine virt, UEFI firmware, no x86 features and no SeaBIOS serial
option, no USB tablet, and scsi disks with the sd prefix. machine is the
unversioned alias, so libvirt resolves the version the hypervisor has. The
video model stays vga, unlike riscv64: the aarch64 virt machine offers no
virtio video model, and libvirt refuses the domain that asks for one.

The profile also names a CPU model, which riscv64 did not need. With no <cpu>
element libvirt passes -cpu max, which under TCG turns on SVE, and the guest
stays in its firmware. build_xmldesc writes the model only when nothing else
built a cpu element, so vm.cpumode and a pseries guest keep theirs.

kvm_guest_arch.t covers the new arm. Eleven of its assertions fail without this
change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-08 03:35:05 -03:00
Daniel Hilst 846ef996ef test(kvm): cover the libvirt domain of an aarch64 guest
guest_arch_profile() has an arm for riscv64 and an arm for POWER, and none for
aarch64. An aarch64 node therefore keeps the x86 defaults and mkvm defines an
x86_64 domain, which cannot run the grubaa64.efi that nodeset staged.

kvm_guest_arch.t now builds the domain of an aarch64 node on an x86_64
hypervisor and asserts the domain type, the os arch, the machine type, the UEFI
firmware, the pinned CPU model and the scsi disks. It also asserts that a
POWER guest keeps its own cpu element and that an x86_64 guest states none, so
the new arm cannot reach another architecture.

Eleven of the new assertions fail on the unfixed tree.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-08 03:34:49 -03:00
Daniel Hilst 5952dc04a2 Merge pull request #7594 from VersatusHPC/feat/fips-support
feat(fips): support installation on FIPS-enabled systems
2026-10-07 10:34:18 -03:00
Daniel Hilst e469015227 Merge pull request #7902 from VersatusHPC/test/r26-routeop-behavior
test(routeop): exercise the complete postscript
2026-10-07 10:33:41 -03:00
Daniel Hilst 332e054516 Merge pull request #7897 from VersatusHPC/fix/openeuler-ppc64le-core-mock-resultdir
fix(xcat-core): the openEuler ppc64le core build cannot write its own resultdir
2026-10-07 10:31:05 -03:00
Daniel Hilst 644dd3d4d1 Merge pull request #7901 from VersatusHPC/fix/openeuler-encrypted-passwd-openssl
fix(xcat-core): encrypted_passwd_openssl_diskfull reports no password on openEuler
2026-10-07 10:30:30 -03:00
Daniel Hilst 1a0cebb7df Merge pull request #7904 from middelkoopt/tm-genimage-gpgcheck-v3
feat(genimage): opt-in package signature checks for EL images
2026-10-07 10:24:26 -03:00
Daniel Hilst 324507651c fix(xcat-core): the chrootuid comment and its assertion describe mock wrongly
build-utils/lib/XCAT/BuildUtils.pm said the inherited chrootuid 1000 stays in
effect for the chroot. A mock configuration is Python, so the later assignment
replaces the value and nothing reads 1000 afterwards. The in-chroot build user
becomes uid 0.

buildrpms_mock_resultdir_uid.t asserted that the inherited line is still
present. The pattern is a line of the test's own fixture and mock_config_text
only appends, so the assertion passes even when the function returns the base
text unchanged. It is removed.

The comment now states the replacement and its consequence, and records why
chrootgid is left unset. Without the chrootuid assignment the file fails 2 of
10.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-06 22:05:25 -03:00
Timothy Middelkoop d1faba077c feat(genimage): opt-in package signature checks for EL images
Add the linuximage gpgcheck attribute. When it is set to 1 or yes,
genimage passes --gpgcheck to the shared RPM image builder, which
exports the builder's trusted RPM keys exactly as it does for openEuler
and writes gpgcheck=1 with that gpgkey for the pkgdir, kerneldir and
otherpkgdir repositories. Unset keeps the existing unverified
configuration, openEuler stays always verified, and builders without
the option reject the attribute instead of ignoring it.

Collect the otherpkgs repositories in imgutils so that an otherpkgdir
holding only URLs no longer adds a file:/// repository that fails to
download metadata on EL.

Signed-off-by: Timothy Middelkoop <tmiddelkoop@internet2.edu>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:24:33 -05:00
Vinícius Ferrão 6fc1f332cb docs(test): document routeop sandbox prerequisites 2026-10-06 12:21:47 -03:00
Vinícius Ferrão ca33542789 test(routeop): exercise the complete postscript
Replace the extracted-function Perl runner with BATS tests that invoke
routeop in isolated Linux namespaces. Check route commands, persistent
entries, matching routes, and replacement failures.
2026-10-06 12:21:47 -03:00
Daniel Hilst edb7d3217a fix(xcat-core): encrypted_passwd_openssl_diskfull reports no password on openEuler
The case failed on openeuler20.03sp4, openeuler22.03sp4 and openeuler24.03sp4, 3 occurrences
in xcat-ci build 89. The diff check failed, not the extraction.

encrypted_passwd_openssl_diskfull is the only case in passwd/case0 that selects the extraction
by distribution. It greps /etc/*release for SUSE, then for "Red Hat|CentOS|Rocky|Alma", then for
Ubuntu. On an openEuler management node all three miss and openEuler matches, so the case takes
the final arm, prints "Sorry,this is not supported os", writes nothing to
/tmp/instcryptedpasswd, and the diff against the password table reports rc=2.

openEuler now takes the Red Hat arm. compute.openeuler.tmpl writes
"rootpw --iscrypted #CRYPT:passwd:key=system,username=root:password#", which is byte-identical
to every EL template, so field 3 holds the hash and the EL cells already pass with that arm.

The diff check is unchanged, so the case still fails when the extraction reads the wrong field:
field 3 of the expanded line gives diff rc=0 and field 4 gives rc=1.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit a1b9372c413f54d18ba6a60d3839e9f75d7b8261)
2026-10-06 10:32:33 -03:00
Daniel Hilst 93322cd0f4 Merge pull request #7899 from VersatusHPC/fix/xcat-ws-conf-module-path
fix(xCAT-server): xcat-ws.conf names a SUSE module path and never matches its package
2026-10-06 10:21:57 -03:00
Daniel Hilst 74f0267ca1 Merge pull request #7898 from VersatusHPC/fix/openeuler-nicextraparams-ifcfg-persist
fix(configeth): a nicextraparams key never reaches an ifcfg NIC profile
2026-10-06 10:21:31 -03:00
Vinícius Ferrão 3976dd96b3 docs(fips): describe installation and validation boundaries 2026-10-05 22:56:35 -03:00
Vinícius Ferrão cb70af1e16 test(discovery): exercise bootstrap signing and reused keys 2026-10-05 22:56:00 -03:00
Vinícius Ferrão 3908b13960 fix(discovery): use FIPS-compatible bootstrap keys 2026-10-05 22:55:27 -03:00
Vinícius Ferrão 923fe01d2d test(dhcp): cover conditional SHA client requirements 2026-10-05 22:54:53 -03:00
Vinícius Ferrão b633f669c4 fix(dhcp): check SHA support only when OMAPI requires it 2026-10-05 22:54:27 -03:00
Vinícius Ferrão 6cd25ac453 test(kea): cover FIPS key errors and legacy compatibility 2026-10-05 22:53:43 -03:00
Vinícius Ferrão 45d773d5cd fix(kea): propagate invalid FIPS key policy 2026-10-05 22:53:29 -03:00
Vinícius Ferrão f095e5da81 test(dhcp): cover shared FIPS defaults and BIND signing 2026-10-05 22:52:49 -03:00
Vinícius Ferrão d01cb679eb fix(dhcp): share SHA-256 key policy in FIPS mode 2026-10-05 22:52:34 -03:00
Vinícius Ferrão dc2f83a2de test(ssh): exercise FIPS policy and optional host keys 2026-10-05 18:14:20 -03:00
Vinícius Ferrão 750ed7e5a5 fix(ssh): skip optional DSA host keys in FIPS mode 2026-10-05 18:14:20 -03:00
Vinícius Ferrão 449c52acfe test(dhcp): isolate compatibility fixtures from host FIPS mode 2026-10-05 18:14:20 -03:00
Daniel Hilst 86aaceb714 fix(xcat-core): read the NIC configuration from the file NetworkManager reports
confignetwork_secondarynic_nicextraparams_updatenode fails on EL8 because the dump
nic_cfg.sh prints carries no extra params, although configeth wrote CONNECTED_MODE and the
node has it.

nm_show resolves the connection's backend file by globbing
/etc/NetworkManager/system-connections for the UUID. The keyfile plugin keeps a connection
there, and on EL9 and EL10 it is the only plugin. On EL8 the ifcfg-rh plugin owns the
connection and keeps it under /etc/sysconfig/network-scripts, so the glob matches nothing and
no file is dumped. Every check that greps the dump for a value nm_show does not normalize
then sees nothing.

Ask NetworkManager for the path through the UUID,FILENAME fields and keep the glob as a
fallback. Read the MTU from either spelling, because a keyfile writes "mtu=" and an ifcfg
file "MTU=".

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 14:07:47 -03:00
Daniel Hilst b1d3190298 fix(xcat-core): the nicextraparams repair keeps a stale value and joins lines
xcat_persist_nic_extra_param only appended a key that was absent. When the profile already held
CONNECTED_MODE=no, a request for yes left no. It appended after the last line, so a profile with
no final newline got NAME=xcat-ens4CONNECTED_MODE=yes. In a keyfile it appended at the end of the
file, which is not the [user] section when another section follows it.

The function now rewrites the profile with awk. It replaces the line of the exact key, or inserts
the key at the end of [user] for a keyfile and at the end of an ifcfg file. It adds [user] when the
keyfile has none.

The repair block of configeth moves into xcat_nm_persist_nic_extra_params, so a test can reach the
store decision. configeth calls it after the last nmcli con up. xcat_uses_nm_keyfile now calls
xcat_nm_conn_file instead of repeating its two nmcli calls.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 14:07:47 -03:00
Daniel Hilst 2228479cac test(xcat-core): capture the nicextraparams repair on an ifcfg profile
The persist test sourced only xcatlib.sh and never reached the gate in configeth that skipped an
ifcfg profile, so putting that gate back left every test green. Its refusal test also passed on a
127 from a missing function.

The test now calls the repair through xcat_nm_persist_nic_extra_params with nmcli stubbed to
report an ifcfg file and a keyfile. It also captures three faults of xcat_persist_nic_extra_param:
it keeps an old value, it joins the key to a last line with no newline, and it appends a keyfile
key after a section that follows [user].

nic_cfg.bats captures that nm_show prints no profile when NM reports an ifcfg file, so the xcattest
case cannot match CONNECTED_MODE=yes there. nic_cfg.sh returns before its dispatch when sourced.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 14:07:36 -03:00
Daniel Hilst 6bc7800bba fix(xcat-core): deny the REST aliases when mod_rewrite is not loaded
xcat-ws.conf sends /xcatws and /xcatwsv2 to https only when mod_rewrite is
loaded. Without that module the aliases run the REST CGI on any port.

An IfModule !mod_rewrite.c block now answers 403 for both aliases.
RedirectMatch comes from mod_alias, which the ScriptAlias lines of the
same file already require. Other paths, such as /install, are not changed.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 14:03:14 -03:00
Daniel Hilst 469e108ff4 Merge upstream master into fix/xcat-ws-conf-module-path
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 13:50:47 -03:00
Daniel Hilst 4f6938c6b2 test(xcat-core): check the REST aliases when mod_rewrite is not loaded
xcat-ws.conf keeps its https redirect inside an IfModule mod_rewrite.c
block. No test starts Apache with the fragment, so nothing checks what the
REST aliases answer when that module is not loaded.

wsapi_apache_access.t starts a private Apache on a free port with the
fragment from the source tree. Without mod_rewrite it expects 403 from
/xcatws and /xcatwsv2. With mod_rewrite it expects the 302 to https. In
both cases /install is still served.

The Debian packages do not install xcat-ws.conf, so the GitHub action runs
the test from the source tree after install. The installed copy skips.

The test fails without mod_rewrite: both aliases answer 200 and run the CGI.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 13:38:52 -03:00
Daniel Hilst 4df004ee2d Merge pull request #7857 from VersatusHPC/test/r26-redaction-behavior
test(xcatd): exercise loaded password redaction
2026-10-05 11:27:27 -03:00
Daniel Hilst 74d5184963 fix(xcat-core): xcat-ws.conf names a SUSE module path and never matches its package
`rpm -V xCAT-server` reports /etc/httpd/conf.d/xcat-ws.conf and
/etc/apache2/conf.d/xcat-ws.conf changed on every EL, openEuler and SUSE
management node, for the life of the install. %install shipped the Apache 2.2
fragment as the payload, and %post replaced it with the Apache 2.4 fragment
whenever httpd, apachectl or apache2ctl reported 2.4. Every supported
distribution runs Apache 2.4, so the file on disk never matched the package
digest. The drift is a permanent false positive for anyone who verifies an
installed xCAT before trusting it.

Both fragments also began with
`LoadModule rewrite_module /usr/lib64/apache2-prefork/mod_rewrite.so`. That
file exists only on SUSE under the prefork MPM. Apache tolerates it on EL and
openEuler because conf.modules.d loaded mod_rewrite first, and logs AH01574;
where the module is not loaded first, the missing file stops Apache from
starting.

xcat-ws.conf.apache22 and xcat-ws.conf.apache24 are replaced by one
xcat-ws.conf that serves both generations: the redirect sits behind
<IfModule mod_rewrite.c>, and the authorization directives behind
<IfModule mod_authz_core.c> and its negation. %install copies that one file to
both conf.d paths and %post no longer names them, so the payload is the final
file. %post runs a2enmod rewrite where a2enmod manages modules, which is how
SUSE gets the module the removed LoadModule used to pull in.

xCAT-test/unit/wsapi_apache_conf_portable.t fails 22 of its 30 assertions
without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 11:25:38 -03:00
Daniel Hilst ff9b74805c test(xcat-core): capture the xcat-ws.conf module path and the rpm -V drift
`rpm -V xCAT-server` reports /etc/httpd/conf.d/xcat-ws.conf and
/etc/apache2/conf.d/xcat-ws.conf changed on every EL, openEuler and SUSE
management node, for ever. %install ships the Apache 2.2 fragment as the
payload and %post replaces it with the Apache 2.4 fragment on any server that
reports 2.4, which is every supported distribution.

Both fragments also start with
`LoadModule rewrite_module /usr/lib64/apache2-prefork/mod_rewrite.so`. That
file is absent on EL and openEuler, and absent on SUSE under any MPM but
prefork. Apache skips the line today only because the distribution loaded
mod_rewrite first, and logs AH01574.

The new test parses each shipped fragment into directives and enclosing
sections, and the spec into its scriptlet sections. It asserts the fragment
declares no LoadModule and no absolute path, that the redirect and both
generations of the authorization directives sit behind their own <IfModule>
guard, and that %post never names the installed conf.

22 of its 30 assertions fail on this commit.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 11:25:38 -03:00
Daniel Hilst 7a2cbf66f6 test(xcat-core): two negative checks in the persist test cannot fail
bash ignores errexit for a command inverted with "!", so a "! grep" that is not the last line of
a bats test never fails it. The ifcfg test wrote two of them, and the first could not report a
[user] section appearing in an ifcfg profile.

Both now call refute_grep, the helper that exists for this. Restoring the keyfile-only write
fails that test on both assertions.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 11:25:10 -03:00
Daniel Hilst 46fd59f26d fix(xcat-core): a nicextraparams key never reaches an ifcfg NIC profile
confignetwork_secondarynic_nicextraparams_updatenode fails on openEuler 20.03sp4, 22.03sp4 and
24.03sp4 and on el8, while its sibling confignetwork_secondarynic_updatenode passes everywhere.
The only failing check is CONNECTED_MODE=yes, twice. The run log shows configeth receives the
value -- "array_nic_params 0=CONNECTED_MODE=yes" -- and the profile NetworkManager reports,
/etc/sysconfig/network-scripts/ifcfg-xcat-ens4-1, does not contain it afterwards.

configeth writes nicextraparams in configipv4 and then activates the connection. The comment on
the late persistence block states why that write does not survive: the nmcli con reload/up in the
restart phase re-serializes the connection from NetworkManager's in-memory model and drops
anything NetworkManager does not model. The block repairs it after activation, but its gate
requires xcat_uses_nm_keyfile, so it runs for a keyfile store only. el8 never reaches that test,
and openEuler reaches it and fails it because NetworkManager there reports an ifcfg file. Those
are the two families on the ifcfg path and the two that fail.

The block now runs for both stores. xcat_nm_conn_file asks NetworkManager which file holds the
connection rather than composing the name, because NetworkManager suffixes it when a file of the
plain name exists. xcat_persist_nic_extra_param writes the key as the profile spells it -- under
[user] with an xcat. prefix in a keyfile, plain in an ifcfg file -- and appends only when the key
is absent.

xcatlib_nic_extra_param_persist.bats covers both stores with nmcli stubbed. Two behavioural
mutants were run against it: restoring the keyfile-only behaviour fails the three ifcfg
assertions and leaves the keyfile ones passing, and composing the filename fails only the
resolution assertion.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 11:25:09 -03:00
Daniel Hilst 871f8362f9 fix(xcat-core): the openEuler ppc64le core build cannot write its own resultdir
mock refuses every package of the openeuler-24.03-ppc64le target with
"Could not create dir dist/openeuler-24.03-ppc64le/rpms/SRPMS/.
Error: [Errno 13] Permission denied: 'dist'", so the target builds nothing.

mock 6.8 reloads its uid manager from chrootuid, so chrootuid now also owns
--resultdir and the three log files mock writes beside it. buildrpms.pl passes a
relative resultdir under a source tree owned by root. xcat-dep's
openeuler-24.03-ppc64le.cfg declares chrootuid 1000, for the native dependency
prerequisites that need a non-root build identity, and mock_config_text copied the
target configuration verbatim.

mock_config_text now assigns chrootuid 0 after the inherited lines. An xcat-core
rpm build has no declared non-root identity, and every other target already builds
as root because no other configuration sets the option. The inherited declaration
stays in the file, so the chroot still sees what xcat-dep shipped.

chrootgid is left alone. mock creates the in-chroot mock group with it, and
`groupadd mock -g 0` fails because the root group already holds gid 0: pinning both
took the target from a resultdir failure to "mock --init failed" on all fourteen
packages. root creates the resultdir whatever group it carries.

buildrpms_mock_resultdir_uid.t fails 2 of 11 without this change.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 11:24:38 -03:00
Daniel Hilst 0491c5b733 test(xcat-core): the openEuler ppc64le core build cannot write its own resultdir
Every package of xcat-core-build-openeuler24.03-ppc64le #1 died before rpmbuild
started:

    ERROR: Could not create dir dist/openeuler-24.03-ppc64le/rpms/SRPMS/.
    Error: [Errno 13] Permission denied: 'dist'

30 such lines, 0 srpms. buildrpms.pl passes a relative --resultdir inside a source
tree owned by root, and mock 6.8 creates that directory as chrootuid.
openeuler-24.03-ppc64le.cfg declares chrootuid 1000 for the native dependency
prerequisites, and createmockconfig copied the target configuration verbatim, so
the core build inherited a uid that cannot write there. No openEuler x86_64
configuration declares one, which is why only the ppc64le target fails.

createmockconfig had no unit test because it built its text inline and wrote it
straight to /etc/mock. The rendering moves to XCAT::BuildUtils::mock_config_text,
which takes the base text and returns the rendered text; the script keeps the two
file operations.

buildrpms_mock_resultdir_uid.t drives it directly and fails 2 of its 11 checks, both
on the uid the rendered configuration carries.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
2026-10-05 11:24:38 -03:00
Daniel Hilst d7c32d2689 Merge pull request #7885 from VersatusHPC/feat/ipxe-netboot
feat(netboot): boot x86 nodes with the upstream iPXE loader
2026-10-05 11:15:47 -03:00