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>
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>
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>
kea_build_ddns_intent returned the deferral under a deferred key. No other
xCAT code uses that key: dhcp.pm reports through error, warning, node and
data, and makedhcp already passed this message to the callback as a warning.
The intent hash now carries the message under warning, so one name describes
it from the hash to the callback. Behaviour does not change.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The comment stated the xcatconfig default and then repeated the reason for the
change, which the commit message already carries. Keep the condition only.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
makedhcp -n fails on a new management node that uses the Kea backend:
Error: Unable to find DDNS key material for Kea D2. Run makedns with
dnshandler=ddns first.
xcatconfig writes site.dnshandler=ddns on every new installation, so
kea_ddns_enabled reports DDNS on, and kea_build_ddns_intent then requires
/etc/xcat/ddns.key. Only makedns -n writes that file. The ISC backend reads no
key, so an ISC management node runs makedhcp -n without one. The Kea backend
plan states that basic DHCP and PXE support must not depend on DDNS.
kea_build_ddns_intent now reports a deferral instead of an error when it finds
no key material. kea_apply_ddns_intent attaches the D2 connection only when a
key exists, and returns the deferral for makedhcp to print as a warning. A
management node with key material gets the same configuration as before.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The comments added with the Ubuntu fixes carried the bug report and its
consequences: what a compute node stops at, what named answers to every query
once its working directory is unwritable, and that a failed export does not fail
the service node. The comment rules keep the invariant in the source and put the
symptom and the chain in the commit.
Each is cut to the fact the code cannot show: that the resolv.conf a
systemd-resolved host publishes holds a stub pointing back at this named, that
named must be able to write the directory it drops privileges into, that apt
refuses an unsigned repository, and that re-exporting a mount needs an fsid.
service.subiquity.tmpl keeps its header, which is identical to the sibling
compute template and should stay that way.
No executable line changes.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
nodepurge removes the autoinstall configuration of each node it deletes. The
cleanup loop was inline in the nodepurge sub of profilednodes.pm, which no test
can load, so the loop moves to xCAT::ProfiledNodeUtils->remove_node_config_files
with its behaviour unchanged.
nodepurge_autoinst_cleanup.t drives that routine against a scratch directory. It
fails here: the Subiquity node keeps its directory, and the preseed file and the
.pre and .post scripts are removed.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
After `apt-get remove`, dpkg reports a package as "deinstall ok
config-files". uninstall_xcat_completely() selected packages with
installed_packages(), which accepts only "install ok installed". So
`go-xcat completely uninstall` after `go-xcat uninstall` did not purge
the xCAT packages, and their configuration files stayed on the node.
uninstall_xcat_completely() now uses purgeable_packages(). On Debian it
also accepts packages whose state ends in "ok config-files". On rpm
systems it is installed_packages(). uninstall_xcat() keeps the
installed-only filter.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
A Windows UEFI install deferred to proxyDHCP gets boot-file-name "" in its
Kea reservation. Kea treats the empty string as not specified, so the
subnet classes still match on architecture, and xcat-uefi-x64 offers
xcat/xnba.efi. The firmware then boots xNBA instead of asking the
proxyDHCP daemon on port 4011.
kea_node_client_classes_for_nodes now also puts the MAC of a proxyDHCP
node in xcat-localboot, which every class that names a boot file already
excludes. The per-node class that sets option 60 to PXEClient names no
boot file and still matches.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
go-xcat runs internal_setup and the main program at file scope. A test
that sources the script to read its package lists or call its functions
starts the installer, so the tests extracted function bodies with awk and
evaluated them instead.
When go-xcat is sourced, it now skips internal_setup and returns before
the main program. A direct run and a run from a pipe do not change.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
Master fixed debuild-xcat-genesis-base and added a bats test for it. The
branch deleted that script as unused. The merge keeps the script and
moves it to xCAT-genesis-base with the other Genesis base files.
Master also stages verify-genesis-payload for the spec %install check.
stage_genesis_base_sources() now stages it too, and
genesis_base_sources_staged.t expects it in the tarball.
The workflow, builds.rst and xcat_probe_package_payload.t take the
master version.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
mknb wrote BOOTIF=01-${netX/machyp} into the BIOS Genesis script.
machyp is an xNBA setting, and stock iPXE expands it to an empty string.
Without the boot MAC, the legacy Genesis stops with "Unable to find boot
device" after at least 10 minutes. The OpenEmbedded Genesis fails at once
with BOOT_INTERFACE_NOT_FOUND.
Use ${netX/mac:hexhyp}, as the UEFI Genesis script and xnba.pm do. xNBA
expands both settings to the same value, so boot with xNBA is unchanged.
The install monitor holds the later connections for a node whose handler
is still running, and forks the next one when it reaps that handler.
SIGCHLD is what brings the parent back to look: it interrupts the accept.
A handler can exit after the parent checks its queue and before the
accept begins. The signal is then handled where there is no accept to
interrupt, and the parent blocks in accept with a connection already
queued and ready to run. That connection waits until some other node
calls in. A single node retrying on its own waits until it times out.
do_installm_service now waits through wait_for_installm_connection, which
selects on the listening socket. The wait is bounded by
$installm_wakeup_seconds while connections are queued, so the parent
looks at its queue again instead of waiting for another client. An idle
monitor with an empty queue still waits without a bound, because a
handler that exits then leaves nothing to do.
The new case asserts the wait ends on its own bound with nothing to
accept, and ends at once when a connection is already there. It fails
when the bound is ignored.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
Merge current master into the openEuler support branch. Keep native
kernel, DHCP, locale and timezone requirements with the upstream payload
verifier and EL10 package paths. Preserve signed openEuler installation.
Update the native fixtures to check the merged payload contract.
The ordering between two requests for one node was a chain of pipes: each child
held the write end and the next child for that node read the previous one to end
of file. End of file there means the previous process is gone, not that its work
finished, so a child that died released the one behind it -- and released the
wrong one, because each child waits on its immediate predecessor rather than on
the request actually in flight. The fork-failure path closed the predecessor and
served the request in line without waiting at all.
The parent now owns the order. %installm_busy names the handler serving a node,
%installm_queue holds the connections accepted for that node meanwhile, and the
next one is forked when the handler ahead of it is reaped. A handler that dies
cannot release the one behind it, and the fork-failure path has nothing to fall
back over, because it is reached only when the node has no handler.
Three other changes the same design makes possible or necessary:
- The answer to a destiny advance now follows the advance. Every other request
is still answered before it runs, because its result does not change what
the node does next. Holding one node costs no other node anything now, and
it lets the node retry an advance whose handler died -- which the old order
could not, because "done" was already on the wire.
- The monitor drains its handlers before it exits. Without this a restart
orphans them into the systemd service cgroup, where anything still running
at TimeoutStopSec is killed after its answer was already sent.
- SIGCHLD is caught, so a handler exiting interrupts accept and the parent
comes back to look for a connection queued for that node.
The pid file path is a variable, so the test can point the lifted routine at a
scratch file instead of the one a restarting xcatd reads to tell the running
monitor to let go of the port.
xcatd_install_monitor_concurrency.t grew the cases for all of it. Four
mutations, each caught by one assertion: forking every connection at once turns
the ordering case red; answering a destiny advance before the plugin turns the
release case red; removing the drain turns the stand-down case red; and leaving
the emptied queue entry behind turns the leak case red. The full unit suite is
194 files, 5662 tests, green.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The step that fills lib/firmware in the Ubuntu netboot initrd asked modinfo
about $rootimg_dir/$module and looked a firmware name up under lib/firmware.
The copy step beside it takes a module from $customdir or $pathtofiles first,
and the kernel looks a firmware name up under updates/<kernel>, updates/,
<kernel>/ and lib/firmware. So a custom driver reached the initrd with no
firmware, even when the root image carried it, and a firmware override was left
out of the initrd altogether.
initrd_firmware_files now takes the module directories the copy step searches
and the kernel release. It resolves each module in that order before asking
modinfo, and keeps every firmware file that exists in the four directories the
kernel searches, so the override still wins on the node.
ubuntu_genimage_initrd_firmware.t covers both: its two new cases are red on the
commit before this one.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
The first subiquity error command redirects into /run/#HOSTNAME#-logs.tar. A
test can shadow tar, but not the redirection: the shell opens that file
whether or not tar runs, so the test writes to the host it runs on. Unprivileged
the open fails and "exit 0" hides it; CI runs as root, where the same line
creates or truncates the file.
The path is read from XCAT_ERROR_ARCHIVE, falling back to the same default, the
way XCAT_ERROR_CONSOLE already does on the next line. An install sets neither
variable and writes where it always did.
The test points the variable inside BATS_TEST_TMPDIR, has the tar shadow emit a
marker so the output can be traced to the file it named, and asserts the default
path under /run was not touched. Reverting the template to the fixed path fails
that case.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
GO_XCAT_UNINSTALL_LIST names every package go-xcat installs plus the ones xCAT
has stopped producing, so a node installed before they went away is still
cleaned up. uninstall_xcat handed that whole list to the package manager, and
most of it is not installed on any one node: apt answers "Unable to locate
package" for a name it does not know and go-xcat warns once per package, while
dnf answers "No match for argument" and fails the call when nothing matches.
installed_packages() asks the local package database which of them this system
has, and uninstall_xcat and uninstall_xcat_completely pass only those on. A
node with none of them installed calls the package manager not at all.
This is also what makes a retired name in the list free to keep.
go_xcat_uninstall_installed_only.t runs uninstall_xcat with rpm and dpkg-query
answering from a fake package database and remove_package shadowed, and reads
the argument list the package manager would have been given. A filter that
kept everything and a filter that kept nothing each fail three of its four
assertions.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
Deleting xCAT-genesis-builder/README.md removed 99 lines that describe the
build path this branch keeps: the kas virtualenv, the architectures `oe/build`
accepts, the console keys, `oe/export`, the signed-extension workflow with
`oe/export-extension`, and the `oe/report` baseline comparison. Only the legacy
RPM builder half was dead. The reader is now told nothing about how to build a
Genesis image.
xCAT-genesis-base/README.md carries that half with its paths on the new
directory. The legacy RPM builder chapter stays deleted.
go-xcat keeps xCAT-genesis-builder in GO_XCAT_UNINSTALL_LIST. No build
produces that rpm any more, but a management node installed before 2.19 still
has it, and the list is what `go-xcat uninstall` hands to the package manager.
genesis_readme_paths.t asserts every in-tree path the README names exists, and
that its link to the architecture plan resolves. It reads the file because the
file is the artifact: the text is the instruction. It matches any xCAT-*
directory rather than the new name alone, so a path left on the old name fails
instead of going uncollected, and it bails below a fixed floor so a pattern
that stops matching cannot pass on an empty plan.
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
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>