mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-21 16:39:30 +00:00
4dd16eb5f1
The nodeset_shell_incorrectmasterip case ran "nodeset testnode shell", the command failed with "/tftpboot/boot/grub2/grub2.x86_64 does not exits", and the case still passed. check_destiny in xCAT-test/autotest/testcase/genesis/test.sh discards the return value of runcmd and greps the boot configuration file, which grub2.pm writes before it stops on the missing boot loader. The sub-case asserts nothing. wait_for_boot in xCAT-test/autotest/testcase/genesis/genesistest.pl waits for nodelist.status "booted". A Genesis node reports its destiny with getdestiny and xcatd writes "shell", "configuring" or "booting" from it, never "booted". Every caller discards the return value, so each case rests on its xdsh probes alone. genesis_incorrectmasterip_check.t now runs the check with a nodeset that fails, and reads whether the grub2 boot loader for the node arch is present when nodeset runs. genesis_testcase_helpers.t drives the status wait with lsdef shadowed, and drives the shell case with every command it runs shadowed. genesis_payload_verification.t reads a payload without mktemp, which getdestiny needs to make its request file. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 3597760645ddf38f110457934982e2cc9a113f84)
96 lines
4.2 KiB
Perl
96 lines
4.2 KiB
Perl
#!/usr/bin/env perl
|
|
# Drive verify-genesis-payload against payload trees that reproduce the three holes the
|
|
# released legacy Genesis image shipped with.
|
|
use strict;
|
|
use warnings;
|
|
|
|
use File::Path qw(make_path);
|
|
use File::Slurper qw(read_text write_text);
|
|
use File::Temp qw(tempdir);
|
|
use FindBin;
|
|
use lib "$FindBin::Bin/../lib";
|
|
use Test::More;
|
|
|
|
use XCAT::Test::File qw(repo_path);
|
|
|
|
my $verifier = repo_path('xCAT-genesis-builder/verify-genesis-payload');
|
|
plan skip_all => 'verify-genesis-payload not found' unless -f $verifier;
|
|
plan tests => 11;
|
|
|
|
my $tmpdir = tempdir(CLEANUP => 1);
|
|
|
|
# A complete payload: OpenSSH 9.9 sshd plus its session helper, tmux plus a UTF-8 locale.
|
|
my $good = build_payload(sshd_execs_session => 1, session_helper => 1, tmux => 1, locale => 1, dhclient => 1, mktemp => 1);
|
|
my ($rc, $err) = run($good, 'usr/sbin/dhclient');
|
|
is($rc, 0, 'a complete payload passes') or diag($err);
|
|
|
|
# doxcat calls dhclient with ISC flags. The released el9 image carried dhclient.conf and
|
|
# dhclient-script but no dhclient, so Genesis never acquired an address.
|
|
my $nodhcp = build_payload(sshd_execs_session => 1, session_helper => 1, tmux => 1, locale => 1, dhclient => 0, mktemp => 1);
|
|
($rc, $err) = run($nodhcp, 'usr/sbin/dhclient');
|
|
isnt($rc, 0, 'a payload without dhclient fails');
|
|
like($err, qr{usr/sbin/dhclient}, 'the missing dhclient is named');
|
|
|
|
# sshd 9.9 execs /usr/libexec/openssh/sshd-session for every connection.
|
|
my $nohelper = build_payload(sshd_execs_session => 1, session_helper => 0, tmux => 1, locale => 1, dhclient => 1, mktemp => 1);
|
|
($rc, $err) = run($nohelper, 'usr/sbin/dhclient');
|
|
isnt($rc, 0, 'a payload whose sshd execs sshd-session but does not ship it fails');
|
|
like($err, qr{sshd-session}, 'the missing sshd-session is named');
|
|
|
|
# OpenSSH 8 does not use the helper, so el8 must still pass without it.
|
|
my $openssh8 = build_payload(sshd_execs_session => 0, session_helper => 0, tmux => 1, locale => 1, dhclient => 1, mktemp => 1);
|
|
($rc, $err) = run($openssh8, 'usr/sbin/dhclient');
|
|
is($rc, 0, 'an OpenSSH 8 payload passes without sshd-session') or diag($err);
|
|
|
|
# tmux without a UTF-8 locale is what stopped doxcat from ever running.
|
|
my $nolocale = build_payload(sshd_execs_session => 1, session_helper => 1, tmux => 1, locale => 0, dhclient => 1, mktemp => 1);
|
|
($rc, $err) = run($nolocale, 'usr/sbin/dhclient');
|
|
isnt($rc, 0, 'a payload with tmux and no UTF-8 locale fails');
|
|
like($err, qr{C\.utf8}, 'the missing locale is named');
|
|
|
|
# getdestiny makes its request file with mktemp. Without it the node never reports its destiny,
|
|
# so xcatd never sets nodelist.status and the node stays at powering-on.
|
|
my $nomktemp = build_payload(sshd_execs_session => 1, session_helper => 1, tmux => 1, locale => 1, dhclient => 1, mktemp => 0);
|
|
($rc, $err) = run($nomktemp, 'usr/sbin/dhclient');
|
|
isnt($rc, 0, 'a payload without mktemp fails');
|
|
like($err, qr{usr/bin/mktemp}, 'the missing mktemp is named');
|
|
|
|
($rc, $err) = run("$tmpdir/does-not-exist");
|
|
is($rc >> 0, 2, 'a missing payload directory is a usage error');
|
|
|
|
#---
|
|
# build_payload: make a payload tree with the pieces the verifier reasons about.
|
|
#---
|
|
sub build_payload {
|
|
my (%opt) = @_;
|
|
my $root = tempdir(DIR => $tmpdir, CLEANUP => 1);
|
|
make_path("$root/usr/sbin", "$root/usr/bin", "$root/usr/libexec/openssh");
|
|
write_text("$root/usr/sbin/sshd",
|
|
$opt{sshd_execs_session}
|
|
? "OpenSSH_9.9p1\n/usr/libexec/openssh/sshd-session\n"
|
|
: "OpenSSH_8.0p1\n");
|
|
write_text("$root/usr/libexec/openssh/sshd-session", "helper\n") if $opt{session_helper};
|
|
write_text("$root/usr/bin/tmux", "tmux\n") if $opt{tmux};
|
|
if ($opt{locale}) {
|
|
make_path("$root/usr/lib/locale/C.utf8");
|
|
write_text("$root/usr/lib/locale/C.utf8/LC_CTYPE", "ctype\n");
|
|
}
|
|
write_text("$root/usr/sbin/dhclient", "dhclient\n") if $opt{dhclient};
|
|
write_text("$root/usr/bin/mktemp", "mktemp\n") if $opt{mktemp};
|
|
return $root;
|
|
}
|
|
|
|
#---
|
|
# run: run the verifier and return its exit status and stderr.
|
|
#---
|
|
sub run {
|
|
my ($root, @required) = @_;
|
|
my $errfile = "$tmpdir/err.$$";
|
|
my $cmd = join ' ', map { "'$_'" } ($verifier, $root, @required);
|
|
system("/bin/bash $cmd >/dev/null 2>$errfile");
|
|
my $status = $? >> 8;
|
|
my $err = -f $errfile ? read_text($errfile) : '';
|
|
unlink $errfile;
|
|
return ($status, $err);
|
|
}
|