mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-04 12:07:56 +00:00
285 lines
7.9 KiB
Perl
285 lines
7.9 KiB
Perl
#!/usr/bin/env perl
|
|
use strict;
|
|
use warnings;
|
|
|
|
use File::Path qw(make_path);
|
|
use File::Spec;
|
|
use File::Temp qw(tempdir);
|
|
use FindBin;
|
|
use lib "$FindBin::Bin/../lib";
|
|
use Test::More;
|
|
|
|
use XCAT::Test::File qw(repo_path slurp_repo_file);
|
|
|
|
my $scriptlib = repo_path(
|
|
File::Spec->catfile(
|
|
'xCAT-server', 'share', 'xcat', 'install', 'scripts', 'scriptlib'
|
|
)
|
|
);
|
|
-r $scriptlib or BAIL_OUT("$scriptlib is required");
|
|
|
|
is( system( 'bash', '-n', $scriptlib ), 0,
|
|
'the install script library has valid Bash syntax' );
|
|
|
|
my $tmpdir = tempdir( CLEANUP => 1 );
|
|
my $test_bin = File::Spec->catdir( $tmpdir, 'bin' );
|
|
my $empty_bin = File::Spec->catdir( $tmpdir, 'empty-bin' );
|
|
make_path( $test_bin, $empty_bin );
|
|
|
|
my $nmcli_log = File::Spec->catfile( $tmpdir, 'nmcli.log' );
|
|
my $message_log = File::Spec->catfile( $tmpdir, 'messages.log' );
|
|
my $fake_nmcli = File::Spec->catfile( $test_bin, 'nmcli' );
|
|
write_file( $fake_nmcli, <<'SH' );
|
|
#!/bin/sh
|
|
{
|
|
printf 'nmcli'
|
|
for argument in "$@"; do
|
|
printf '\t<%s>' "$argument"
|
|
done
|
|
printf '\n'
|
|
} >>"$XCAT_TEST_NMCLI_LOG"
|
|
|
|
if [ "$#" -eq 4 ] && [ "$1" = '-g' ] && [ "$2" = 'NAME,STATE' ] &&
|
|
[ "$3" = 'con' ] && [ "$4" = 'show' ]; then
|
|
printf '%s' "$XCAT_TEST_NMCLI_OUTPUT"
|
|
fi
|
|
SH
|
|
chmod 0755, $fake_nmcli or die "Unable to make $fake_nmcli executable: $!";
|
|
|
|
my $driver = File::Spec->catfile( $tmpdir, 'run-helper' );
|
|
write_file( $driver, <<'SH' );
|
|
#!/bin/bash
|
|
msgutil_r() {
|
|
{
|
|
printf 'msgutil_r'
|
|
for argument in "$@"; do
|
|
printf '\t<%s>' "$argument"
|
|
done
|
|
printf '\n'
|
|
} >>"$XCAT_TEST_MESSAGE_LOG"
|
|
}
|
|
. "$XCAT_TEST_SCRIPTLIB"
|
|
xcat_enable_active_nm_autoconnect "$@"
|
|
SH
|
|
chmod 0755, $driver or die "Unable to make $driver executable: $!";
|
|
|
|
my $connections = join( "\n",
|
|
'primary uplink:activated', 'backup:deactivated',
|
|
'lo:activated', 'storage fabric:activated',
|
|
':activated', '' ) . "\n";
|
|
|
|
is( run_program( $driver, connections => $connections ), 0,
|
|
'the helper updates active non-loopback connections' );
|
|
is(
|
|
read_file($nmcli_log),
|
|
command_line( '-g', 'NAME,STATE', 'con', 'show' )
|
|
. command_line( 'con', 'mod', 'primary uplink',
|
|
'connection.autoconnect', 'yes' )
|
|
. command_line( 'con', 'mod', 'storage fabric',
|
|
'connection.autoconnect', 'yes' ),
|
|
'inactive, loopback, and blank connections are skipped without splitting names'
|
|
);
|
|
is( read_file($message_log), '',
|
|
'logging stays disabled when the caller does not request it' );
|
|
|
|
is(
|
|
run_program(
|
|
$driver,
|
|
arguments => ['1'],
|
|
connections => "primary uplink:activated\n",
|
|
debug => '1'
|
|
),
|
|
0,
|
|
'the helper accepts the legacy logging mode'
|
|
);
|
|
is(
|
|
read_file($message_log),
|
|
message_line(
|
|
'192.0.2.10', 'info',
|
|
'set connection primary uplink to be activated on system boot',
|
|
'/var/log/xcat/xcat.log'
|
|
),
|
|
'debug mode logs the same connection activation message'
|
|
);
|
|
|
|
is(
|
|
run_program(
|
|
$driver,
|
|
arguments => ['1'],
|
|
connections => "primary uplink:activated\n",
|
|
debug => '2'
|
|
),
|
|
0,
|
|
'the helper preserves extended debug logging'
|
|
);
|
|
is(
|
|
read_file($message_log),
|
|
message_line(
|
|
'192.0.2.10', 'info',
|
|
'set connection primary uplink to be activated on system boot',
|
|
'/var/log/xcat/xcat.log'
|
|
),
|
|
'extended debug mode logs the same connection activation message'
|
|
);
|
|
|
|
is(
|
|
run_program(
|
|
$driver,
|
|
arguments => ['1'],
|
|
connections => "primary uplink:activated\n",
|
|
debug => '0'
|
|
),
|
|
0,
|
|
'the legacy logging mode also supports non-debug operation'
|
|
);
|
|
is( read_file($message_log), '',
|
|
'non-debug operation does not emit the optional message' );
|
|
|
|
is(
|
|
run_program(
|
|
$driver,
|
|
arguments => ['1'],
|
|
connections => "primary uplink:activated\n",
|
|
debug => '1',
|
|
nmcli => 0
|
|
),
|
|
0,
|
|
'the helper is a successful no-op without nmcli'
|
|
);
|
|
is( read_file($nmcli_log), '', 'nmcli is not invoked when it is unavailable' );
|
|
is( read_file($message_log), '',
|
|
'missing nmcli does not produce a connection activation message' );
|
|
|
|
my $rhels8 = stage_rendered_postscript('post.rhels8');
|
|
my $rhels10 = stage_rendered_postscript('post.rhels10');
|
|
|
|
is(
|
|
run_program(
|
|
$rhels8,
|
|
connections => "primary uplink:activated\n",
|
|
debug => '1'
|
|
),
|
|
0,
|
|
'the EL8 and EL9 install postscript uses the shared helper'
|
|
);
|
|
is(
|
|
read_file($message_log),
|
|
message_line(
|
|
'192.0.2.10', 'info',
|
|
'set connection primary uplink to be activated on system boot',
|
|
'/var/log/xcat/xcat.log'
|
|
),
|
|
'the EL8 and EL9 caller preserves connection activation logging'
|
|
);
|
|
is(
|
|
read_file($nmcli_log),
|
|
command_line( '-g', 'NAME,STATE', 'con', 'show' )
|
|
. command_line( 'con', 'mod', 'primary uplink',
|
|
'connection.autoconnect', 'yes' ),
|
|
'the EL8 and EL9 caller passes the connection name unchanged'
|
|
);
|
|
|
|
is(
|
|
run_program(
|
|
$rhels10,
|
|
connections => "primary uplink:activated\n",
|
|
debug => '1'
|
|
),
|
|
0,
|
|
'the EL10 install postscript uses the shared helper'
|
|
);
|
|
is( read_file($message_log), '',
|
|
'the EL10 caller keeps connection activation logging disabled' );
|
|
is(
|
|
read_file($nmcli_log),
|
|
command_line( '-g', 'NAME,STATE', 'con', 'show' )
|
|
. command_line( 'con', 'mod', 'primary uplink',
|
|
'connection.autoconnect', 'yes' ),
|
|
'the EL10 caller passes the connection name unchanged'
|
|
);
|
|
|
|
done_testing();
|
|
|
|
sub command_line {
|
|
return join( '', 'nmcli', map { "\t<$_>" } @_ ) . "\n";
|
|
}
|
|
|
|
sub message_line {
|
|
return join( '', 'msgutil_r', map { "\t<$_>" } @_ ) . "\n";
|
|
}
|
|
|
|
sub run_program {
|
|
my ( $program, %options ) = @_;
|
|
my $arguments = $options{arguments} // [];
|
|
my $has_nmcli = exists( $options{nmcli} ) ? $options{nmcli} : 1;
|
|
|
|
write_file( $nmcli_log, '' );
|
|
write_file( $message_log, '' );
|
|
|
|
local %ENV = %ENV;
|
|
$ENV{PATH} = $has_nmcli ? "$test_bin:$ENV{PATH}" : $empty_bin;
|
|
$ENV{XCATDEBUGMODE} = $options{debug} // '0';
|
|
$ENV{MASTER_IP} = '192.0.2.10';
|
|
$ENV{XCAT_TEST_MESSAGE_LOG} = $message_log;
|
|
$ENV{XCAT_TEST_NMCLI_LOG} = $nmcli_log;
|
|
$ENV{XCAT_TEST_NMCLI_OUTPUT} = $options{connections} // '';
|
|
$ENV{XCAT_TEST_SCRIPTLIB} = $scriptlib;
|
|
|
|
my $status = system( '/bin/bash', $program, @{$arguments} );
|
|
return $status == -1 ? 255 : $status >> 8;
|
|
}
|
|
|
|
sub stage_rendered_postscript {
|
|
my ($name) = @_;
|
|
my $postscript = slurp_repo_file(
|
|
File::Spec->catfile(
|
|
'xCAT-server', 'share', 'xcat', 'install', 'scripts', $name
|
|
)
|
|
);
|
|
my $library = slurp_repo_file(
|
|
File::Spec->catfile(
|
|
'xCAT-server', 'share', 'xcat', 'install', 'scripts', 'scriptlib'
|
|
)
|
|
);
|
|
my $include = '#INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/scriptlib#';
|
|
$postscript =~ s/^\Q$include\E$/$library/m
|
|
or BAIL_OUT("Unable to render the scriptlib include in $name");
|
|
|
|
my $preamble = <<'SH';
|
|
compgen() { return 1; }
|
|
sed() { :; }
|
|
msgutil_r() {
|
|
{
|
|
printf 'msgutil_r'
|
|
for argument in "$@"; do
|
|
printf '\t<%s>' "$argument"
|
|
done
|
|
printf '\n'
|
|
} >>"$XCAT_TEST_MESSAGE_LOG"
|
|
}
|
|
SH
|
|
$postscript =~ s/\A(#![^\n]*\n)/$1$preamble/
|
|
or BAIL_OUT("Unable to stage the test preamble in $name");
|
|
|
|
my $destination = File::Spec->catfile( $tmpdir, $name );
|
|
write_file( $destination, $postscript );
|
|
chmod 0755, $destination
|
|
or die "Unable to make $destination executable: $!";
|
|
return $destination;
|
|
}
|
|
|
|
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;
|
|
}
|