From 7c884cfe2fc1eb4bd056ad8d9ef44003c2599f2e Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:43:40 -0300 Subject: [PATCH 1/7] refactor(xcatdsklspost): put the /xcatpost cleanup in one routine The decision to remove the postscripts from /xcatpost sits inline in the tail of xcatdsklspost, where nothing can drive it without a management node and a real download. A test of that decision has to grep the source of the script instead. Move the decision into append_xcatpost_cleanup, above the XCATDSKLSPOST_SOURCE_ONLY guard, so a test can source the script and call the routine against a scratch directory. The routine takes the mypostscript path and the xcatpost directory, and emits the same text as before for every value of site.cleanupxcatpost. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT/postscripts/xcatdsklspost | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index 6f7dcc63a..5b8774f79 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -224,6 +224,29 @@ parsehttpserver () fi } +##################################################### +# Append to the generated mypostscript the /xcatpost cleanup the site table asks for. +# +# The append happens on every path this script serves: node deployment, and each +# updatenode, moncfg or reboot run. +# +# $1 - path of the generated mypostscript +# $2 - the xcatpost directory to remove the postscripts from +##################################################### +append_xcatpost_cleanup() +{ + local mypostscript=$1 + local postdir=$2 + local cleanupxcatpost + + cleanupxcatpost=`grep CLEANUPXCATPOST= "$mypostscript" |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` + if [[ "$cleanupxcatpost" =~ ^(1|yes|y)$ ]]; then + echo "cd /" >> "$mypostscript" + # /xcatpost might be read-only for statelite nodes + echo "rm -rf $postdir/*" >> "$mypostscript" + fi +} + if [ "$XCATDSKLSPOST_SOURCE_ONLY" = "1" ]; then return 0 2>/dev/null || exit 0 fi @@ -1086,12 +1109,7 @@ fi DHCP_TMP=`sed 's/\(DHCPINTERFACES=\)\(.*\)$/\1"\2"/' /$xcatpost/mypostscript` echo "$DHCP_TMP" > /$xcatpost/mypostscript -CLEANUPXCATPOST=`grep CLEANUPXCATPOST= /$xcatpost/mypostscript |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` -if [[ "$CLEANUPXCATPOST" =~ ^(1|yes|y)$ ]]; then - echo "cd /" >> /$xcatpost/mypostscript - # /xcatpost might be read-only for statelite nodes - echo "rm -rf /$xcatpost/*" >> /$xcatpost/mypostscript -fi +append_xcatpost_cleanup /$xcatpost/mypostscript /$xcatpost From 501b1ba44d1efa85533cf28776153e08b2990d78 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:44:56 -0300 Subject: [PATCH 2/7] test(xcatdsklspost): cover the /xcatpost cleanup after an updatenode run The site table has two attributes for the same directory and only one of them is covered: nothing pins what xcatdsklspost appends to mypostscript for site.cleanupdiskfullxcatpost, on the path every updatenode run takes. Drive append_xcatpost_cleanup against a scratch /xcatpost, run the mypostscript it writes, and assert on the directory that comes back: the postscripts are gone after a run that succeeds, updateflag.awk stays, and a run that fails keeps everything. Add refute_grep to the helpers, because a "! grep" line cannot fail a bats test unless it is the last line of one. Three of the six tests fail on this commit. xcatdsklspost reads CLEANUPXCATPOST and never reads CLEANUPDISKFULLXCATPOST. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-test/bats/helpers/shell_source.bash | 10 ++ .../bats/xcatdsklspost_xcatpost_cleanup.bats | 121 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats diff --git a/xCAT-test/bats/helpers/shell_source.bash b/xCAT-test/bats/helpers/shell_source.bash index 61a0bea8d..4f4384fb2 100644 --- a/xCAT-test/bats/helpers/shell_source.bash +++ b/xCAT-test/bats/helpers/shell_source.bash @@ -130,3 +130,13 @@ extract_first_matching_line() } ' "$file" } + +# grep that fails when the pattern IS present. +# +# Do not write "! grep ..." for this. bash ignores errexit for a command inverted with "!", +# so such a line never fails a test unless it is the last line of one. +refute_grep() +{ + ! grep "$@" + return $? +} diff --git a/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats b/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats new file mode 100644 index 000000000..b6658dcd4 --- /dev/null +++ b/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats @@ -0,0 +1,121 @@ +#!/usr/bin/env bats + +load 'helpers/shell_source' + +setup() +{ + DSKLSPOST="$(repo_path 'xCAT/postscripts/xcatdsklspost')" + [ -r "$DSKLSPOST" ] || skip "$DSKLSPOST is required" + XCATPOST="${BATS_TEST_TMPDIR}/xcatpost" + MYPS="${BATS_TEST_TMPDIR}/mypostscript" + MSGLOG="${BATS_TEST_TMPDIR}/msgutil.log" + export DSKLSPOST XCATPOST MYPS MSGLOG +} + +# A scratch /xcatpost with what an updatenode run downloads into it. +make_xcatpost() +{ + mkdir -p "$XCATPOST/_xcat" + printf 'updateflag\n' >"$XCATPOST/updateflag.awk" + printf 'setroute\n' >"$XCATPOST/setroute" + printf 'xcatlib\n' >"$XCATPOST/xcatlib.sh" + printf 'credentials\n' >"$XCATPOST/_xcat/postscript.cfg" +} + +# A scratch mypostscript that carries the site values and the run result. +# $1 is the value of return_value, the rest are the site table lines. +make_mypostscript() +{ + local result=$1 + shift + { + printf '%s\n' '#!/bin/bash' + printf 'msgutil_r() { printf "%%s\\n" "$3" >>"%s"; }\n' "$MSGLOG" + printf 'MASTER_IP=192.0.2.1\n' + printf 'NODE=node1\n' + printf 'log_label=xcat.updatenode\n' + printf 'return_value=%s\n' "$result" + printf '%s\n' "$@" + } >"$MYPS" +} + +append_cleanup() +{ + ( + XCATDSKLSPOST_SOURCE_ONLY=1 + export XCATDSKLSPOST_SOURCE_ONLY + # shellcheck disable=SC1090 + . "$DSKLSPOST" + type -t append_xcatpost_cleanup >/dev/null \ + || { echo "xcatdsklspost defines no append_xcatpost_cleanup" >&2; exit 99; } + append_xcatpost_cleanup "$MYPS" "$XCATPOST" + ) +} + +@test "an updatenode run that succeeds removes the postscripts when site.cleanupdiskfullxcatpost is set" { + make_xcatpost + make_mypostscript 0 "CLEANUPXCATPOST='no'" "CLEANUPDISKFULLXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ ! -e "$XCATPOST/setroute" ] + [ ! -e "$XCATPOST/xcatlib.sh" ] + [ ! -e "$XCATPOST/_xcat" ] +} + +@test "the cleanup keeps updateflag.awk so the node can still report its status" { + make_xcatpost + make_mypostscript 0 "CLEANUPXCATPOST='no'" "CLEANUPDISKFULLXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -f "$XCATPOST/updateflag.awk" ] + [ -d "$XCATPOST" ] + grep -q 'cleanup of .* completed' "$MSGLOG" +} + +@test "an updatenode run that fails keeps the postscripts for diagnosis" { + make_xcatpost + make_mypostscript 1 "CLEANUPXCATPOST='no'" "CLEANUPDISKFULLXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -f "$XCATPOST/setroute" ] + [ -f "$XCATPOST/_xcat/postscript.cfg" ] + refute_grep -q 'cleanup of .* completed' "$MSGLOG" +} + +@test "site.cleanupdiskfullxcatpost accepts the other true values of the site table" { + make_xcatpost + make_mypostscript 0 "CLEANUPDISKFULLXCATPOST='1'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ ! -e "$XCATPOST/setroute" ] +} + +@test "site.cleanupxcatpost removes every file including updateflag.awk" { + make_xcatpost + make_mypostscript 0 "CLEANUPXCATPOST='yes'" "CLEANUPDISKFULLXCATPOST='no'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -z "$(ls -A "$XCATPOST")" ] +} + +@test "neither setting leaves the downloaded postscripts in place" { + make_xcatpost + make_mypostscript 0 "CLEANUPXCATPOST='no'" "CLEANUPDISKFULLXCATPOST='no'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -f "$XCATPOST/setroute" ] + [ -f "$XCATPOST/updateflag.awk" ] + refute_grep -q -E 'rm -rf|-delete' "$MYPS" +} From 873ad1d41c9807dedfd8b94d5143d2569392ac68 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:46:38 -0300 Subject: [PATCH 3/7] fix(xcatdsklspost): updatenode leaves /xcatpost populated when site.cleanupdiskfullxcatpost is set An administrator sets site.cleanupdiskfullxcatpost, deploys a diskfull node, and /xcatpost is empty. The next updatenode run downloads the postscripts again and leaves them there. /xcatpost is mode 0755 and most of what lands in it is world-readable, so material the administrator was told is gone comes back on every maintenance run and on every reboot. xcatdsklspost is the script that repopulates /xcatpost on all of those paths, and it reads only CLEANUPXCATPOST. CLEANUPDISKFULLXCATPOST reaches the node in the same mypostscript, exported by the site table, and no code reads it. Only xcatinstallpost does, and that runs once, at install. Read it in append_xcatpost_cleanup with the rule xcatinstallpost uses: remove the postscripts when the run returns 0, keep updateflag.awk, and leave everything in place after a failed run so the node can be examined. xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats captures this. Three of its six tests fail on the previous commit. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- .../admin-guides/references/man5/site.5.rst | 4 +++- perl-xCAT/xCAT/Schema.pm | 4 +++- xCAT/postscripts/xcatdsklspost | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/source/guides/admin-guides/references/man5/site.5.rst b/docs/source/guides/admin-guides/references/man5/site.5.rst index 0496a919e..5da893f95 100644 --- a/docs/source/guides/admin-guides/references/man5/site.5.rst +++ b/docs/source/guides/admin-guides/references/man5/site.5.rst @@ -288,7 +288,9 @@ site Attributes: cleanupdiskfullxcatpost: (yes/1 or no/0). Set to 'yes' or '1' to clean up the /xcatpost directory on the diskfull nodes after the - postscripts are run with no errors. Default is no. + postscripts are run with no errors: at deployment, after each + updatenode run, and after a reboot. updateflag.awk stays, so + the node can still report its status. Default is no. db2installloc: The location which the service nodes should mount for the db2 code to install. Format is hostname:/path. If hostname is diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 4fdafac6b..d3618bef1 100644 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1198,7 +1198,9 @@ passed as argument rather than by table value', " postscripts are run. Default is no.\n\n" . " cleanupdiskfullxcatpost: (yes/1 or no/0). Set to 'yes' or '1' to clean up the /xcatpost\n" . " directory on the diskfull nodes after the\n" . -" postscripts are run with no errors. Default is no.\n\n" . +" postscripts are run with no errors: at deployment, after each\n" . +" updatenode run, and after a reboot. updateflag.awk stays, so\n" . +" the node can still report its status. Default is no.\n\n" . " db2installloc: The location which the service nodes should mount for\n" . " the db2 code to install. Format is hostname:/path. If hostname is\n" . " omitted, it defaults to the management node. Default is /mntdb2.\n\n" . diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index 5b8774f79..f8272561d 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -230,6 +230,12 @@ parsehttpserver () # The append happens on every path this script serves: node deployment, and each # updatenode, moncfg or reboot run. # +# The two site attributes do not ask for the same thing. cleanupxcatpost removes +# every file and ignores the result of the run. cleanupdiskfullxcatpost keeps +# updateflag.awk, which the node needs to report its status, and removes nothing +# after a failed run, so the postscripts stay on the node for diagnosis. +# xcatinstallpost applies the same rule at install time. +# # $1 - path of the generated mypostscript # $2 - the xcatpost directory to remove the postscripts from ##################################################### @@ -238,6 +244,7 @@ append_xcatpost_cleanup() local mypostscript=$1 local postdir=$2 local cleanupxcatpost + local cleanupdiskfullxcatpost cleanupxcatpost=`grep CLEANUPXCATPOST= "$mypostscript" |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` if [[ "$cleanupxcatpost" =~ ^(1|yes|y)$ ]]; then @@ -245,6 +252,18 @@ append_xcatpost_cleanup() # /xcatpost might be read-only for statelite nodes echo "rm -rf $postdir/*" >> "$mypostscript" fi + + cleanupdiskfullxcatpost=`grep CLEANUPDISKFULLXCATPOST= "$mypostscript" |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` + if [[ "$cleanupdiskfullxcatpost" =~ ^(1|yes|y)$ ]]; then + cat >> "$mypostscript" < Date: Mon, 14 Sep 2026 20:11:00 -0300 Subject: [PATCH 4/7] test(xcat-core): cover the here-document that embeds a postscript The install-time post script embeds xcatdsklspost, xcatinstallpost and xcatpostinit1 with "#INCLUDE:#" inside a here-document. The template copies each file verbatim, so a line in the postscript that equals the here-document delimiter ends that here-document early, and the rest of the postscript becomes shell code in the generated install script. Nothing measured that. The new test assembles every such embedding the six post.* install scripts declare, and asserts that bash parses the result and that no line of the embedded file equals the delimiter. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-test/unit/postscript_heredoc_embedding.t | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 xCAT-test/unit/postscript_heredoc_embedding.t diff --git a/xCAT-test/unit/postscript_heredoc_embedding.t b/xCAT-test/unit/postscript_heredoc_embedding.t new file mode 100644 index 000000000..6960761b8 --- /dev/null +++ b/xCAT-test/unit/postscript_heredoc_embedding.t @@ -0,0 +1,82 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use FindBin; +use File::Temp qw(tempdir); +use Test::More; + +# The install-time post script embeds whole postscripts with "#INCLUDE:#" inside a +# here-document. The template copies the file verbatim, so a line in the postscript that +# equals the here-document delimiter ends that here-document early. The generated install +# script then holds the rest of the postscript as shell code. +# +# That happened: a "cat >> ... </opt/xcat/xcatdsklspost << 'EOF'", and every diskfull +# install ran a post script that bash refused to parse. No postscript ran, so remoteshell +# never installed the root key and the node answered "Permission denied (publickey)". + +my $root = "$FindBin::Bin/../.."; +my $scriptdir = "$root/xCAT-server/share/xcat/install/scripts"; +plan skip_all => "$scriptdir not found" unless -d $scriptdir; + +# Return every (post script, delimiter, embedded file) the install scripts declare. +sub embeddings { + my @found; + opendir(my $dh, $scriptdir) or die "cannot read $scriptdir: $!"; + my @posts = sort grep { /^post\./ and -f "$scriptdir/$_" } readdir($dh); + closedir $dh; + + for my $post (@posts) { + open(my $fh, '<', "$scriptdir/$post") or die "cannot read $post: $!"; + my @lines = <$fh>; + close $fh; + for my $i (0 .. $#lines - 1) { + # cat >file << 'EOF' / (cat << 'EOF' + my ($delim) = $lines[$i] =~ /<<-?\s*'([A-Za-z_][A-Za-z0-9_]*)'\s*$/; + next unless defined $delim; + my ($include) = $lines[$i + 1] =~ /^#INCLUDE:(.+)#\s*$/; + next unless defined $include; + # The include path is a template expression; only its last element names the file. + next unless $include =~ m{/postscripts/([^/#]+)$}; + my $file = "$root/xCAT/postscripts/$1"; + next unless -f $file; + push @found, { post => $post, delim => $delim, file => $file, name => $1 }; + } + } + return @found; +} + +my @embeddings = embeddings(); +die 'no "#INCLUDE:" inside a here-document was found; the scan no longer matches the install scripts' + unless @embeddings; + +my $scratch = tempdir(CLEANUP => 1); + +for my $e (@embeddings) { + my $label = "$e->{post} embeds $e->{name} in a <<'$e->{delim}' here-document"; + + open(my $fh, '<', $e->{file}) or die "cannot read $e->{file}: $!"; + my @body = <$fh>; + close $fh; + + my @collisions = grep { $body[$_] =~ /^\Q$e->{delim}\E\s*$/ } 0 .. $#body; + is(scalar @collisions, 0, + "$label, and no line of $e->{name} is \"$e->{delim}\"") + or diag("$e->{name} line(s) " . join(', ', map { $_ + 1 } @collisions) + . " end the here-document early"); + + # Assemble the embedding the way the template does and let bash parse it. bash reads the + # here-document up to the first delimiter line, so an early end leaves the rest of the + # postscript as commands. -n parses and runs nothing. + my $script = "$scratch/$e->{post}.$e->{name}.sh"; + open(my $out, '>', $script) or die "cannot write $script: $!"; + print $out "cat >\"\$1\" <<'$e->{delim}'\n", @body, "$e->{delim}\n"; + close $out; + + my $errors = qx{bash -n \Q$script\E 2>&1}; + is($?, 0, "$label, and bash parses the result") + or diag($errors); +} + +done_testing(); From b2d19b4afe187b7998cee1488899fd6f975b3e44 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Mon, 14 Sep 2026 20:12:31 -0300 Subject: [PATCH 5/7] fix(xcat-core): a diskfull install runs a post script bash cannot parse Every diskfull install stopped in the installer. The node installed the OS and answered ping, but no postscript ran, so remoteshell never wrote the root key and the management node got "Permission denied (publickey,password)". The node stayed at status powering-on and reinstalled in a loop. append_xcatpost_cleanup in xCAT/postscripts/xcatdsklspost writes the cleanup with a here-document whose delimiter is EOF, so the file holds a line "EOF". post.xcat, post.xcat.ng, post.xcat.rhels10, post.debian and the two s390x scripts embed the whole file with "#INCLUDE:#" inside "cat >/opt/xcat/xcatdsklspost << 'EOF'". That line ends the outer here-document early, and the remaining 890 lines of xcatdsklspost become shell code in the generated install script. bash reports a syntax error and curtin fails the late-command that runs it. The here-document now ends at XCATPOST_CLEANUP, and a comment states the constraint the file is under. postscript_heredoc_embedding.t assembles each embedding and parses it. It fails on the six install scripts without this change. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT/postscripts/xcatdsklspost | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index f8272561d..c725a80b0 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -255,14 +255,17 @@ append_xcatpost_cleanup() cleanupdiskfullxcatpost=`grep CLEANUPDISKFULLXCATPOST= "$mypostscript" |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` if [[ "$cleanupdiskfullxcatpost" =~ ^(1|yes|y)$ ]]; then - cat >> "$mypostscript" <> "$mypostscript" < Date: Tue, 15 Sep 2026 21:11:14 -0300 Subject: [PATCH 6/7] fix(xcat-core): postscript_heredoc_embedding.t passes when the file it reads is missing postscript_heredoc_embedding.t called plan skip_all when xCAT-server/share/xcat/install/scripts was absent, so a checkout that lost the file reported 0 tests and exit 0. A test that cannot fail measures nothing. Die instead, which is what makentp_ntp_deps.t already does for setupntp. With xCAT-server/share/xcat/install/scripts moved aside the file now exits 2 and prints " not found"; before this change it exited 0 and printed "1..0 # SKIP not found". With the file present the test passes either way. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-test/unit/postscript_heredoc_embedding.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xCAT-test/unit/postscript_heredoc_embedding.t b/xCAT-test/unit/postscript_heredoc_embedding.t index 6960761b8..32d6c17c6 100644 --- a/xCAT-test/unit/postscript_heredoc_embedding.t +++ b/xCAT-test/unit/postscript_heredoc_embedding.t @@ -18,7 +18,7 @@ use Test::More; my $root = "$FindBin::Bin/../.."; my $scriptdir = "$root/xCAT-server/share/xcat/install/scripts"; -plan skip_all => "$scriptdir not found" unless -d $scriptdir; +die "$scriptdir not found\n" unless -d $scriptdir; # Return every (post script, delimiter, embedded file) the install scripts declare. sub embeddings { From 9c2e733b990b2677cda46fec3af7f2c5d5cf9b39 Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:07:16 -0300 Subject: [PATCH 7/7] fix(xcatdsklspost): the diskful cleanup deleted a diskless node's postscripts site.cleanupdiskfullxcatpost names the node type it applies to, and site.5.rst says "on the diskfull nodes". xcatdsklspost serves every type: updatenode calls it for a diskless or statelite node as well, and the site value is one row that reaches all of them. With cleanupdiskfullxcatpost=yes and cleanupxcatpost=no, append_xcatpost_cleanup still appended the delete for those nodes. The diskful branch now reads NODESETSTATE from the generated mypostscript and appends nothing for netboot or statelite. That is the signal remoteshell, hardeths, configeth, otherpkgs and servicenode already use for this question, and mypostscript.tmpl exports it. cleanupxcatpost is unchanged. It names no node type and keeps applying to every one, which xcatdsklspost_xcatpost_cleanup.bats now asserts so a guard added to the wrong branch shows up. Four cases cover it: a netboot node and a statelite node keep their postscripts, a diskful node is still cleaned, and cleanupxcatpost still empties a netboot node. The first two fail against the parent commit. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- .../bats/xcatdsklspost_xcatpost_cleanup.bats | 49 +++++++++++++++++++ xCAT/postscripts/xcatdsklspost | 11 ++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats b/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats index b6658dcd4..60c95ed51 100644 --- a/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats +++ b/xCAT-test/bats/xcatdsklspost_xcatpost_cleanup.bats @@ -98,6 +98,55 @@ append_cleanup() [ ! -e "$XCATPOST/setroute" ] } +# cleanupdiskfullxcatpost names the node type it applies to. updatenode calls this script for a +# diskless or statelite node as well, and the site value is one row that reaches all of them, so +# without a guard a diskless node loses its postscripts to a setting that does not name it. +@test "a netboot node keeps its postscripts when site.cleanupdiskfullxcatpost is set" { + make_xcatpost + make_mypostscript 0 "NODESETSTATE='netboot'" "CLEANUPDISKFULLXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -f "$XCATPOST/setroute" ] + [ -f "$XCATPOST/_xcat/postscript.cfg" ] + # Nothing was appended, so the run cannot report a cleanup it did not do. + refute_grep -q 'cleanup of .* completed' "$MSGLOG" +} + +@test "a statelite node keeps its postscripts when site.cleanupdiskfullxcatpost is set" { + make_xcatpost + make_mypostscript 0 "NODESETSTATE='statelite'" "CLEANUPDISKFULLXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -f "$XCATPOST/setroute" ] +} + +@test "a diskful node is still cleaned when site.cleanupdiskfullxcatpost is set" { + make_xcatpost + make_mypostscript 0 "NODESETSTATE='install'" "CLEANUPDISKFULLXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ ! -e "$XCATPOST/setroute" ] + [ -f "$XCATPOST/updateflag.awk" ] +} + +# site.cleanupxcatpost names no node type, so it keeps applying to every one. A guard added to the +# wrong branch would show up here. +@test "site.cleanupxcatpost still applies to a netboot node" { + make_xcatpost + make_mypostscript 0 "NODESETSTATE='netboot'" "CLEANUPXCATPOST='yes'" + append_cleanup + + run bash "$MYPS" + [ "$status" -eq 0 ] + [ -z "$(ls -A "$XCATPOST")" ] +} + @test "site.cleanupxcatpost removes every file including updateflag.awk" { make_xcatpost make_mypostscript 0 "CLEANUPXCATPOST='yes'" "CLEANUPDISKFULLXCATPOST='no'" diff --git a/xCAT/postscripts/xcatdsklspost b/xCAT/postscripts/xcatdsklspost index c725a80b0..ffd209849 100755 --- a/xCAT/postscripts/xcatdsklspost +++ b/xCAT/postscripts/xcatdsklspost @@ -236,6 +236,12 @@ parsehttpserver () # after a failed run, so the postscripts stay on the node for diagnosis. # xcatinstallpost applies the same rule at install time. # +# cleanupdiskfullxcatpost names the node type it applies to, and this script serves +# every type: updatenode calls it for a diskless or statelite node as well. The site +# value is one row and reaches all of them, so the diskful branch reads NODESETSTATE +# and does nothing for netboot or statelite. cleanupxcatpost carries no such word and +# keeps applying everywhere. +# # $1 - path of the generated mypostscript # $2 - the xcatpost directory to remove the postscripts from ##################################################### @@ -253,8 +259,11 @@ append_xcatpost_cleanup() echo "rm -rf $postdir/*" >> "$mypostscript" fi + local nodesetstate + nodesetstate=`grep '^NODESETSTATE=' "$mypostscript" |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` cleanupdiskfullxcatpost=`grep CLEANUPDISKFULLXCATPOST= "$mypostscript" |awk -F = '{print $2}' | tr -d \'\" | tr A-Z a-z` - if [[ "$cleanupdiskfullxcatpost" =~ ^(1|yes|y)$ ]]; then + if [[ "$cleanupdiskfullxcatpost" =~ ^(1|yes|y)$ ]] \ + && [ "$nodesetstate" != "netboot" ] && [ "$nodesetstate" != "statelite" ]; then # post.xcat and the other install scripts embed this whole file in a here-document # that ends at a line "EOF". A line "EOF" here ends that here-document early and # leaves the rest of this file as shell code in the generated install script.