All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

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