Commit 0756ad57 authored by Mac Newbold's avatar Mac Newbold

RPC Power control support finished.

parent 3a67ca5f
......@@ -2,10 +2,7 @@
#
# Testbed Power Control script
#
# Syntax:
# power on <machine> <machine> ...
# power off <machine> <machine> ...
# power cycle <machine> <machine> ...
# power [on|off|cycle] <node> [<node>] ...
#
############################################################
......@@ -24,6 +21,8 @@ print "VERBOSE ON: Set to level $verbose\n" if $verbose;
#
my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@";
use lib "@prefix@/lib";
use power_rpc27;
# un-taint path since this gets called from setuid scripts.
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:@prefix@/bin';
......@@ -42,9 +41,8 @@ my $exitval = 0;
my $snmpit="$TB/bin/snmpit";
#Must have at least an op and a machine, so at least 2 ARGV
die("Usage:\npower [-v[n]] on <machine> <machine> ...\n",
"power [-v[n]] off <machine> <machine> ...\n",
"power [-v[n]] cycle <machine> <machine> ...\n")
die("Usage:\npower [-v[n]] [on|off|cycle] <node> [<node>] ...\n",
"n = verbosity level (0-3)\n")
if ( @ARGV < 2 );
#Read in ARGV
......@@ -54,10 +52,6 @@ if ($op =~ /^(on|off|cycle)$/) {
} else {
die("Invalid command '$op'\n");
}
if ($op eq "cycle") {
$op = "cyc";
}
$op = '-'.$op;
@machines = @ARGV;
foreach my $n (0..$#ARGV) {
#
......@@ -82,19 +76,24 @@ use Mysql;
my $dbh = Mysql->connect("localhost",$DBNAME,"script","none");
my $sth ="";
print "Looking up node->(powerIP,outlet) mappings...\n" if $verbose;
$sth = $dbh->query("select o.node_id,i.IP,o.outlet from ".
"outlets as o left join interfaces as i ".
"on o.power_id = i.node_id");
print "Looking up node->(power_id,powerIP,outlet,powerType) mappings...\n"
if $verbose;
$sth = $dbh->query("select o.node_id,o.power_id,i.IP,o.outlet, n.type ".
"from outlets as o left join interfaces as i ".
"on o.power_id = i.node_id left join nodes as n ".
"on o.power_id = n.node_id");
while ( @_ = $sth->fetchrow_array()) {
$IPList{$_[0]}= $_[1];
$OutletList{$_[0]}= '-'.$_[2];
$powerID{$_[0]}= $_[1];
$IPList{$_[0]}= $_[2] || 0; # RPC-27's don't have IPs...
$OutletList{$_[0]}= $_[3];
$powerType{$_[0]}= $_[4];
}
if ($verbose > 2) {
print "Displaying node -> (powerIP, outlet) map...\n";
foreach $item (sort keys(%IPList)) {
print "$item\t",$IPList{$item},"\t",$OutletList{$item},"\n";
print "$item\t$powerID{$item}\t$IPList{$item}\t".
"$OutletList{$item}\t$powerType{$item}\n";
}
}
......@@ -212,27 +211,35 @@ foreach $node ( sort @machines) {
print "Power controller for $node not found. Skipping...\n";
$exitval++;
} else {
my $cmd = ( $verbose > 1 ? "-debug $verbose " : "");
$cmd .= join(" ",
('-v','-i',$IPList{$node},$op,$OutletList{$node}));
$cmd = "$snmpit ".$cmd;
print "Calling snmpit: '$cmd'\n" if $verbose > 1;
open(OUT,$cmd." |");
while (<OUT>) {
if ($verbose) { print $_; }
if (/was outlet([OnfRebot]+)/) {
print "$node was $1";
}
if (/to outlet([OnfRebot]+)/) {
print " ... $node now $1";
my $type = $powerType{$node};
if ($type eq "APC") {
my $cmd = ( $verbose > 1 ? ("-debug ".($verbose-1)) : " ");
$cmd .= join(" ",
('-v','-i',$IPList{$node},"-$op -$OutletList{$node}"));
$cmd = "$snmpit ".$cmd;
print "Calling snmpit: '$cmd'\n" if $verbose > 1;
open(OUT,$cmd." |");
while (<OUT>) {
if ($verbose) { print $_; }
if (/was outlet([OnfRebot]+)/) {
print "$node was $1";
}
if (/to outlet([OnfRebot]+)/) {
print " ... $node now $1";
}
}
print "\n";
} elsif ($type eq "RPC27") {
if (rpc27ctrl($op,$powerID{$node},$OutletList{$node})) {
print "$node now ",($op eq "cycle" ? "reboot" : $op),"\n";
} else { print "Control of $node failed.\n"; $exitval++; }
} else {
print "power: Unknown power type '$type'\n";
$exitval++;
}
print "\n";
}
}
}
#
# Return 0 on success. Return non-zero number of nodes that failed.
#
exit $exitval;
#!/usr/bin/perl -wT
#use English;
#use strict;
use Socket;
use IO::Handle;
use lib "@prefix@/lib";
use libdb;
package power_rpc27;
use Exporter;
@ISA = ("Exporter");
@EXPORT = qw( rpc27ctrl );
use Socket;
use IO::Handle;
use lib "@prefix@/lib";
use libdb;
# A little perl module to power cycle something attached to an RPC27.
# Thats a serially controlled, power controller.
......@@ -19,15 +17,18 @@ use Exporter;
# XXX The little secretkey handshake is coded in here. If this changes
# in capture, you have to change it here too. Look for the "pack"
# statement below.
#
# XXX Note that if someone has already tipped to the power controller
# in question, this won't work at all.
# Turn off line buffering on output
$| = 1;
# Set for more output.
my $debug = 1;
my $debug = 0;
# RPC27 Prompt string
my $RPC27_PROMPT = "RPC27>";
my $RPC27_PROMPT = "RPC-27>";
my %RPC27_CMD =
("cycle"=>"reboot",
"on" =>"on",
......@@ -39,49 +40,51 @@ my %RPC27_CMD =
# controller = <node_id>
# outlet = int, 1 <= outlet <= 20
sub rpc27ctrl {
my($cmd, $controller, $outlet) = @_;
my($TIP, $i);
# Form the connection to the controller via a "tip" line to the
# capture process. Once we have that, we can just talk to the
# controller directly.
if (! ($TIP = tipconnect($controller))) {
print STDERR "*** Could not form TIP connection to $controller\n";
return 1;
}
if ( $outlet < 1 || $outlet > 20 ) {
print STDERR "*** Invalid outlet '$outlet': Must be 1-20\n";
return 1;
}
# Send a couple of newlines to get the command prompt, and then wait
# for it to print out the command prompt. This loop is set for a small
# number since if it cannot get the prompt quickly, then something has
# gone wrong/
print $TIP "\n";
for ($i = 0; $i < 5; $i++) {
my $line = <$TIP>;
if ($line =~ /^$RPC27_PROMPT/) {
last;
my($cmd, $controller, $outlet) = @_;
my($TIP, $i);
# Form the connection to the controller via a "tip" line to the
# capture process. Once we have that, we can just talk to the
# controller directly.
if (! ($TIP = tipconnect($controller))) {
print STDERR "*** Could not form TIP connection to $controller\n";
return 1;
}
if ( $outlet < 1 || $outlet > 20 ) {
print STDERR "*** Invalid outlet '$outlet': Must be 1-20\n";
return 1;
}
# Send a couple of newlines to get the command prompt, and then wait
# for it to print out the command prompt. This loop is set for a small
# number since if it cannot get the prompt quickly, then something has
# gone wrong/
print $TIP "\r\n";
for ($i = 0; $i < 5; $i++) {
my $line = <$TIP>;
if ($debug) { print "Read: $line"; }
if ($line =~ /^$RPC27_PROMPT/) {
if ($debug) { print "Matched prompt '$RPC27_PROMPT'!\n"; }
last;
}
print $TIP "\r\n";
}
print $TIP "\n";
}
# Okay, got a prompt. Send it the string:
print $TIP "$RPC27_CMD{$cmd} $outlet\n";
# Okay, got a prompt. Send it the string:
print $TIP "$RPC27_CMD{$cmd} $outlet\r\n";
if ($debug) {
print "rpc27ctrl: Sent $cmd command to outlet $outlet on $controller.\n";
}
if ($debug) {
print "Sending '$RPC27_CMD{$cmd} $outlet'...\n";
print "rpc27ctrl: Sent $cmd command to outlet $outlet on $controller.\n";
}
close($TIP);
close($TIP);
}
# Connect up to the capture process. This should probably be in a library
# someplace.
sub tipconnect($)
{
sub tipconnect($) {
my($controller) = $_[0];
my($server, $portnum, $keylen, $keydata);
my($inetaddr, $paddr, $proto);
......@@ -89,7 +92,7 @@ sub tipconnect($)
local *TIP;
my $query_result =
DBQueryWarn("select * from tiplines where node_id='$controller'");
DBQueryWarn("select * from tiplines where node_id='$controller'");
if ($query_result->numrows < 1) {
print STDERR "*** No such tipline: $controller\n";
......@@ -116,25 +119,25 @@ sub tipconnect($)
$paddr = sockaddr_in($portnum, $inetaddr);
$proto = getprotobyname('tcp');
if (! socket(TIP, 'PF_INET', 'SOCK_STREAM', $proto)) {
if (! socket(TIP, PF_INET, SOCK_STREAM, $proto)) {
print STDERR "*** Cannot create socket.\n";
return 0;
}
if (! connect(TIP, $paddr)) {
print STDERR
"*** Cannot connect to $controller on $server($portnum)\n";
"*** Cannot connect to $controller on $server($portnum)\n";
return 0;
}
TIP->autoflush(1);
# Okay, we got a connection. We have to send over the key. This is a
# little hokey, since we have to make it look like the C struct.
my $secretkey = pack("iZ256", $keylen, $keydata);
if (! syswrite(TIP, $secretkey)) {
print STDERR
"*** Cannot write key to $controller on $server($portnum)\n";
"*** Cannot write key to $controller on $server($portnum)\n";
return 0;
}
......
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