2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-04 12:07:56 +00:00

Merge pull request #7798 from VersatusHPC/refactor/xcatdsklspost-mypostscript-fetch

refactor(xcatdsklspost): share mypostscript fetch pipeline
This commit is contained in:
Daniel Hilst
2026-08-31 12:05:59 -03:00
committed by GitHub
3 changed files with 203 additions and 7 deletions
+184
View File
@@ -0,0 +1,184 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use File::Temp qw(tempdir tempfile);
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::More;
use XCAT::Test::File qw(repo_path);
my $postscript = repo_path(
File::Spec->catfile( 'xCAT', 'postscripts', 'xcatdsklspost' ) );
my $library = repo_path(
File::Spec->catfile( 'xCAT', 'postscripts', 'xcatlib.sh' ) );
is( system( 'bash', '-n', $postscript ), 0,
'xcatdsklspost retains valid Bash syntax' );
is( system( 'bash', '-n', $library ), 0,
'xcatlib retains valid Bash syntax' );
my ( $runner_fh, $runner ) = tempfile( UNLINK => 1 );
print {$runner_fh} <<'BASH';
source "$POST_TEST_LIBRARY"
xcatpost=$POST_TEST_ROOT
GETPOSTSCRIPT_ARGS=${POST_TEST_NODE-}
if [ "$POST_TEST_MODE" = "twice" ]; then
first=$(fetch_mypostscript "$xcatpost" $GETPOSTSCRIPT_ARGS)
first_status=$?
second=$(fetch_mypostscript "$xcatpost" $GETPOSTSCRIPT_ARGS)
second_status=$?
printf 'first_status=%s\nfirst=%s\n' "$first_status" "$first"
printf 'second_status=%s\nsecond=%s\n' "$second_status" "$second"
exit 0
fi
fetch_mypostscript "$xcatpost" $GETPOSTSCRIPT_ARGS
BASH
close($runner_fh);
sub run_fetch {
my (%options) = @_;
my $root = tempdir( CLEANUP => 1 );
my $responses = File::Spec->catdir( $root, 'responses' );
mkdir($responses) or die "Unable to create $responses: $!";
my $fetcher = File::Spec->catfile( $root, 'getpostscript.awk' );
write_file(
$fetcher,
<<'SH'
#!/bin/sh
count=0
if [ -r "$POST_TEST_COUNTER" ]; then
IFS= read -r count < "$POST_TEST_COUNTER"
fi
count=$((count + 1))
printf '%s\n' "$count" > "$POST_TEST_COUNTER"
printf 'argc=%s argv=%s\n' "$#" "$*" >> "$POST_TEST_ARGV"
cat "$POST_TEST_RESPONSES/$count"
SH
);
chmod( 0755, $fetcher ) or die "Unable to make $fetcher executable: $!";
my $index = 0;
for my $response ( @{ $options{responses} } ) {
$index++;
write_file( File::Spec->catfile( $responses, $index ), $response );
}
my $target = File::Spec->catfile( $root, 'mypostscript' );
write_file( $target, $options{preexisting} )
if exists $options{preexisting};
my $argv = File::Spec->catfile( $root, 'argv' );
my $counter = File::Spec->catfile( $root, 'counter' );
local %ENV = (
%ENV,
POST_TEST_ARGV => $argv,
POST_TEST_COUNTER => $counter,
POST_TEST_LIBRARY => $library,
POST_TEST_MODE => $options{mode} // 'single',
POST_TEST_NODE => $options{node} // '',
POST_TEST_RESPONSES => $responses,
POST_TEST_ROOT => $root,
);
open( my $output_fh, '-|', 'bash', '--noprofile', '--norc', $runner )
or die "Unable to run xcatdsklspost helper: $!";
my $output = do { local $/; <$output_fh> };
close($output_fh);
my $status = $? >> 8;
return {
argv => -e $argv ? read_file($argv) : '',
output => $output,
status => $status,
target => -e $target ? read_file($target) : undef,
};
}
sub write_file {
my ( $path, $contents ) = @_;
open( my $fh, '>:raw', $path ) or die "Unable to write $path: $!";
print {$fh} $contents;
close($fh) or die "Unable to close $path: $!";
}
sub read_file {
my ($path) = @_;
open( my $fh, '<:raw', $path ) or die "Unable to read $path: $!";
my $contents = do { local $/; <$fh> };
close($fh) or die "Unable to close $path: $!";
return $contents;
}
my $decoded = run_fetch(
node => 'node01',
responses => [ <<'XML' ],
<xcatresponse>
<data> MASTER=192.0.2.1</data>
<data> COMMAND=&lt;tag&gt; &amp; &quot;quoted&quot; &apos;single&apos;</data>
<data> LITERAL=&amp;lt;</data>
<data> </data>
<info>ignored</info>
</xcatresponse>
XML
);
is( $decoded->{status}, 0, 'a response containing MASTER succeeds' );
is( $decoded->{output}, "MASTER=192.0.2.1\n",
'the helper returns the MASTER content used by the caller' );
is(
$decoded->{target},
"MASTER=192.0.2.1\nCOMMAND=<tag> & \"quoted\" 'single'\nLITERAL=&lt;\n",
'the helper strips XML, empty lines, indentation, and decodes entities'
);
is( $decoded->{argv}, "argc=1 argv=node01\n",
'the short node name is passed to getpostscript.awk' );
my $without_node = run_fetch(
responses => [ "<data>MASTER=198.51.100.8</data>\n" ],
);
is( $without_node->{status}, 0, 'a fetch without a node name succeeds' );
is( $without_node->{argv}, "argc=0 argv=\n",
'an empty node name does not add an argument' );
my $overwrite = run_fetch(
preexisting => "MASTER=stale\n",
responses => [ "<data>POSTSCRIPT=ready</data>\n" ],
);
isnt( $overwrite->{status}, 0, 'a response without MASTER is incomplete' );
is( $overwrite->{output}, '', 'an incomplete response returns no MASTER content' );
is( $overwrite->{target}, "POSTSCRIPT=ready\n",
'each fetch overwrites the previous mypostscript' );
my $empty = run_fetch( responses => [''] );
isnt( $empty->{status}, 0, 'an empty response is incomplete' );
is( $empty->{output}, '', 'an empty response returns no MASTER content' );
is( $empty->{target}, '', 'an empty response leaves an empty output file' );
my $retry = run_fetch(
mode => 'twice',
node => 'node02',
responses => [
"<data>POSTSCRIPT=not-ready</data>\n",
"<data>MASTER=203.0.113.7</data>\n<data>POSTSCRIPT=ready</data>\n",
],
);
is( $retry->{status}, 0, 'two consecutive fetches complete' );
is(
$retry->{output},
"first_status=1\nfirst=\nsecond_status=0\nsecond=MASTER=203.0.113.7\n",
'a later response supplies the MASTER content used to stop retries'
);
is(
$retry->{target},
"MASTER=203.0.113.7\nPOSTSCRIPT=ready\n",
'the successful retry replaces the incomplete response'
);
is( $retry->{argv}, "argc=1 argv=node02\nargc=1 argv=node02\n",
'each fetch retry passes the same short node name' );
done_testing();
+3 -7
View File
@@ -182,7 +182,6 @@ download_mypostscript()
}
# pmatch determines if 1st argument string is matched by 2nd argument pattern
pmatch ()
@@ -680,6 +679,7 @@ fi
# We need to call getpostscript.awk .
if [ ! -x /$xcatpost/mypostscript ]; then
. /$xcatpost/xcatlib.sh
echolog "debug" "no pre-generated mypostscript.<nodename>, trying to get it with getpostscript.awk..."
GETPOSTSCRIPT_ARGS=""
if [ -n "$node_short" ]; then
@@ -699,10 +699,7 @@ if [ ! -x /$xcatpost/mypostscript ]; then
useflowcontrol=0
fi
fi
/$xcatpost/getpostscript.awk $GETPOSTSCRIPT_ARGS | egrep '<data>' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/&lt;/</g' -e 's/&gt;/>/g' -e 's/&amp;/\&/g' -e 's/&quot;/"/g' -e "s/&apos;/'/g" > /$xcatpost/mypostscript;
MYCONT=`grep MASTER /$xcatpost/mypostscript`
MYCONT=`fetch_mypostscript "$xcatpost" $GETPOSTSCRIPT_ARGS`
MAX_RETRIES=10
RETRY=0
while [ -z "$MYCONT" ]; do
@@ -733,8 +730,7 @@ if [ ! -x /$xcatpost/mypostscript ]; then
useflowcontrol=0
fi
fi
/$xcatpost/getpostscript.awk $GETPOSTSCRIPT_ARGS | egrep '<data>' | sed -e 's/<[^>]*>//g'|egrep -v '^ *$'|sed -e 's/^ *//' | sed -e 's/&lt;/</g' -e 's/&gt;/>/g' -e 's/&amp;/\&/g' -e 's/&quot;/"/g' -e "s/&apos;/'/g" > /$xcatpost/mypostscript;
MYCONT=`grep MASTER /$xcatpost/mypostscript`
MYCONT=`fetch_mypostscript "$xcatpost" $GETPOSTSCRIPT_ARGS`
if [ ! -z "$MYCONT" ]; then
break;
fi
+16
View File
@@ -832,3 +832,19 @@ function msgutil_r {
function msgutil {
msgutil_r "" "$@"
}
function fetch_mypostscript {
local postroot
postroot=$1
shift
/$postroot/getpostscript.awk "$@" |
egrep '<data>' |
sed -e 's/<[^>]*>//g' |
egrep -v '^ *$' |
sed -e 's/^ *//' |
sed -e 's/&lt;/</g' -e 's/&gt;/>/g' -e 's/&amp;/\&/g' \
-e 's/&quot;/"/g' -e "s/&apos;/'/g" > /$postroot/mypostscript
grep MASTER /$postroot/mypostscript
}