2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-25 09:14:05 +00:00

test(xcat-core): a failed Ubuntu install waits for someone to collect its logs

The Subiquity template offers the installer logs with "nc -l 8080" in
error-commands. Subiquity waits for every error command to return, and that
listener waits for a collector an unattended install never has, so a failed
install stops there until the provisioning timeout resets the node.

The test runs the template's own error commands with nc, tar and tail replaced,
and requires that they return and that they write the end of the curtin log to
the console the caller names. Both assertions fail before the fix: the first
times out.

Evidence: reg_linux_diskfull_installation_flat on Ubuntu 24.04 ppc64le, cluster
xcat25. The node wrote no disk block and sent no packet for 18 minutes with the
console at "acquiring and extracting image from cp:///tmp/.../mount". Port 8080
was open; one connection to it released the install and the console then
reported the error.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
Daniel Hilst
2026-09-12 14:28:25 -03:00
parent 5d0f6fc50d
commit 19a7a41572
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use File::Temp qw(tempdir);
use Test::More;
# Subiquity waits for every error command to return before it reports the failure. The template
# used to offer the installer logs with "nc -l 8080", which waits for a collector that an
# unattended install never has, so a failed install stopped there: the node answered ping with no
# disk or network activity for as long as the provisioning timeout allowed, and the reason for the
# failure stayed on the node. That is how a missing grub-ieee1275 on ppc64el read as a wedged
# curtin extract.
#
# 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.
my $tmpl = "$FindBin::Bin/../../xCAT-server/share/xcat/install/ubuntu/compute.subiquity.tmpl";
plan skip_all => 'compute.subiquity.tmpl not found' unless -r $tmpl;
open(my $fh, '<', $tmpl) or die "open $tmpl: $!";
my $source = do { local $/; <$fh> };
close $fh;
my ($block) = $source =~ m{^ error-commands:\n((?: [-#].*\n)+)}m;
BAIL_OUT('the template declares no error-commands') unless $block;
# One command per list item. The list form ['sh', '-c', '...'] carries the command in its last
# element; a plain item is the command itself.
my @commands;
foreach my $line (split /\n/, $block) {
next unless $line =~ m{^ - (.*)$};
my $item = $1;
if ($item =~ m{^\['[^']+', '-c', '(.*)'\]$}) { push @commands, $1; }
else { push @commands, $item; }
}
BAIL_OUT('no error command found in the block') unless @commands;
my $root = tempdir(CLEANUP => 1);
my $console = "$root/console";
my $script = "$root/error-commands.sh";
# nc, tar and tail are shadowed: bash resolves a function ahead of PATH, so the commands run as
# written while nothing reaches the host or the network. nc waits the way a listener with no
# collector waits.
open(my $out, '>', $script) or die "open $script: $!";
print {$out} "export XCAT_ERROR_CONSOLE='$console'\n";
print {$out} "nc() { sleep 300; }\n";
print {$out} "tar() { :; }\n";
print {$out} "tail() { echo XCAT_CURTIN_LOG_TAIL; }\n";
foreach my $command (@commands) {
( my $rendered = $command ) =~ s/#HOSTNAME#/testnode/g;
# Subiquity runs each error command on its own, so a command that ends in "exit 0" must not
# end the others.
print {$out} "( $rendered )\n";
}
close $out;
my $rc = system('timeout', '10', 'bash', $script);
my $status = $rc == -1 ? -1 : $rc >> 8;
isnt( $status, 124, 'the error commands return instead of waiting for someone to collect the logs' );
my $written = '';
if (open(my $log, '<', $console)) { local $/; $written = <$log>; close $log; }
like( $written, qr/XCAT_CURTIN_LOG_TAIL/, 'and write the end of the curtin log to the console the installer names' );
done_testing();