mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-26 09:44:03 +00:00
fix(xcat-core): the genesis harness passes on a nodeset that failed and a node that never booted
The nodeset_shell_incorrectmasterip case passed while "nodeset testnode shell" failed with "/tftpboot/boot/grub2/grub2.x86_64 does not exits". The grub2 sub-case asserted nothing. Every genesis case reported "After 30 iterations node status: powering-on" and passed anyway. check_destiny in xCAT-test/autotest/testcase/genesis/test.sh discarded the return value of runcmd and read the boot configuration file, which grub2.pm writes before it stops on the missing boot loader. xCAT builds no grub2 boot loader for x86_64, so the file is absent on a correctly built management node. wait_for_boot in genesistest.pl waited for nodelist.status "booted"; a Genesis node reports its destiny with getdestiny and xcatd writes "shell", "configuring" or "booting" from it. Every caller discarded the return value. The node did not reach even those statuses, because getdestiny makes its request file with mktemp and the dracut module never installed it. check_destiny now returns the status of nodeset, and the grub2 check stages an empty grub2.<arch> when the management node has none and removes it after. wait_for_node_status takes the status the destiny implies and each caller fails when the node does not reach it; the shell case moved into run_nodeset_shell_test so its result can be read. clearenv no longer waits, because "rinstall <node> boot" boots a disk with no operating system and reports nothing. The dracut modules install mktemp and verify-genesis-payload requires it. Tests: genesis_incorrectmasterip_check.t runs the check with a failing nodeset and reads whether the boot loader is present when nodeset runs; genesis_testcase_helpers.t drives the status wait and the shell case; genesis_payload_verification.t reads a payload without mktemp. Each fails on the parent commit. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> (cherry picked from commit 8ecf0a806785023aca0ea6d1b0e41810630816b2) The Release hunk of the original commit is dropped. buildrpms.pl writes Release from SOURCE_DATE_EPOCH at build time, so the committed snap stamp is build debris.
This commit is contained in:
@@ -47,6 +47,9 @@ install() {
|
||||
dracut_install mount.nfs sshd vi reboot lspci parted tmux mkfs mkfs.ext4 mkfs.xfs xfs_db
|
||||
#dracut_install libvirtd /usr/share/libvirt/cpu_map.xml /usr/bin/qemu-img /usr/libexec/qemu-kvm
|
||||
dracut_install mkswap df ifenslave ssh-keygen scp clear
|
||||
# getdestiny makes its request file with mktemp. Without it the node reports no
|
||||
# destiny, so xcatd never moves nodelist.status past powering-on.
|
||||
dracut_install mktemp
|
||||
dracut_install lldpad
|
||||
|
||||
# RHEL 10 packages no ISC dhcp-client. Install whichever client the build root carries;
|
||||
|
||||
@@ -52,6 +52,9 @@ install() {
|
||||
dracut_install mount.nfs sshd vi reboot lspci parted screen mkfs mkfs.ext4 mkfs.btrfs
|
||||
#dracut_install libvirtd /usr/share/libvirt/cpu_map.xml /usr/bin/qemu-img /usr/libexec/qemu-kvm
|
||||
dracut_install mkswap df ifenslave ssh-keygen scp clear
|
||||
# getdestiny makes its request file with mktemp. Without it the node reports no
|
||||
# destiny, so xcatd never moves nodelist.status past powering-on.
|
||||
dracut_install mktemp
|
||||
dracut_install dhclient lldpad
|
||||
|
||||
# OpenSSH 9.8 moved the per-connection work into sshd-session, which sshd execs by
|
||||
|
||||
@@ -37,6 +37,7 @@ for path in "$@"; do
|
||||
done
|
||||
|
||||
require usr/sbin/sshd "Genesis is reached over ssh"
|
||||
require usr/bin/mktemp "getdestiny makes its request file with it"
|
||||
|
||||
# OpenSSH 9.8 split the per-connection work into sshd-session, which sshd execs by absolute
|
||||
# path. EL9 carries OpenSSH 9.9, so an image with sshd alone refuses every connection.
|
||||
|
||||
@@ -83,29 +83,7 @@ if (!(-e $nodestanza)) {
|
||||
####nodesetshell test for genesis
|
||||
####################################
|
||||
if ($genesis_nodesetshell_test) {
|
||||
send_msg(2, "[$$]:Running nodeset NODE shell test...............");
|
||||
`nodeset $noderange shell`;
|
||||
if ($?) {
|
||||
send_msg(0, "[$$]:nodeset $noderange shell failed...............");
|
||||
exit 1;
|
||||
}
|
||||
`rpower $noderange boot`;
|
||||
if ($?) {
|
||||
send_msg(0, "[$$]:rpower $noderange failed...............");
|
||||
exit 1;
|
||||
}
|
||||
else {
|
||||
send_msg(2, "Installing with \"nodeset $noderange shell\" for shell test");
|
||||
sleep 120; # wait 2 min for install to finish
|
||||
wait_for_boot();
|
||||
}
|
||||
#run nodeshell test
|
||||
send_msg(2, "prepare for nodeshell script.");
|
||||
if ( &testxdsh(3)) {
|
||||
send_msg(0, "[$$]:Could not verify test results using xdsh...............");
|
||||
exit 1;
|
||||
}
|
||||
send_msg(2, "[$$]:Running nodesetshell test success...............");
|
||||
exit 1 if &run_nodeset_shell_test();
|
||||
}
|
||||
####################################
|
||||
####runcmd test for genesis
|
||||
@@ -142,6 +120,36 @@ if ($clear_env) {
|
||||
send_msg(2, "[$$]:Clear genesis test enviroment success...............");
|
||||
}
|
||||
##################################
|
||||
#run_nodeset_shell_test
|
||||
#################################
|
||||
sub run_nodeset_shell_test {
|
||||
send_msg(2, "[$$]:Running nodeset NODE shell test...............");
|
||||
`nodeset $noderange shell`;
|
||||
if ($?) {
|
||||
send_msg(0, "[$$]:nodeset $noderange shell failed...............");
|
||||
return 1;
|
||||
}
|
||||
`rpower $noderange boot`;
|
||||
if ($?) {
|
||||
send_msg(0, "[$$]:rpower $noderange failed...............");
|
||||
return 1;
|
||||
}
|
||||
send_msg(2, "Installing with \"nodeset $noderange shell\" for shell test");
|
||||
sleep 120; # wait 2 min for install to finish
|
||||
if (&wait_for_node_status("shell")) {
|
||||
send_msg(0, "[$$]:$noderange did not report the shell destiny...............");
|
||||
return 1;
|
||||
}
|
||||
#run nodeshell test
|
||||
send_msg(2, "prepare for nodeshell script.");
|
||||
if (&testxdsh(3)) {
|
||||
send_msg(0, "[$$]:Could not verify test results using xdsh...............");
|
||||
return 1;
|
||||
}
|
||||
send_msg(2, "[$$]:Running nodesetshell test success...............");
|
||||
return 0;
|
||||
}
|
||||
##################################
|
||||
#report_genesis_files
|
||||
#################################
|
||||
sub report_genesis_files {
|
||||
@@ -223,7 +231,7 @@ sub rungenesiscmd {
|
||||
else {
|
||||
send_msg(2, "Installing with \"$rinstall_cmd\" for runcmd test");
|
||||
sleep 120; # wait 2 min for install to finish
|
||||
wait_for_boot();
|
||||
$value = -1 if &wait_for_node_status("configuring");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
@@ -266,7 +274,7 @@ sub rungenesisimg {
|
||||
} else {
|
||||
send_msg(2, "Installing with \"$rinstall_cmd\" for runimage test\n");
|
||||
sleep 120; # wait 2 min for install to finish
|
||||
wait_for_boot();
|
||||
$value = -1 if &wait_for_node_status("booting");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
@@ -375,8 +383,9 @@ sub clearenv {
|
||||
`cat $nodestanza | chdef -z`;
|
||||
unlink("$nodestanza");
|
||||
}
|
||||
# "rinstall <node> boot" boots the node from its disk, which carries no operating system,
|
||||
# so the node reports no destiny and nodelist.status stays at powering-on. Only wait.
|
||||
sleep 120; # wait 2 min for reboot to finish
|
||||
wait_for_boot();
|
||||
return 0;
|
||||
}
|
||||
####################################
|
||||
@@ -448,9 +457,10 @@ sub send_msg {
|
||||
|
||||
}
|
||||
#########################################
|
||||
### Wait for node to be in "booted" state
|
||||
### Wait for the node to report the status its destiny implies
|
||||
##########################################
|
||||
sub wait_for_boot {
|
||||
sub wait_for_node_status {
|
||||
my ($expected) = @_;
|
||||
my $iterations = 30; # Max wait 30x10 = 5 min
|
||||
my $sleep_interval = 10;
|
||||
my $boot_status;
|
||||
@@ -458,11 +468,11 @@ sub wait_for_boot {
|
||||
foreach my $i (1..$iterations) {
|
||||
$boot_status = `lsdef $noderange -i status -c | cut -d'=' -f2`;
|
||||
chop($boot_status);
|
||||
if ($boot_status eq "booted") {
|
||||
if ($boot_status eq $expected) {
|
||||
return 0;
|
||||
}
|
||||
sleep $sleep_interval;
|
||||
}
|
||||
print "After $iterations iterations node status: $boot_status \n";
|
||||
print "After $iterations iterations node status: $boot_status, expected $expected \n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,41 @@ TESTNODE_ARCH="$(uname -m)"
|
||||
# against a scratch tree.
|
||||
TFTPDIR="${TFTPDIR:-/tftpboot}"
|
||||
|
||||
# grub2.pm names the boot loader grub2.<arch>, with every ppc64 flavour written as "ppc".
|
||||
TESTNODE_LOADER_ARCH="$TESTNODE_ARCH"
|
||||
[[ $TESTNODE_LOADER_ARCH =~ ^ppc64 ]] && TESTNODE_LOADER_ARCH="ppc"
|
||||
STAGED_BOOT_LOADER=""
|
||||
|
||||
MASTER_PRIVATE_IP="192.168.1.1"
|
||||
MASTER_PRIVATE_NETMASK="255.255.0.0"
|
||||
MASTER_PRIVATE_NETWORK="192_168_0_0-255_255_0_0"
|
||||
|
||||
|
||||
# xCAT builds no grub2 network boot loader for x86_64 or aarch64. The administrator installs
|
||||
# grub2.<arch> by hand -- docs/source/guides/install-guides/yum/grub2.rst. grub2.pm stops the
|
||||
# configuration when the file is absent, and this case reads the configuration only.
|
||||
function stage_boot_loader() {
|
||||
local loader="$TFTPDIR/boot/grub2/grub2.$TESTNODE_LOADER_ARCH";
|
||||
if [[ -e $loader ]];then
|
||||
return 0;
|
||||
fi
|
||||
mkdir -p "$TFTPDIR/boot/grub2" || return 1;
|
||||
: > "$loader" || return 1;
|
||||
STAGED_BOOT_LOADER="$loader";
|
||||
echo "Staged an empty boot loader at $loader for the check";
|
||||
return 0;
|
||||
}
|
||||
|
||||
function unstage_boot_loader() {
|
||||
if [[ -z $STAGED_BOOT_LOADER ]];then
|
||||
return 0;
|
||||
fi
|
||||
# grub2.pm links grub2-<node> to the loader. Remove the link with the file it points at.
|
||||
rm -f "$STAGED_BOOT_LOADER" "$TFTPDIR/boot/grub2/grub2-${TESTNODE}";
|
||||
STAGED_BOOT_LOADER="";
|
||||
return 0;
|
||||
}
|
||||
|
||||
function check_destiny() {
|
||||
cmd="chdef ${TESTNODE} arch=${TESTNODE_ARCH} cons=ipmi groups=all ip=${TESTNODE_IP} mac=4e:ee:ee:ee:ee:0e netboot=$NETBOOT tftpserver=$MASTER_PRIVATE_IP xcatmaster=$MASTER_PRIVATE_IP";
|
||||
runcmd $cmd;
|
||||
@@ -58,8 +88,15 @@ function check_destiny() {
|
||||
grep ${TESTNODE} /etc/hosts
|
||||
cmd="nodeset ${TESTNODE} shell";
|
||||
runcmd $cmd;
|
||||
# grub2.pm writes the boot configuration and only then stops on a missing boot loader,
|
||||
# so the file the check reads below exists even when nodeset failed.
|
||||
nodeset_rc=$?;
|
||||
cmd="ip addr del $MASTER_PRIVATE_IP/$MASTER_PRIVATE_NETMASK dev $NET2";
|
||||
runcmd $cmd;
|
||||
if [[ $nodeset_rc -ne 0 ]];then
|
||||
echo "'nodeset ${TESTNODE} shell' FAILED";
|
||||
return 1;
|
||||
fi
|
||||
echo "Check if 'nodeset ${TESTNODE} shell' is added to ${SHELLFOLDER}/${TESTNODE}"
|
||||
echo "==============================================="
|
||||
cat "${SHELLFOLDER}/${TESTNODE}"
|
||||
@@ -97,9 +134,12 @@ while [ "$#" -ge "0" ]; do
|
||||
SHELLFOLDER="$TFTPDIR/xcat/xnba/nodes"
|
||||
else
|
||||
SHELLFOLDER="$TFTPDIR/boot/grub2";
|
||||
stage_boot_loader || exit 1;
|
||||
fi
|
||||
check_destiny ;
|
||||
if [[ $? -eq 1 ]];then
|
||||
rc=$?;
|
||||
unstage_boot_loader;
|
||||
if [[ $rc -eq 1 ]];then
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user