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 = (); ...@@ -152,7 +152,7 @@ my %all_nodes = ();
foreach my $n (0..$#machines) { foreach my $n (0..$#machines) {
$all_nodes{"\L$machines[$n]"} = 1; # Lowercase it and use as hash key $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 # Dump the args
...@@ -641,6 +641,7 @@ sub dostatus(@) { ...@@ -641,6 +641,7 @@ sub dostatus(@) {
# XXX this is not very efficient. # XXX this is not very efficient.
# #
my @nwanted = (); my @nwanted = ();
my %pernode = ();
for my $node (@wanted) { for my $node (@wanted) {
my $ctrl; my $ctrl;
...@@ -653,6 +654,13 @@ sub dostatus(@) { ...@@ -653,6 +654,13 @@ sub dostatus(@) {
next; next;
} else { } else {
($ctrl, $outlet) = $result->fetchrow(); ($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"; print "$node is $ctrl outlet $outlet...\n";
} }
} else { } else {
...@@ -740,6 +748,30 @@ sub dostatus(@) { ...@@ -740,6 +748,30 @@ sub dostatus(@) {
$errors++; $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; return $errors;
} }
......
...@@ -45,7 +45,7 @@ use warnings; ...@@ -45,7 +45,7 @@ use warnings;
use Exporter; use Exporter;
our @ISA = ("Exporter"); our @ISA = ("Exporter");
our @EXPORT = qw( iloctrl ); our @EXPORT = qw( iloctrl ilostatus );
use lib "@prefix@/lib"; use lib "@prefix@/lib";
use libdb; use libdb;
...@@ -66,16 +66,41 @@ $| = 1; ...@@ -66,16 +66,41 @@ $| = 1;
my %portinfo = (); my %portinfo = ();
sub ilostatus($$@) {
my ($type,$statusp,@nodes) = @_;
return iloaction($type, "status", $statusp, @nodes);
}
# #
# usage: iloctrl(type, cmd, nodes) # usage: iloctrl(type, cmd, nodes)
# type = { "ilo" | "ilo2" | "ilo3" | "drac" | "ipmi15" | "ipmi20" } # 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 # nodes = list of one or more physical node names
# #
# Returns 0 on success. Non-zero on failure. # Returns 0 on success. Non-zero on failure.
# #
sub iloctrl($$@) { sub iloctrl($$@) {
my ($type,$cmd,@nodes) = @_; 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 $exitval = 0;
my $force = 0; my $force = 0;
...@@ -86,9 +111,12 @@ sub iloctrl($$@) { ...@@ -86,9 +111,12 @@ sub iloctrl($$@) {
if ($cmd eq "forcecycle") { if ($cmd eq "forcecycle") {
$force = 1; $force = 1;
$cmd = "cycle"; $cmd = "cycle";
} elsif ($cmd ne "cycle" && $cmd ne "on" && $cmd ne "off") { } elsif ($cmd !~ /^(cycle|on|off|status)$/) {
warn "invalid power command '$cmd'; \n" . 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); return scalar(@nodes);
} }
...@@ -102,6 +130,7 @@ sub iloctrl($$@) { ...@@ -102,6 +130,7 @@ sub iloctrl($$@) {
" and interface_type='$type'"); " and interface_type='$type'");
if (!defined($res) || !$res || $res->num_rows() == 0) { if (!defined($res) || !$res || $res->num_rows() == 0) {
warn "No $type interface for $n; cannot find $type IP!\n"; warn "No $type interface for $n; cannot find $type IP!\n";
$statusp->{$n} = -1;
++$exitval; ++$exitval;
next; next;
} }
...@@ -114,6 +143,7 @@ sub iloctrl($$@) { ...@@ -114,6 +143,7 @@ sub iloctrl($$@) {
" where node_id='$n' and key_type='$type'"); " where node_id='$n' and key_type='$type'");
if (!defined($res) || !$res || $res->num_rows() == 0) { if (!defined($res) || !$res || $res->num_rows() == 0) {
warn "No $type remote auth info for $n!\n"; warn "No $type remote auth info for $n!\n";
$statusp->{$n} = -1;
++$exitval; ++$exitval;
next; next;
} }
...@@ -188,19 +218,34 @@ sub iloctrl($$@) { ...@@ -188,19 +218,34 @@ sub iloctrl($$@) {
} }
# #
# Check the exit codes. # Check the exit codes.
# Is this awkward or what?
# #
foreach my $result (@results) { for (my $i = 0; $i < @ilos; $i++) {
++$exitval my $n = $ilos[$i]->[0];
if ($result != 0); my $rv = ($results[$i] >> 8);
$statusp->{$n} = $rv;
if ($cmd eq "status") {
$exitval++
if ($rv < 0);
} else {
++$exitval
if ($rv != 0);
}
} }
} }
else { else {
for my $key (keys(%ilo_nodeinfo)) { 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)) { my $rv;
++$exitval; 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; return $exitval;
...@@ -208,6 +253,8 @@ sub iloctrl($$@) { ...@@ -208,6 +253,8 @@ sub iloctrl($$@) {
# #
# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$timeout] # 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($$$$$$$;$) { sub iloexec($$$$$$$;$) {
my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$timeout) = @_; my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$timeout) = @_;
...@@ -241,6 +288,10 @@ sub iloexec($$$$$$$;$) { ...@@ -241,6 +288,10 @@ sub iloexec($$$$$$$;$) {
$power_cmd = ($type eq "drac" ? $power_cmd = ($type eq "drac" ?
'racadm serveraction powerdown' : 'power off'); 'racadm serveraction powerdown' : 'power off');
} }
elsif ($cmd eq 'status') {
$power_cmd = ($type eq "drac" ?
'racadm serveraction powerstatus' : 'power');
}
else { else {
warn "Bad iLO power command $cmd"; warn "Bad iLO power command $cmd";
return -11; return -11;
...@@ -411,12 +462,27 @@ sub iloexec($$$$$$$;$) { ...@@ -411,12 +462,27 @@ sub iloexec($$$$$$$;$) {
} }
kill('KILL',$pid) if (!$dead); 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... # if we get here, things probably went ok...
return 0; return 0;
} }
# #
# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$kgkey,$privlvl,$timeout] # 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($$$$$$$;$$$$) { sub ipmiexec($$$$$$$;$$$$) {
my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$kgkey,$privlvl,$timeout,$force) = @_; my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$kgkey,$privlvl,$timeout,$force) = @_;
...@@ -433,7 +499,7 @@ sub ipmiexec($$$$$$$;$$$$) { ...@@ -433,7 +499,7 @@ sub ipmiexec($$$$$$$;$$$$) {
return -1; return -1;
} }
if ($cmd =~ /^(cycle|reset|on|off)$/) { if ($cmd =~ /^(cycle|reset|on|off|status)$/) {
$cmd = $1; $cmd = $1;
} }
else { else {
...@@ -513,7 +579,16 @@ again: ...@@ -513,7 +579,16 @@ again:
print $output; 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; 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