An x86 client without a node definition, such as a node in discovery,
now gets xcat/ipxe/i386/undionly.kpxe for BIOS and
xcat/ipxe/x86_64-sb/snponly-shim.efi for UEFI. Once it reports the iPXE
features of its path, it gets the Genesis script of its network from
xcat/ipxe/nets, which mknb writes. ISC and Kea apply the same test. As
for xNBA, neither backend names a loader that the local TFTP directory
lacks, or the second stage that the loader would fetch.
Kea gave every x86 client its first-stage loader from the global
classes, which now name the upstream loader. An xnba node therefore
carries its own first-stage classes, which name xcat/xnba.kpxe and
xcat/xnba.efi when the local xNBA BIOS file exists, as its ISC host
statements do. An ipxe node carries its own classes for the upstream
loader, because an upgrade keeps the global classes of an older
makedhcp -n until the next makedhcp -n. The ISC host statements of a
node do not change.
The next change gives unknown x86 clients the upstream iPXE loader, and
an xnba node carries its own first-stage classes in Kea. These checks
describe the xNBA loader for unknown clients, so they go: the files,
tests and architectures of the global x86 classes, the network classes,
the Etherboot class, the UEFI class of the proxyDHCP case, and the xNBA
branches and missing-loader cases of the ISC x86 lines.
The node class checks of an xnba node and of an ipxe node compare only
the second-stage classes, which do not change. The test after the change
covers the new loader.
dhcpd keeps the host statements that makedhcp gives it through OMAPI in
dhcpd.leases, where it saves them without parentheses, and reads them
back when it restarts.
The lease test stores the statements of netboot=ipxe nodes through OMAPI
in a private network namespace, checks the saved leases with dhcpd -t,
and restarts dhcpd with them. The configuration test checks the iPXE
feature declarations of the ISC header with dhcpd -t.
start_daemon can now keep the identity of the caller, and the
integration case expects six files.
The helpers that start, wait for and stop a DHCP daemon lived in the
Kea smoke test. The ISC lease test and the packet test need them too.
They move to XCAT::Test::DHCP in integration/lib, which the xCAT-test
packages install with the tests. The smoke test loads them from there
and behaves as before.
The Kea classes and the ISC host statements of a netboot=ipxe node name
the ipxe-xcat loaders without a local file. The node script goes to a
client with HTTP, bzImage and PXE on BIOS and HTTP and EFI on UEFI, and
the first-stage classes negate the same test. A SAN node needs iSCSI as
well. An xnba node beside an ipxe node keeps its classes. dhcp.pm gives
node classes to ipxe and xnba nodes, with their method and SAN flag. Kea
defines option 175, the ISC header declares every feature that a host
statement tests, and no host statement depends on parentheses: each
feature test sits inside its architecture test.
makedhcp gives a netboot=ipxe node xcat/ipxe/i386/undionly.kpxe for
BIOS and xcat/ipxe/x86_64-sb/snponly-shim.efi for UEFI. That shim, which
Microsoft signs, loads snponly.efi from its own directory, so the node
also boots with UEFI Secure Boot on: the firmware does not load
snponly.efi directly, as only the iPXE Secure Boot CA signs it.
The node gets its boot script from xcat/ipxe/nodes only when it reports,
in option 175, the iPXE features that the script needs: HTTP, bzImage
and PXE for BIOS, HTTP and EFI for UEFI. A SAN node also needs iSCSI.
Every other client of the node first gets the loader above. xNBA sends
the same option, but xCAT recognizes xNBA by its user class, and the
upstream loader sends the user class of a firmware iPXE. The upstream
loader does not have to be in the local TFTP directory, because a node
can load from another TFTP server.
ISC applies the test in the host statements of the node, and nests each
feature test inside its architecture test: dhcpd saves a host statement
in dhcpd.leases without parentheses, and omshell reads only 1023 bytes
of the line that sets it. Kea applies it in the classes of the node,
which carry their own first-stage loader and the purpose ipxe-boot. As
for an xnba node, a node in state boot or iscsiboot gets no boot file
unless it boots from SAN. The statements and classes of netboot=xnba and
netboot=pxe nodes do not change.
The upstream iPXE loader of an unknown x86 client will fetch its Genesis
discovery script from xcat/ipxe/nets. mknb writes the same BIOS, UEFI
and elilo scripts there as under xcat/xnba/nets. xcat/xnba/nets keeps
them for a server whose DHCP configuration still names it.
nodeset through the ipxe plugin writes the BIOS, UEFI, elilo and
pxelinux files of a node under xcat/ipxe/nodes, and the scripts name
that directory. An xnba node still gets xcat/xnba/nodes. SvrUtils reads
the nodeset state of both. An x86_64 osimage accepts netboot=ipxe, and
the noderes.netboot description lists it.
xCAT boots x86 nodes through iPXE with netboot=xnba, which names the
xNBA fork that xCAT retires. netboot=ipxe is the method for the upstream
iPXE loaders of the ipxe-xcat package.
The ipxe plugin runs the xnba code, with the boot scripts under
xcat/ipxe/nodes instead of xcat/xnba/nodes. nodeset stat, the osimage
check of nodeset and rinstall, and the install check of Postage accept
the new value. The noderes.netboot description lists it and marks xnba
deprecated. The z/VM and FSM builds of xCAT-server leave the ipxe plugin
out with the xnba and pxe plugins. netboot=xnba does not change, and
makedhcp does not serve the new method yet.
lookupNetboot lists the netboot methods that an osimage accepts. The
x86_64 case compared the whole list, so any new x86 method broke it.
It now checks that xnba, pxe and grub2 are accepted, in any order.
A local dhcpd, and an external one without netboot=ipxe nodes, get no
check. An external dhcpd that returns the check host updates every
node, after one omshell run that creates the host, whose statement
tests every iPXE feature option, and one that reads it back and removes
it. The first run opens no host, and each run creates a host with its
own name and address.
A rejected statement, a run cut short or without a reply, a lost
connection and the host of another run leave the netboot=ipxe nodes
unchanged, and the error names the server and the nodes. The replies
are those of dhcpd 4.4.
makedhcp does not write the configuration of a DHCP server that
site.externaldhcpservers names, so an upgrade leaves it without the
iPXE feature options. OMAPI removes a host before it adds it again, so
a host statement that such a server rejects loses the reservation of
the node.
Before it updates netboot=ipxe nodes on that server, makedhcp creates a
host of its own whose statement tests every iPXE feature option, reads
it back in a second omshell run, and removes it. Only the server can
return the address of that host, so the nodes are updated only when it
does. Otherwise makedhcp reports the server and leaves the reservations
of those nodes unchanged. Other nodes and a local server get no check.
Each run uses its own host name and address, as other xCAT servers can
check the same server at the same time. The check opens no host before
the create, because the omshell of Ubuntu 20.04 and 22.04 can hang on a
failed open.
makedhcp adds the missing ISC declarations after the gpxe option space,
and the missing Kea definitions after the existing ones, once. Indented
ISC declarations and declarations with more blanks count. An ISC
configuration without the gpxe space gives an error and stays as it is,
and so does a Kea definition of option 175 without the gpxe
encapsulation, and makedhcp then writes nothing.
makedhcp writes the ISC configuration and restarts dhcpd at once. When
the configuration declares no gpxe option space, or makedhcp cannot
write the file or restart dhcpd, it reports the error and changes no
subnet or host. A marker beside the configuration stays until a restart
succeeds, so the next run restarts dhcpd before it changes a host.
Without a dhcpd.conf, or with one that xCAT did not write, it gives no
error and goes on to write a new configuration. Kea restarts to load the
definitions, also when the Control Agent applies the host reservations.
Every option code stays a number: JSON::XS writes a number that Perl has
used as a string as a JSON string, and Kea rejects it. kea-dhcp4 -t
checks an upgraded and a current configuration that makedhcp writes
back.
A package upgrade keeps the DHCP configuration of an older makedhcp -n,
which does not declare the iPXE feature options. makedhcp without -n
then adds the rules of the upstream loader to it. dhcpd rejects a subnet
or an OMAPI host statement that tests an undeclared option, and Kea
never finds a sub-option of option 175 without its definition.
makedhcp without -n now adds the missing declarations to an ISC
configuration that xCAT wrote, after its gpxe option space, writes it
and restarts dhcpd before it changes a subnet or a host. Declarations
with any blanks count. It stops when the configuration declares no gpxe
option space, or when it cannot write the file or restart dhcpd, because
OMAPI removes a host before it adds it again. A missing configuration,
or one that xCAT did not write, still gets a new one, which declares the
options. A marker file beside the configuration records a restart that
has not happened yet, so the next run restarts dhcpd before it changes a
host when a run stopped before the restart or the restart failed.
It adds the missing definitions to an existing Kea configuration, and
Kea restarts, also when the Control Agent applies the host reservations.
A site definition of option 175 without the gpxe encapsulation stays,
because option data can name it, and makedhcp stops with an error that
names the fix.
The rules for the upstream iPXE loader test the feature indicators that
iPXE sends as sub-options of option 175: iSCSI, HTTP, bzImage, PXE and
EFI. Declare them in the gpxe space of the ISC header. Define option 175
and the indicators in Kea, which does not find a sub-option without its
definition.
The declarations only decode the options. OMAPI keeps host statements in
dhcpd.leases, and makedhcp -n restarts dhcpd before -a rewrites them, so
the header declares them whether or not a node uses them. A statement
written for a node on the upstream loader must still parse after the
node moves back to xNBA.
Hold the Kea classes, the ISC x86 lines, and the ISC host statements of
each netboot=xnba and netboot=pxe branch to the exact text the renderers
produced before the x86 loader became selectable.
dhcp.pm wrote the ISC host statements of netboot=xnba and netboot=pxe
nodes inline. Each Kea class builder named the xNBA files and the xNBA
user-class test on its own.
Move the host statements into isc_node_boot_statements. Give every ISC
and Kea builder its loader files and second-stage tests from x86_loader.
The rendered statements, lines and classes do not change.
kea_node_client_classes_for_nodes answered { classes, noip } when it
could not open the noderes or mac table, and left out the localboot
list that kea_sync_node_client_classes reads. makedhcp then died with
"Can't use an undefined value as an ARRAY reference".
Return an empty localboot list as well.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
kea_node_client_classes_for_nodes returns early, without a localboot
list, when it cannot open the noderes or mac table.
kea_sync_node_client_classes then dereferences that missing list and
dies with "Can't use an undefined value as an ARRAY reference".
dhcp_kea_ddns_deferral.t takes this path, so the unit tests fail on
master since #7830 added the localboot list.
Check the early answer and the sync with both tables unavailable.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
reg_linux_diskfull_installation_flat never finishes on openEuler. The install completes, the
postscripts run, and then the node reboots into the installer again and repeats, so the case waited
an hour and the node stayed at status=installing.
post.xcat.ng ends with updateflag.awk, the call its own comment calls the one that must always run
to prevent infinite installation loops. It passed $MASTER, a hostname. The anaconda %post chroot on
openEuler has no /etc/resolv.conf and no management node entry in /etc/hosts, so gawk cannot open
the socket. From the node's own /var/log/xcat/xcat.log:
awk: /xcatpost/updateflag.awk:15: warning: remote host and port information
(xcat58-mn, 3002) invalid: Name or service not known
updateflag.awk: Retrying flag update
It retries ten times, gives up, and the status is never sent. Nothing reports it: the retry message
goes to logger, and a %post chroot runs no rsyslog.
The same script already uses $MASTER_IP for all 36 of its other callbacks, and the kickstart sets it
to the same host: MASTER_IP=192.168.58.1, MASTER=xcat58-mn. All six updateflag calls now use the
address, so none of them depends on a resolver the node does not have.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
xCAT-test/debian/install did not list lib/xCAT/Test/OS.pm, so the
Debian package shipped xcattest without the module it loads, and
xcattest stopped at startup with "Can't locate xCAT/Test/OS.pm in @INC".
Install the module to opt/xcat/lib/perl/xCAT/Test, as the RPM spec does.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
xcattest loads xCAT::Test::OS from /opt/xcat/lib/perl. xCAT-test.spec
installs it, but xCAT-test/debian/install does not, so xcattest on an
Ubuntu management node dies at startup with "Can't locate
xCAT/Test/OS.pm in @INC".
Check that the RPM spec and the Debian install list both ship every
module under xCAT-test/lib/xCAT. The Debian check fails.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
xcattest reports "Test case <name> has an invalid OS option - Linux" and then
"There is no valid case to run", so every case is skipped on openEuler.
Recorded on an openEuler 24.03 LTS SP4 management node with xCAT 2.20.0: both
flat provisioning cases were rejected and the run measured nothing.
Two causes, both in the os: comparison in xCAT-test/xcattest. get_current_os
takes the /etc/os-release branch, finds no sles, and falls off the end of that
branch, so it returns the exit status of the failed grep, 256, which names no
distribution. And a case marked os:Linux expands to exactly rhels, sles and
ubuntu, so openEuler would be rejected even by a correct get_current_os.
Both halves move into xCAT::Test::OS. xcattest finds it beside itself and the
package installs it at <prefix>/lib/perl. current_os takes a path prefix, so a
test describes a system by writing release files into a scratch tree. openEuler
is named in both halves and nothing else changes.
xCAT-test/unit/xcattest_os_selection.t covers it. Removing openeuler from
linux_aliases fails two checks, and removing the openEuler branch from
current_os fails three. A further case gives a root both /etc/redhat-release
and an openEuler /etc/os-release and asserts rhels10, so the precedence is
named: openEuler ships neither that file nor /etc/lsb-release.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
wget asks for the root image as //install/..., so the leading slash repeats.
The path filter matched a single leading slash and did not count those
requests. A service node that served only the root image would therefore read
as having served no boot payload.
The filter now accepts a repeated leading slash. The bats cases come from
fix/service-node-ub, where a real Ubuntu service node logged one //install
request beside 272 /install and 8 /tftpboot ones. Both new cases fail with the
single-slash filter.
This brings the file level with fix/service-node-ub, so the two branches no
longer carry different versions of the same check.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
fix/service-node-el fixed the management-node guard as commit 0f708b96a, with the same
correction this branch made: the log must hold lines, not gain them. The two differ
only in the comment and in the error message, so the file no longer merges as one
change.
The wording here now matches fix/service-node-el. The remaining difference in this file
is the doubled-slash path filter, which that branch does not carry.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
local_logs added XCAT_HTTPD_ACCESS_LOG to the list of candidate logs and then
read the system paths as well. On a build host that runs apache, the check
counted the host's own /var/log/apache2/access.log beside the file the test
pointed at, so a test could not control what it measured. The empty-log case
read 64 lines it did not write.
An explicit XCAT_HTTPD_ACCESS_LOG now replaces the search instead of extending
it. Production behaviour is unchanged: nothing sets that variable there.
Without this change the bats case for an empty management-node log fails on a
host that serves apache, and passes on one that does not.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit bcb4a77f1a)
check_provisioning_source.sh --baseline wrote one message for two conditions:
"no access log to baseline on ${MN_BASE:+$SN}${MN_BASE:-$MN}". When the management
node has a log and the service node does not, the second expansion returns the
management node's baseline spec, not a host name. On xcat42 the message read "no
access log to baseline on nosuchnode-xyz/var/log/httpd/access_log:881". That is the
message an operator reads when xdsh cannot reach the service node, so it has to name
the host that has no log.
Each condition now has its own test and its own message.
check_provisioning_source.bats covers the service-node condition. The case also
asserts the management node's log path is absent from the message, because the node
name alone matches the old text as a substring.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit 89ac4558a0)
local_logs added XCAT_HTTPD_ACCESS_LOG to the list of candidate logs and then
read the system paths as well. On a build host that runs apache, the check
counted the host's own /var/log/apache2/access.log beside the file the test
pointed at, so a test could not control what it measured. The empty-log case
read 64 lines it did not write.
An explicit XCAT_HTTPD_ACCESS_LOG now replaces the search instead of extending
it. Production behaviour is unchanged: nothing sets that variable there.
Without this change the bats case for an empty management-node log fails on a
host that serves apache, and passes on one that does not.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
check_provisioning_source.sh --baseline wrote one message for two conditions:
"no access log to baseline on ${MN_BASE:+$SN}${MN_BASE:-$MN}". When the management
node has a log and the service node does not, the second expansion returns the
management node's baseline spec, not a host name. On xcat42 the message read "no
access log to baseline on nosuchnode-xyz/var/log/httpd/access_log:881". That is the
message an operator reads when xdsh cannot reach the service node, so it has to name
the host that has no log.
Each condition now has its own test and its own message.
check_provisioning_source.bats covers the service-node condition. The case also
asserts the management node's log path is absent from the message, because the node
name alone matches the old text as a substring.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
check_provisioning_source.sh required the management node's httpd access log to gain
lines after the baseline. The three hierarchy cases take the baseline after
SN_setup_case has provisioned the service node. After that point a correct hierarchical
provision leaves the management node serving nothing, so its log does not grow. On the
xcat42 EL9 cell the service node served the compute node 252 boot-payload requests and
the management node served 0, and the check still reported "no httpd access log with
new entries could be read on xcat42-mn-dhilst".
reg_linux_diskless_installation_hierarchy failed for that message.
The guard now requires the log to hold lines, not to hold new ones. An empty log still
fails, because it makes "the management node served nothing" a property of the file
instead of a measurement.
check_provisioning_source.bats asserted the removed behavior in "a management node log
with nothing new fails the check instead of reading as silence". That case now asserts
the opposite, and a second case covers the empty log. Both fail against the unfixed
script.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
On a new Kea management node, makedhcp -n defers DDNS until makedns -n
writes the key. makedhcp -a then applied the D2 settings to the fresh
intents, but saved the loaded configurations, which had no dhcp-ddns.
It also wrote no kea-dhcp-ddns.conf, so DNS updates stayed off.
When DDNS is on and the loaded DHCPv4 configuration has no dhcp-ddns,
makedhcp -a now copies the D2 settings into the loaded DHCPv4 and DHCPv6
configurations, writes the D2 configuration and, when enabled, the
Control Agent configuration. It then enables and restarts the Kea
services.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
On a new Kea management node, makedhcp -n defers DDNS because no key
exists. After makedns -n writes the key, makedhcp -a keeps the DHCPv4
configuration without dhcp-ddns and writes no kea-dhcp-ddns.conf, so
DNS updates stay off.
The test runs makedhcp -n without a key, adds the key, runs
makedhcp -a, and checks the rendered DHCPv4 and D2 configurations.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
enable_repo_commands chose subscription-manager from the vendor id and the presence of the
binary. An unregistered RHEL node has both, so the postscript ran
`subscription-manager repos --enable`, the command failed for want of a registration, and only
the fallback to `dnf config-manager` enabled the builder repository. The log named the
repository, not the registration.
The decision now takes the registration state. registered_with_subscription_manager reads the
exit status and the output of `subscription-manager identity`, which the postscript runs, and
enable_repo_commands emits the subscription-manager command only for a registered node. A
Foreman, Katello or Red Hat Satellite client registers through subscription-manager, so the same
path covers it, and the vendor id no longer decides. uses_subscription_manager is removed with
its caller.
service_node_artifacts_el.t asserts the probe against the registered and the unregistered output
of subscription-manager 1.30.12, against a missing binary, and against a call without root
privilege. It also asserts that an unregistered node runs no subscription-manager command.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
On the Ubuntu 24.04 hierarchy cell the check reported the right counts and then
failed: "xcat22-sn served xcat22-cn 277 boot-payload request(s)", "xcat22-mn-dhilst
served xcat22-cn 0", and then "no httpd access log with new entries could be read on
xcat22-mn-dhilst". The guard required the management node log to gain lines after the
baseline. It does not: the management node provisions the service node in
SN_setup_case, before the baseline the hierarchy case takes, and it is then idle. Its
silence is the result the check exists to find.
The guard now asks that the log hold at least one line, which is what makes a count of
0 mean something, and no longer asks for activity in the measured window.
The path filter also missed a doubled leading slash. The compute node fetches the root
image with wget as //install/netboot/<os>/<arch>/compute/rootimg.cpio.gz, which the
service node logged and the filter did not count.
check_provisioning_source.bats covers both. The four cases added in the commit before
this one fail without this change.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
check_provisioning_source.bats held a case that required the check to FAIL when the
management node logs nothing after the baseline. That is the hierarchical result, not
a broken log: the management node provisions the service node before the baseline and
then serves the compute node nothing. The suite passed 14 of 14 while the check could
not pass on a real cluster.
Two more cases cover the path filter. The compute node fetches the root image with
wget from a URL that carries a double slash, so the path reaches the log as
//install/netboot/..., and the filter matched neither direction: the request counted
as no boot payload on the service node, and a flat provision that served it went
unreported.
All four cases fail against the current script.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
check_provisioning_source.sh counted every request the compute node had ever
made, for any path. Both directions were wrong. A flat run left
management-node requests for the same address, so a later hierarchical run
read them as its own and failed. A service-node entry from an earlier run, or
a 404 for /favicon.ico, satisfied the positive check without any boot payload
being served.
The script now takes a baseline. --baseline records how many lines each access
log holds on the management node and on the service node, before provisioning,
and the check counts only lines after that point. It counts only requests
under /install or /tftpboot, which are the trees httpd serves a boot payload
from. A log shorter than its baseline was rotated, so it is read from its
first line. Without a baseline the check refuses to answer instead of reading
the whole log. The three hierarchy cases call --baseline before nodeset.
check_provisioning_source.bats covers both regressions: a management-node
request before the baseline no longer fails the run, a service-node request
before the baseline no longer satisfies it, and a request that carries no boot
payload does neither. Removing the baseline comparison fails the first two.
Removing the path filter fails the other two.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
(cherry picked from commit d6f25640b1)
check_provisioning_source.sh counted every request the compute node had ever
made, for any path. Both directions were wrong. A flat run left
management-node requests for the same address, so a later hierarchical run
read them as its own and failed. A service-node entry from an earlier run, or
a 404 for /favicon.ico, satisfied the positive check without any boot payload
being served.
The script now takes a baseline. --baseline records how many lines each access
log holds on the management node and on the service node, before provisioning,
and the check counts only lines after that point. It counts only requests
under /install or /tftpboot, which are the trees httpd serves a boot payload
from. A log shorter than its baseline was rotated, so it is read from its
first line. Without a baseline the check refuses to answer instead of reading
the whole log. The three hierarchy cases call --baseline before nodeset.
check_provisioning_source.bats covers both regressions: a management-node
request before the baseline no longer fails the run, a service-node request
before the baseline no longer satisfies it, and a request that carries no boot
payload does neither. Removing the baseline comparison fails the first two.
Removing the path filter fails the other two.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>