Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions xCAT-server/lib/xcat/plugins/ipmi.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7653,15 +7653,11 @@ sub initsdr_withrepinfo {


if ($sessdata->{sdr_info}->{version} != 0x51) {
sendoutput(1, "SDR version unsupported.");
xCAT::SvrUtils::sendmsg([ 1, "SDR version unsupported." ], $callback, $sessdata->{node}, %allerrornodes);
return (1); #bail, do not try to continue
}

if ($sessdata->{sdr_info}->{resv_sdr} != 1) {
sendoutput(1, "SDR reservation unsupported.");
return 1;
}

# Some BMCs grant a reservation that Get SDR Repository Info does not advertise.
$sessdata->{ipmisession}->subcmd(netfn => 0x0a, command => 0x22, data => [], callback => \&reserved_sdr_repo, callback_args => $sessdata);
}

Expand Down Expand Up @@ -7695,7 +7691,7 @@ sub start_sdr_record {
my $rsp = shift;
my $sessdata = shift;
if ($rsp->{error}) {
sendoutput(1, $rsp->{error});
xCAT::SvrUtils::sendmsg([ 1, $rsp->{error} ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
my $resv_id_ls = shift @{ $sessdata->{sdr_fetch_args} };
Expand All @@ -7709,7 +7705,7 @@ sub start_sdr_record {
if (!$text) {
$text = sprintf("unknown response %02x", $code);
}
sendoutput(1, $text);
xCAT::SvrUtils::sendmsg([ 1, $text ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
$sessdata->{sdr_nrid_ls} = $returnd[1];
Expand Down Expand Up @@ -7763,7 +7759,7 @@ sub add_sdr_data {
my $numbytes = $sessdata->{sdr_fetch_args}->[5];
my $offset = $sessdata->{sdr_offset}; #shorten typing a little
if ($rsp->{error}) {
sendoutput([ 1, $rsp->{error} ]);
xCAT::SvrUtils::sendmsg([ 1, $rsp->{error} ], $callback, $sessdata->{node}, %allerrornodes);
return; #give up
}
my @returnd = ($rsp->{code}, @{ $rsp->{data} });
Expand All @@ -7773,7 +7769,7 @@ sub add_sdr_data {
if (!$text) {
$text = sprintf("unknown response %02x", $code);
}
sendoutput([ 1, $text ]);
xCAT::SvrUtils::sendmsg([ 1, $text ], $callback, $sessdata->{node}, %allerrornodes);
return; #abort the whole mess
}
push @{ $sessdata->{sdr_data} }, @returnd[ 3 .. @returnd - 1 ];
Expand Down Expand Up @@ -7996,7 +7992,7 @@ sub gotdevid {
my $text;

if ($rsp->{error}) {
sendoutput([ 1, $rsp->{error} ]);
xCAT::SvrUtils::sendmsg([ 1, $rsp->{error} ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
else {
Expand All @@ -8007,7 +8003,7 @@ sub gotdevid {
if (!$text) {
$text = sprintf("unknown response %02x", $code);
}
sendoutput([ 1, $text ]);
xCAT::SvrUtils::sendmsg([ 1, $text ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
}
Expand Down Expand Up @@ -8093,7 +8089,7 @@ sub got_sdr_rep_info {
my $sessdata = shift;

if ($rsp->{error}) {
sendoutput([ 1, $rsp->{error} ]);
xCAT::SvrUtils::sendmsg([ 1, $rsp->{error} ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
else {
Expand All @@ -8104,7 +8100,7 @@ sub got_sdr_rep_info {
if (!$text) {
$text = sprintf("unknown response %02x", $code);
}
sendoutput(1, $text);
xCAT::SvrUtils::sendmsg([ 1, $text ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
}
Expand All @@ -8119,18 +8115,21 @@ sub reserved_sdr_repo {
my $rsp = shift;
my $sessdata = shift;
if ($rsp->{error}) {
sendoutput([ 1, $rsp->{error} ]);
xCAT::SvrUtils::sendmsg([ 1, $rsp->{error} ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
else {
my $code = $rsp->{code};

if ($code != 0x00) {
my $text = $codes{$code};
if (!$text) {
if ($code == 0xc1 && !$sessdata->{sdr_info}->{resv_sdr}) {
$text = "SDR reservation unsupported.";
} elsif (!$text) {
$text = sprintf("unknown response %02x", $code);
}
sendoutput([ 1, $text ]);
xCAT::SvrUtils::sendmsg([ 1, $text ], $callback, $sessdata->{node}, %allerrornodes);
return;
}
}
my @returnd = @{ $rsp->{data} };
Expand Down
131 changes: 131 additions & 0 deletions xCAT-test/unit/ipmi_sdr_errors.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env perl

use strict;
use warnings;
## no critic (Modules::RequireFilenameMatchesPackage, TestingAndDebugging::ProhibitNoStrict, TestingAndDebugging::ProhibitNoWarnings)
no warnings qw(once redefine);

use File::Spec;
use FindBin;
use Test::More;

# An IPMI command reads the device ID and then the SDR repository before it can answer.
# A failure in that chain must reach the administrator as an error of the node and must end
# the chain, instead of being dropped or reported under no node.

BEGIN {
for my $module (qw(
xCAT::GlobalDef xCAT_monitoring::monitorctrl xCAT::IPMI
xCAT::BMCUtils xCAT::PasswordUtils xCAT::Utils xCAT::TableUtils
xCAT::IMMUtils xCAT::ServiceNodeUtils xCAT::NetworkUtils xCAT::Usage
xCAT::data::ibmhwtypes xCAT::data::ibmleds
xCAT::data::ipmigenericevents xCAT::data::ipmisensorevents
IBM::EnergyManager
)) {
(my $file = $module) =~ s{::}{/}g;
$INC{"$file.pm"} = __FILE__;
no strict 'refs';
*{"${module}::import"} = sub { };
}

package xCAT::SvrUtils;
our @messages;
sub import { }
sub sendmsg { push @messages, { text => $_[0], node => $_[2] }; }
$INC{'xCAT/SvrUtils.pm'} = __FILE__;

package xCAT::SPD;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::decode_spd"} = sub { return; };
}
$INC{'xCAT/SPD.pm'} = __FILE__;

package File::Path;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::mkpath"} = sub { return; };
}
$INC{'File/Path.pm'} = __FILE__;

package Thread;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::yield"} = sub { return; };
}
$INC{'Thread.pm'} = __FILE__;

package LWP;
our $VERSION = 5.64;
sub import { }
$INC{'LWP.pm'} = __FILE__;

package HTTP::Request::Common;
sub import {
my $caller = caller;
no strict 'refs';
*{"${caller}::GET"} = sub { return; };
*{"${caller}::POST"} = sub { return; };
}
$INC{'HTTP/Request/Common.pm'} = __FILE__;

package main;
*CORE::GLOBAL::chmod = sub (@) { return 1; };
}

package FakeSession;
sub new { return bless { calls => [] }, shift; }
sub subcmd { my ($self, %args) = @_; push @{ $self->{calls} }, \%args; return; }

package main;

my $repo_root = File::Spec->catdir($FindBin::Bin, '..', '..');
$ENV{XCATROOT} = File::Spec->catdir($repo_root, 'xCAT-server');
my $plugin = File::Spec->catfile($repo_root, qw(xCAT-server lib xcat plugins ipmi.pm));
do $plugin or die $@ || "Unable to load $plugin: $!";

# Run one callback of the chain with a reply and return what it reported and requested.
sub run_step {
my ($step, $rsp, %state) = @_;
my $sessdata = { node => 'node01', ipmisession => FakeSession->new(), %state };
local @xCAT::SvrUtils::messages = ();
my $ok = eval { $step->($rsp, $sessdata); 1 };
return {
died => $ok ? '' : ($@ || 'died'),
messages => [@xCAT::SvrUtils::messages],
requests => $sessdata->{ipmisession}->{calls},
};
}

sub assert_node_error {
my ($result, $text, $case) = @_;
is($result->{died}, '', "$case: the callback returns");
is(scalar @{ $result->{messages} }, 1, "$case: one message");
my $message = $result->{messages}->[0] || {};
is($message->{node}, 'node01', "$case: the message names the node");
is_deeply($message->{text}, [ 1, $text ], "$case: the message is an error with the reply text");
is(scalar @{ $result->{requests} }, 0, "$case: the chain stops");
}

my $invalid_command = { code => 0xc1, data => [] };
my $timeout = { error => 'timeout' };

for my $step (
[ 'Get Device ID', \&xCAT_plugin::ipmi::gotdevid ],
[ 'Get SDR Repository Info', \&xCAT_plugin::ipmi::got_sdr_rep_info ],
[ 'Reserve SDR Repository', \&xCAT_plugin::ipmi::reserved_sdr_repo ],
[ 'the first Get SDR', \&xCAT_plugin::ipmi::start_sdr_record ],
[ 'a following Get SDR', \&xCAT_plugin::ipmi::add_sdr_data ],
) {
my ($name, $callback) = @$step;
assert_node_error(run_step($callback, $timeout), 'timeout', "$name times out");
}

my $result = run_step(\&xCAT_plugin::ipmi::reserved_sdr_repo, $invalid_command,
sdr_info => { resv_sdr => 1 });
assert_node_error($result, "Invalid or unsupported command", "a refused SDR reservation");

done_testing();
Loading
Loading