diff --git a/xCAT-genesis-scripts/usr/bin/bmcsetup b/xCAT-genesis-scripts/usr/bin/bmcsetup index 7344aaeeb..9ccb147a8 100755 --- a/xCAT-genesis-scripts/usr/bin/bmcsetup +++ b/xCAT-genesis-scripts/usr/bin/bmcsetup @@ -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 diff --git a/xCAT-test/unit/bmcsetup_disable_users.t b/xCAT-test/unit/bmcsetup_disable_users.t new file mode 100644 index 000000000..a9933e8e1 --- /dev/null +++ b/xCAT-test/unit/bmcsetup_disable_users.t @@ -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 <> "$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 <10.0.0.2 +off +10.0.0.1 +255.255.255.0 +USERID +passw0rd +static +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; +}