2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-28 16:20:51 +00:00

Merge pull request #7834 from VersatusHPC/fix/ubuntu-subiquity-ppc64le-grub-ieee1275

fix(xcat-core): the Ubuntu ppc64le diskful install stops without grub-ieee1275
This commit is contained in:
Daniel Hilst
2026-09-24 10:57:04 -03:00
committed by GitHub
4 changed files with 127 additions and 3 deletions
+14 -2
View File
@@ -1850,6 +1850,18 @@ sub ubuntu_subiquity_apt_mirror
# The key curtin names in the Deb822 source it writes for the primary apt mirror on 24.04 and later.
my $UBUNTU_ARCHIVE_KEYRING = '/usr/share/keyrings/ubuntu-archive-keyring.gpg';
# The apt lines that keep the recommended packages out of the install. ospkgs installs without
# them and the installer matches it. ppc64el is the exception: curtin installs a bootloader
# package of its own for UEFI and for s390x only, and on a PReP machine install_grub runs
# "dpkg-reconfigure grub-ieee1275" on a package the Ubuntu kernel image only recommends.
sub ubuntu_subiquity_no_recommends_lines
{
my ($osarch) = @_;
return () if defined($osarch) && $osarch =~ /^ppc64/i;
return (q( conf: 'APT::Install-Recommends "false";'));
}
sub ubuntu_subiquity_apt_config
{
my ($media_dir, $osarch, $pkgdirs) = @_;
@@ -1877,7 +1889,7 @@ sub ubuntu_subiquity_apt_config
' apt:',
' preserve_sources_list: false',
' geoip: false',
q( conf: 'APT::Install-Recommends "false";'),
ubuntu_subiquity_no_recommends_lines($osarch),
' mirror-selection:',
' primary:',
" - uri: $online_mirror",
@@ -1916,7 +1928,7 @@ sub ubuntu_subiquity_apt_config
' preserve_sources_list: false',
' fallback: offline-install',
' geoip: false',
q( conf: 'APT::Install-Recommends "false";'),
ubuntu_subiquity_no_recommends_lines($osarch),
' disable_suites:',
' - updates',
' - backports',
@@ -127,4 +127,11 @@ autoinstall:
# monitor that died and never came back is #7759.
- ['bash', '-c', 'xm=#XCATVAR:XCATMASTER#; port="#TABLEBLANKOKAY:site:key=xcatiport:value#"; [ -n "$port" ] || port=3002; ok=0; for i in 1 2 3 4 5; do if exec 3<>/dev/tcp/$xm/$port; then if read -r -t 10 hello <&3 && [ "$hello" = "ready" ]; then printf "next\n" >&3; if read -r -t 10 ack <&3 && [ "$ack" = "done" ]; then ok=1; fi; fi; exec 3>&- 3<&-; [ "$ok" = 1 ] && break; fi; sleep 5; done; if [ "$ok" != 1 ]; then echo "xcat: FAILED to flip $(hostname) to local-disk boot via $xm:$port; the node will PXE back into the installer" >>/target/var/log/xcat/xcat.log; fi; exit 0']
error-commands:
- tar -c --ignore-failed-read --transform='s/^/#HOSTNAME#-logs\//' /var/crash /var/log/installer /tmp/pre-install.log /autoinstall.yaml 2>/dev/null |nc -l 8080
# Subiquity waits for every error command to return. "nc -l 8080" waits for a collector, which
# an unattended install does not have. Keep the archive on the installer, and print the end of
# the curtin log to the console, which the management node records.
#
# Both destinations are read from the environment so a test can point them at its own
# directory. The installer sets neither, so an install writes where it always did.
- ['sh', '-c', 'tar -c --ignore-failed-read --transform="s/^/#HOSTNAME#-logs\//" /var/crash /var/log/installer /tmp/pre-install.log /autoinstall.yaml >"${XCAT_ERROR_ARCHIVE:-/run/#HOSTNAME#-logs.tar}" 2>/dev/null; exit 0']
- ['sh', '-c', 'tail -n 80 /var/log/installer/curtin-install.log >"${XCAT_ERROR_CONSOLE:-/dev/console}" 2>/dev/null; exit 0']
@@ -0,0 +1,92 @@
#!/usr/bin/env bats
#
# Subiquity waits for every error command to return before it reports the failure. An error
# command that waits for a collector an unattended install does not have therefore holds the
# node until the provisioning timeout.
#
# Run the error commands, with the programs that would reach the host or the network replaced,
# and check that they return and that they write the end of the curtin log where the caller
# points.
load 'helpers/shell_source'
setup()
{
TEMPLATE="$(repo_path 'xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl')"
[ -r "$TEMPLATE" ] || skip "$TEMPLATE is required"
export TEMPLATE
}
# One command per list item of the error-commands block. The list form ['sh', '-c', '...']
# carries the command in its last element; a plain item is the command itself.
error_commands()
{
awk '
/^ error-commands:$/ { copy = 1; next }
copy && !/^ [-#]/ { exit }
copy && /^ - / {
found = 1
line = substr($0, 7)
if (match(line, /^\[[^]]*, .-c., .*\]$/)) {
sub(/^\[[^]]*, .-c., ./, "", line)
sub(/.\]$/, "", line)
}
print line
}
END { if (!found) exit 1 }
' "$TEMPLATE"
}
# bash resolves a function ahead of PATH, so the commands run as written while nothing reaches
# the host or the network. The nc shadow waits the way a listener with no collector waits.
#
# Shadowing a command does not stop the shell opening the file the command redirects into: the
# redirection is the shell's, and it happens whether or not tar runs. So the archive path is
# taken from the environment too, and pointed inside the test's own directory. Without that,
# this test would truncate /run/<node>-logs.tar on the host running it, and CI runs as root.
run_error_commands()
{
local script="${BATS_TEST_TMPDIR}/error-commands.sh" command
: >"$script"
{
printf "export XCAT_ERROR_CONSOLE='%s'\n" "$CONSOLE"
printf "export XCAT_ERROR_ARCHIVE='%s'\n" "$ARCHIVE"
printf 'nc() { sleep 300; }\n'
printf 'tar() { echo XCAT_LOGS_ARCHIVE; }\n'
printf 'tail() { echo XCAT_CURTIN_LOG_TAIL; }\n'
} >>"$script"
while IFS= read -r command; do
# Subiquity runs each error command on its own, so a command that ends in "exit 0"
# must not end the others.
printf '( %s )\n' "${command//\#HOSTNAME\#/testnode}" >>"$script"
done < <(error_commands)
timeout 10 bash "$script"
}
@test "the error commands return instead of waiting for someone to collect the logs" {
[ -n "$(error_commands)" ]
CONSOLE="${BATS_TEST_TMPDIR}/console"
ARCHIVE="${BATS_TEST_TMPDIR}/logs.tar"
run run_error_commands
[ "$status" -ne 124 ]
grep -q XCAT_CURTIN_LOG_TAIL "$CONSOLE"
}
@test "the log archive is written where the caller points, and nowhere else" {
CONSOLE="${BATS_TEST_TMPDIR}/console"
ARCHIVE="${BATS_TEST_TMPDIR}/logs.tar"
run run_error_commands
[ "$status" -ne 124 ]
# The archive command redirects into the path it was given, so its output IS the proof
# that the redirection went there and not to the default under /run. There is nothing to
# add by looking at the default path: whether /run/testnode-logs.tar exists says nothing
# about this test, because anything else may have created it, and its absence would be
# just as true had the override never worked.
grep -q XCAT_LOGS_ARCHIVE "$ARCHIVE"
}
+13
View File
@@ -193,8 +193,21 @@ is( $render->( $pkglist, environvar => 'ACCEPT_EULA=Y' ), $without,
};
like( $apt_render->(), qr{URIs: http://mirror\.example/ubuntu}, 'the pkgdir mirror joins the installer sources' );
like( $apt_render->(), qr{^ conf: 'APT::Install-Recommends "false";'$}m, 'the installer installs without recommended packages, as ospkgs does' );
# On a PReP machine curtin installs no bootloader package of its own: install_missing_packages
# covers UEFI and s390x only, and install_grub then runs "dpkg-reconfigure grub-ieee1275".
# The Ubuntu kernel image recommends grub-ieee1275, so the package reaches the target only
# when the installer keeps recommended packages.
unlike( $apt_render->( osarch => 'ppc64el' ), qr{APT::Install-Recommends},
'except on ppc64el, where the bootloader the installer configures is a recommended package' );
unlike( $apt_render->( environvar => 'http_proxy=http://proxy.example:3128' ), qr{mirror\.example|xcat-pkgdir},
'but not for an osimage with environvar, whose mirrors may need those variables' );
# The offline configuration installs from the media alone and carries the same setting.
local *xCAT::Template::ubuntu_subiquity_apt_mirror = sub { '' };
like( $apt_render->(), qr{^ conf: 'APT::Install-Recommends "false";'$}m,
'an offline install drops the recommended packages as well' );
unlike( $apt_render->( osarch => 'ppc64el' ), qr{APT::Install-Recommends},
'and keeps them on ppc64el for the same reason' );
}
done_testing();