Commit 40de3cfd authored by Mike Hibler's avatar Mike Hibler

Make "power status" work for IPMI and iLO.

This turned out to be more involved than I hoped, but it is done.
Works on "ipmi20" and "ilo3". May need a little work for "drac".
parent c0517087
......@@ -152,7 +152,7 @@ my %all_nodes = ();
foreach my $n (0..$#machines) {
$all_nodes{"\L$machines[$n]"} = 1; # Lowercase it and use as hash key
}
@machines= sort keys %all_nodes;
@machines= sort byname keys %all_nodes;
#
# Dump the args
......@@ -641,6 +641,7 @@ sub dostatus(@) {
# XXX this is not very efficient.
#
my @nwanted = ();
my %pernode = ();
for my $node (@wanted) {
my $ctrl;
......@@ -653,6 +654,13 @@ sub dostatus(@) {
next;
} else {
($ctrl, $outlet) = $result->fetchrow();
# XXX hack for IPMI/iLo nodes
if ($ctrl =~ /^(ipmi15|ipmi20|ilo|ilo2|ilo3|drac)$/) {
push(@{$pernode{$ctrl}}, $node);
next;
}
print "$node is $ctrl outlet $outlet...\n";
}
} else {
......@@ -740,6 +748,30 @@ sub dostatus(@) {
$errors++;
}
}
#
# Now handle all IPMI/iLo nodes
#
foreach my $ctrl (keys %pernode) {
my @cnodes = @{$pernode{$ctrl}};
my %status = ();
$errors += ilostatus($ctrl, \%status, @cnodes);
foreach my $node (@cnodes) {
my $state;
if (!exists($status{$node})) {
$state = "<unknown>";
} elsif ($status{$node} == 1) {
$state = "on";
} elsif ($status{$node} == 0) {
$state = "off";
} else {
$state = "<unknown>";
}
print "$node: $state\n";
}
}
return $errors;
}
......
......@@ -45,7 +45,7 @@ use warnings;
use Exporter;
our @ISA = ("Exporter");
our @EXPORT = qw( iloctrl );
our @EXPORT = qw( iloctrl ilostatus );
use lib "@prefix@/lib";
use libdb;
......@@ -66,16 +66,41 @@ $| = 1;
my %portinfo = ();
sub ilostatus($$@) {
my ($type,$statusp,@nodes) = @_;
return iloaction($type, "status", $statusp, @nodes);
}
#
# usage: iloctrl(type, cmd, nodes)
# type = { "ilo" | "ilo2" | "ilo3" | "drac" | "ipmi15" | "ipmi20" }
# cmd = { "cycle" | "on" | "off" }
# cmd = { "forcecycle" | "cycle" | "on" | "off" | "status" }
# nodes = list of one or more physical node names
#
# Returns 0 on success. Non-zero on failure.
#
sub iloctrl($$@) {
my ($type,$cmd,@nodes) = @_;
# XXX it would be useful to propagate the individual node status here too
my %status = ();
return iloaction($type, $cmd, \%status, @nodes);
}
#
# Internal command to do the work.
#
# usage: iloaction(type, cmd, status, nodes)
# type = { "ilo" | "ilo2" | "ilo3" | "drac" | "ipmi15" | "ipmi20" }
# cmd = { "forcecycle" | "cycle" | "on" | "off" | "status" }
# status = hash ref keyed by node with value of per-node return status
# nodes = list of one or more physical node names
#
# Returns 0 on success. Non-zero on failure.
#
sub iloaction($$$@) {
my ($type,$cmd,$statusp,@nodes) = @_;
my $exitval = 0;
my $force = 0;
......@@ -86,9 +111,12 @@ sub iloctrl($$@) {
if ($cmd eq "forcecycle") {
$force = 1;
$cmd = "cycle";
} elsif ($cmd ne "cycle" && $cmd ne "on" && $cmd ne "off") {
} elsif ($cmd !~ /^(cycle|on|off|status)$/) {
warn "invalid power command '$cmd'; \n" .
" valid commands are 'cycle, 'off', and 'on'.\n";
" valid commands are 'cycle, 'off', 'on', and 'status'.\n";
foreach my $n (@nodes) {
$statusp->{$n} = -1;
}
return scalar(@nodes);
}
......@@ -102,6 +130,7 @@ sub iloctrl($$@) {
" and interface_type='$type'");
if (!defined($res) || !$res || $res->num_rows() == 0) {
warn "No $type interface for $n; cannot find $type IP!\n";
$statusp->{$n} = -1;
++$exitval;
next;
}
......@@ -114,6 +143,7 @@ sub iloctrl($$@) {
" where node_id='$n' and key_type='$type'");
if (!defined($res) || !$res || $res->num_rows() == 0) {
warn "No $type remote auth info for $n!\n";
$statusp->{$n} = -1;
++$exitval;
next;
}
......@@ -188,19 +218,34 @@ sub iloctrl($$@) {
}
#
# Check the exit codes.
# Is this awkward or what?
#
foreach my $result (@results) {
++$exitval
if ($result != 0);
for (my $i = 0; $i < @ilos; $i++) {
my $n = $ilos[$i]->[0];
my $rv = ($results[$i] >> 8);
$statusp->{$n} = $rv;
if ($cmd eq "status") {
$exitval++
if ($rv < 0);
} else {
++$exitval
if ($rv != 0);
}
}
}
else {
for my $key (keys(%ilo_nodeinfo)) {
my ($n,$IP,$krole,$kuid,$kkey) = @{$ilo_nodeinfo{$key}};
my ($n,$IP,$krole,$kuid,$kkey,$kgkey,$kprivlvl) = @{$ilo_nodeinfo{$key}};
if (iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout)) {
++$exitval;
my $rv;
if ($type =~ /^ipmi/) {
$rv = ipmiexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$kgkey,$kprivlvl,$timeout,$force);
} else {
$rv = iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout);
}
$statusp->{$n} = $rv;
++$exitval
if ($rv < 0);
}
}
return $exitval;
......@@ -208,6 +253,8 @@ sub iloctrl($$@) {
#
# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$timeout]
# on/off/cycle returns: 0 for success, < 0 otherwise
# status returns: 0 for off, 1 for on, -1 for error
#
sub iloexec($$$$$$$;$) {
my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$timeout) = @_;
......@@ -241,6 +288,10 @@ sub iloexec($$$$$$$;$) {
$power_cmd = ($type eq "drac" ?
'racadm serveraction powerdown' : 'power off');
}
elsif ($cmd eq 'status') {
$power_cmd = ($type eq "drac" ?
'racadm serveraction powerstatus' : 'power');
}
else {
warn "Bad iLO power command $cmd";
return -11;
......@@ -411,12 +462,27 @@ sub iloexec($$$$$$$;$) {
}
kill('KILL',$pid) if (!$dead);
if ($cmd eq "status") {
foreach my $line (@lines) {
if ($line =~ /server power is currently:\s+(\S+)/) {
return ($1 eq "Off") ? 0 : 1;
}
}
print "iLO unexpected power status:\n";
foreach my $line (@lines) {
print "'$line'\n";
}
return -1;
}
# if we get here, things probably went ok...
return 0;
}
#
# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$kgkey,$privlvl,$timeout]
# on/off/cycle returns: 0 for success, <0 on error
# status returns: 0 for off, 1 for on, <0 for error
#
sub ipmiexec($$$$$$$;$$$$) {
my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$kgkey,$privlvl,$timeout,$force) = @_;
......@@ -433,7 +499,7 @@ sub ipmiexec($$$$$$$;$$$$) {
return -1;
}
if ($cmd =~ /^(cycle|reset|on|off)$/) {
if ($cmd =~ /^(cycle|reset|on|off|status)$/) {
$cmd = $1;
}
else {
......@@ -513,7 +579,16 @@ again:
print $output;
}
return $stat;
if (!$stat && $cmd eq "status") {
if ($output =~ /power is (off|on)/i) {
return ($1 eq "off") ? 0 : 1;
}
print "IPMI unexpected power status:\n";
print $output;
return -1;
}
return ($stat ? -1 : 0);
}
1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment