mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-05-17 11:54:16 +00:00
fix: skip disabled IPMI user slots in bmcsetup
bmcsetup iterated every user slot and retried ipmitool user disable for slots that were already disabled. Lenovo XCC reports those attempts as Invalid data field in request, so discovery can spend minutes retrying no-op disables. Read the current user table once per BMC, keep the old fallback when the table cannot be read, and disable only non-target slots whose IPMI Msg flag is true. Also use the loop's current username when resolving the target slot and keep the intended userslot 2 fallback assignment. Fixes xcat2/xcat-core#5065
This commit is contained in:
@@ -481,9 +481,27 @@ for user in $BMCUS; do
|
||||
if [ "$user" = "" ]; then
|
||||
continue
|
||||
fi
|
||||
DISABLEUSERS=$(ipmitool user list $LANCHAN|awk '{print $1}'|grep -v ID)
|
||||
if USERLIST=$(ipmitool -d $idev user list "$LANCHAN") && [ -n "$USERLIST" ]; then
|
||||
DISABLEUSERS=$(echo "$USERLIST" | awk '$1 != "ID" && $1 ~ /^[0-9]+$/ {print $1}')
|
||||
ENABLEDUSERS=$(echo "$USERLIST" | awk '
|
||||
$1 == "ID" { next }
|
||||
$1 !~ /^[0-9]+$/ { next }
|
||||
{
|
||||
ipmi_msg = $(NF - 1)
|
||||
if ($(NF - 1) == "NO" && $NF == "ACCESS") {
|
||||
ipmi_msg = $(NF - 2)
|
||||
}
|
||||
if (ipmi_msg == "true") {
|
||||
print $1
|
||||
}
|
||||
}')
|
||||
else
|
||||
DISABLEUSERS=$(ipmitool user list "$LANCHAN"|awk '{print $1}'|grep -v ID)
|
||||
ENABLEDUSERS="$DISABLEUSERS"
|
||||
logger -s -t $log_label -p local4.warning "Could not read IPMI user list for device $idev, falling back to disabling all non-target users"
|
||||
fi
|
||||
# Get the User Slots
|
||||
USERSLOT=`ipmitool -d $idev user list $LANCHAN |grep -v ^ID|awk '{print $1 " " $2}'|grep -w "$BMCUS"|awk '{print $1}'`
|
||||
USERSLOT=$(echo "$USERLIST" | awk -v user="$user" '$1 != "ID" && $2 == user {print $1; exit}')
|
||||
if [ -z "$USERSLOT" ]; then
|
||||
USERSLOT=$((`ipmitool raw 6 0x44 1 1|awk '{print $3}'` + 1))
|
||||
fi
|
||||
@@ -498,7 +516,7 @@ for user in $BMCUS; do
|
||||
done
|
||||
fi
|
||||
# fall back to userslot 2 as a last resort
|
||||
if [ "$USERSLOT" == 0 ]; then $USERSLOT = 2; fi
|
||||
if [ "$USERSLOT" = 0 ]; then USERSLOT=2; fi
|
||||
if [ "$ISITE" = 1 ]; then
|
||||
allowcred.awk &
|
||||
CREDPID=$!
|
||||
@@ -510,13 +528,15 @@ for user in $BMCUS; do
|
||||
fi
|
||||
|
||||
# Get the specified user
|
||||
CURRENTUSER=`ipmitool -d $idev user list $LANCHAN|grep ^$USERSLOT|awk '{print $2}'`
|
||||
DISABLEUSERS=`echo $DISABLEUSERS|sed -e s/$USERSLOT//`
|
||||
CURRENTUSER=$(echo "$USERLIST" | awk -v slot="$USERSLOT" '$1 == slot {print $2; exit}')
|
||||
DISABLEUSERS=$(echo "$DISABLEUSERS" | awk -v slot="$USERSLOT" '$1 != slot {print $1}')
|
||||
logger -s -t $log_label -p local4.info "CURRENTUSER=$CURRENTUSER, DISABLEUSERS=$DISABLEUSERS"
|
||||
for userid in $DISABLEUSERS; do
|
||||
TRIES=0
|
||||
# user disable is not idempotent on several BMCs; skip slots already disabled.
|
||||
echo "$ENABLEDUSERS" | grep -q "^${userid}$" || continue
|
||||
# Disable the non-specified user
|
||||
while ! ipmitool -d $idev user disable $userid; do
|
||||
while ! ipmitool -d $idev user disable "$userid"; do
|
||||
sleep 1
|
||||
let TRIES=TRIES+1
|
||||
if [ $TRIES -gt $TIMEOUT ]; then break; fi
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Path qw(make_path);
|
||||
use File::Temp qw(tempdir);
|
||||
use FindBin;
|
||||
use Test::More;
|
||||
|
||||
my $bmcsetup = "$FindBin::Bin/../../xCAT-genesis-scripts/usr/bin/bmcsetup";
|
||||
plan skip_all => 'bmcsetup script not found' unless -x $bmcsetup;
|
||||
|
||||
my $ipmicfg = '/tmp/ipmicfg.xml';
|
||||
my $cleanup_ipmicfg = !-e $ipmicfg;
|
||||
plan skip_all => "$ipmicfg already exists" unless $cleanup_ipmicfg;
|
||||
END {
|
||||
unlink $ipmicfg if $cleanup_ipmicfg && -e $ipmicfg;
|
||||
}
|
||||
|
||||
my $tmpdir = tempdir(CLEANUP => 1);
|
||||
my $bindir = "$tmpdir/bin";
|
||||
make_path($bindir);
|
||||
|
||||
write_executable(
|
||||
"$bindir/ipmitool",
|
||||
<<'EOF'
|
||||
#!/bin/sh
|
||||
echo "$@" >> "$IPMITOOL_CALL_LOG"
|
||||
|
||||
if [ "$1" = "-V" ]; then
|
||||
echo "ipmitool version 1.8.19"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$1" = "-d" ]; then
|
||||
shift 2
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
mc)
|
||||
if [ "$2" = "info" ]; then
|
||||
cat <<MCINFO
|
||||
IPMI Version : 2.0
|
||||
Manufacturer ID : 10876
|
||||
Product ID : 2437
|
||||
MCINFO
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
channel)
|
||||
if [ "$2" = "info" ]; then
|
||||
echo "Channel Medium Type : 802.3"
|
||||
exit 0
|
||||
fi
|
||||
if [ "$2" = "getaccess" ]; then
|
||||
echo "Fixed Name : No"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
user)
|
||||
case "$2" in
|
||||
list)
|
||||
cat "$IPMITOOL_USER_LIST"
|
||||
exit 0
|
||||
;;
|
||||
disable)
|
||||
echo "$3" >> "$IPMITOOL_DISABLE_LOG"
|
||||
exit 0
|
||||
;;
|
||||
enable|priv|set)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
raw|lan|chassis)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
);
|
||||
|
||||
write_executable("$bindir/logger", "#!/bin/sh\nexit 0\n");
|
||||
write_executable("$bindir/modprobe", "#!/bin/sh\nexit 0\n");
|
||||
write_executable("$bindir/sleep", "#!/bin/sh\nexit 0\n");
|
||||
write_executable("$bindir/updateflag.awk", "#!/bin/sh\nexit 0\n");
|
||||
write_executable("$bindir/remoteimmsetup", "#!/bin/sh\nexit 0\n");
|
||||
write_executable("$bindir/allowcred.awk", "#!/bin/sh\nexit 0\n");
|
||||
write_executable(
|
||||
"$bindir/getipmi",
|
||||
<<'EOF'
|
||||
#!/bin/sh
|
||||
cat > /tmp/ipmicfg.xml <<IPMICFG
|
||||
<bmcip>10.0.0.2</bmcip>
|
||||
<taggedvlan>off</taggedvlan>
|
||||
<gateway>10.0.0.1</gateway>
|
||||
<netmask>255.255.255.0</netmask>
|
||||
<username>USERID</username>
|
||||
<password>passw0rd</password>
|
||||
<ipcfgmethod>static</ipcfgmethod>
|
||||
IPMICFG
|
||||
exit 0
|
||||
EOF
|
||||
);
|
||||
|
||||
my $user_list = "$tmpdir/user-list.txt";
|
||||
write_file(
|
||||
$user_list,
|
||||
<<'EOF'
|
||||
ID Name Callin Link Auth IPMI Msg Channel Priv Limit
|
||||
1 true false false NO ACCESS
|
||||
2 USERID true true true ADMINISTRATOR
|
||||
3 true false false NO ACCESS
|
||||
4 olduser true true true ADMINISTRATOR
|
||||
5 viewer true true false NO ACCESS
|
||||
EOF
|
||||
);
|
||||
|
||||
my $call_log = "$tmpdir/ipmitool-calls.log";
|
||||
my $disable_log = "$tmpdir/disabled-users.log";
|
||||
|
||||
local $ENV{PATH} = "$bindir:$ENV{PATH}";
|
||||
local $ENV{IPMITOOL_USER_LIST} = $user_list;
|
||||
local $ENV{IPMITOOL_CALL_LOG} = $call_log;
|
||||
local $ENV{IPMITOOL_DISABLE_LOG} = $disable_log;
|
||||
|
||||
my $output = `bash "$bmcsetup" 2>&1`;
|
||||
my $rc = $? >> 8;
|
||||
is($rc, 0, 'bmcsetup exits successfully with stubbed IPMI commands')
|
||||
or diag($output);
|
||||
|
||||
my @disabled = read_lines($disable_log);
|
||||
is_deeply(\@disabled, ['4'], 'bmcsetup disables only enabled non-target user slots');
|
||||
|
||||
my @calls = read_lines($call_log);
|
||||
ok(
|
||||
!grep({ /user disable (1|3|5)\b/ } @calls),
|
||||
'bmcsetup does not retry user disable for slots that are already disabled'
|
||||
);
|
||||
|
||||
done_testing();
|
||||
|
||||
sub write_executable {
|
||||
my ($path, $content) = @_;
|
||||
write_file($path, $content);
|
||||
chmod 0755, $path or die "chmod $path: $!";
|
||||
}
|
||||
|
||||
sub write_file {
|
||||
my ($path, $content) = @_;
|
||||
open(my $fh, '>', $path) or die "open $path: $!";
|
||||
print {$fh} $content;
|
||||
close($fh) or die "close $path: $!";
|
||||
}
|
||||
|
||||
sub read_lines {
|
||||
my ($path) = @_;
|
||||
return () unless -e $path;
|
||||
open(my $fh, '<', $path) or die "open $path: $!";
|
||||
my @lines = <$fh>;
|
||||
close($fh) or die "close $path: $!";
|
||||
chomp @lines;
|
||||
return @lines;
|
||||
}
|
||||
Reference in New Issue
Block a user