mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-05 04:27:55 +00:00
Merge pull request #7793 from VersatusHPC/refactor/nm-autoconnect
refactor(netboot): share NetworkManager autoconnect setup
This commit is contained in:
@@ -6,15 +6,7 @@
|
||||
[ "$MASTER_IP" ] || export MASTER_IP="#ENV:MASTER_IP#"
|
||||
#INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/scriptlib#
|
||||
|
||||
if command -v nmcli >/dev/null 2>&1; then
|
||||
nmcli -g NAME,STATE con show | \
|
||||
awk -F: '$1 != "lo" && $2 == "activated" {print $1}' | \
|
||||
while IFS= read -r con_name
|
||||
do
|
||||
[ -n "$con_name" ] || continue
|
||||
nmcli con mod "$con_name" connection.autoconnect yes
|
||||
done
|
||||
fi
|
||||
xcat_enable_active_nm_autoconnect
|
||||
|
||||
internet_repo_file_list="oracle-linux-ol10.repo uek-ol10.repo Rocky-AppStream.repo Rocky-BaseOS.repo Rocky-Extras.repo rocky.repo rocky-extras.repo CentOS-Base.repo centos.repo centos-addons.repo almalinux-ha.repo almalinux-nfv.repo almalinux-powertools.repo almalinux.repo almalinux-resilientstorage.repo almalinux-rt.repo"
|
||||
|
||||
|
||||
@@ -6,22 +6,6 @@
|
||||
[ "$MASTER_IP" ] || export MASTER_IP="#ENV:MASTER_IP#"
|
||||
#INCLUDE:#ENV:XCATROOT#/share/xcat/install/scripts/scriptlib#
|
||||
|
||||
activate_nm_connections()
|
||||
{
|
||||
nmcli -g NAME,STATE con show | \
|
||||
awk -F: '$1 != "lo" && $2 == "activated" {print $1}' | \
|
||||
while IFS= read -r con_name
|
||||
do
|
||||
[ -n "$con_name" ] || continue
|
||||
case "$XCATDEBUGMODE" in
|
||||
"1"|"2")
|
||||
msgutil_r "$MASTER_IP" "info" "set connection $con_name to be activated on system boot" "/var/log/xcat/xcat.log"
|
||||
;;
|
||||
esac
|
||||
nmcli con mod "$con_name" connection.autoconnect yes
|
||||
done
|
||||
}
|
||||
|
||||
activated_ifcfg=0
|
||||
if compgen -G "/etc/sysconfig/network-scripts/ifcfg-*" >/dev/null 2>&1; then
|
||||
for i in /etc/sysconfig/network-scripts/ifcfg-*
|
||||
@@ -40,11 +24,11 @@ if compgen -G "/etc/sysconfig/network-scripts/ifcfg-*" >/dev/null 2>&1; then
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$activated_ifcfg" -eq 0 ] && command -v nmcli >/dev/null 2>&1; then
|
||||
activate_nm_connections
|
||||
if [ "$activated_ifcfg" -eq 0 ]; then
|
||||
xcat_enable_active_nm_autoconnect 1
|
||||
fi
|
||||
elif command -v nmcli >/dev/null 2>&1; then
|
||||
activate_nm_connections
|
||||
else
|
||||
xcat_enable_active_nm_autoconnect 1
|
||||
fi
|
||||
|
||||
# List of internal repos to be disabled
|
||||
|
||||
@@ -43,3 +43,23 @@ declare -F msgutil &>/dev/null || function msgutil {
|
||||
msgutil_r "" "$@"
|
||||
}
|
||||
|
||||
declare -F xcat_enable_active_nm_autoconnect &>/dev/null || function xcat_enable_active_nm_autoconnect {
|
||||
local log_changes="${1:-}"
|
||||
|
||||
command -v nmcli >/dev/null 2>&1 || return 0
|
||||
|
||||
nmcli -g NAME,STATE con show | \
|
||||
awk -F: '$1 != "lo" && $2 == "activated" {print $1}' | \
|
||||
while IFS= read -r con_name
|
||||
do
|
||||
[ -n "$con_name" ] || continue
|
||||
if [ -n "$log_changes" ]; then
|
||||
case "$XCATDEBUGMODE" in
|
||||
"1"|"2")
|
||||
msgutil_r "$MASTER_IP" "info" "set connection $con_name to be activated on system boot" "/var/log/xcat/xcat.log"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
nmcli con mod "$con_name" connection.autoconnect yes
|
||||
done
|
||||
}
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
#!/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;
|
||||
}
|
||||
Reference in New Issue
Block a user