Newer
Older
#!/usr/bin/perl -wT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
use English;
use Getopt::Std;
#
# Turn on/off admin mode for nodes and optionally reboot/wait.
#
sub usage()
{
print STDOUT "Usage: node_admin [-h] [-n | -w] <on | off> [node ....]\n";
print STDOUT " node_admin [-h] [-n | -w] -e pid,eid <on | off>\n";
print STDOUT "-h This message\n";
print STDOUT "-n Do not reboot node\n";
print STDOUT "-w Wait for node to come back up if rebooted\n";
print STDOUT "-e Operate on all nodes in an experiment\n";
exit(-1);
}
my $optlist = "hnwe:";
my $waitmode = 0;
my $reboot = 1;
#
# Configure variables
#
my $TB = "@prefix@";
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use StateWait;
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
#
#
my $nodereboot = "$TB/bin/node_reboot";
my $osselect = "$TB/bin/os_select";
my $ADMINOSID = TB_OSID_FREEBSD_MFS;
my @nodes = ();
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{h})) {
usage();
}
if (defined($options{"n"})) {
$reboot = 0;
}
if (defined($options{"w"})) {
$waitmode = 1;
}
if (!@ARGV) {
usage();
}
my $onoff = shift(@ARGV);
if ($onoff ne "on" && $onoff ne "off") {
usage();
}
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
if (defined($options{"e"})) {
#
# Reboot all nodes in an experiment
#
if (@ARGV) {
usage();
}
my $eidmode = $options{"e"};
my $pid;
my $eid;
if ($eidmode =~ /([-\w]*),([-\w]*)/) {
$pid = $1;
$eid = $2;
}
else {
die("*** $0:\n".
" Invalid argument to -e option: $eidmode\n");
}
#
# Verify permission to muck with this experiment. This is to head off
# permission problems early; the nodes are indvidually checked later
# in the library.
#
if ($UID && !TBAdmin($UID) &&
! TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_MODIFY)) {
die("*** $0:\n".
" You not have permission to reboot nodes in $pid/$eid!\n");
}
my $query_result =
DBQueryFatal("select node_id from reserved where ".
"pid='$pid' and eid='$eid'");
if ($query_result->numrows == 0) {
die("*** $0:\n".
" There are no nodes reserved in pid/eid $pid/$eid\n");
}
while (my ($nodeid) = $query_result->fetchrow_array()) {
push(@nodes, $nodeid);
}
}
else {
if (! @ARGV) {
usage();
}
# Untaint the nodes.
foreach my $node ( @ARGV ) {
if ($node =~ /^([-\w]+)$/) {
$node = $1;
}
else {
die("*** Tainted node name: $node\n");
}
if (!TBValidNodeName($node)) {
die("*** $0:\n".
" Node does not exist: $node\n");
}
push(@nodes, $node);
}
#
# Root and admin types can do whatever they want. Normal users
# can only run this on nodes in their own experiments.
#
if ($UID && !TBAdmin($UID)) {
if (! TBNodeAccessCheck($UID, TB_NODEACCESS_LOADIMAGE, @nodes)) {
die("*** $0:\n".
" You are not allowed to put some nodes into admin mode\n");
}
}
}
# Switcheroo the osids on the nodes.
if ($onoff eq "on") {
system("$osselect -t $ADMINOSID @nodes") and
die("*** $0:\n".
" Failed to set temp boot to $ADMINOSID for some nodes!\n");
}
else {
system("$osselect -c -t @nodes") and
die("*** $0:\n".
" Failed to clear temp boot for some nodes!\n");
}
# Is this needed anymore?
DBQueryFatal("update nodes set startupcmd='', startstatus='none' ".
"where " . join(" or ", map("node_id='$_'", @nodes)));
#
# Reboot nodes
#
if ($reboot) {
if ($waitmode) {
Leigh B. Stoller
committed
$StateWait::debug = 0;
#
# Initialize the statewait library.
#
Leigh B. Stoller
committed
my @states = ();
my @finished = ();
my @failed = ();
Leigh B. Stoller
committed
#
# Only wait for MFSSETUP when going into the MFS. When coming out
# of MFS, just wait for generic ISUP.
#
push(@states, TBDB_NODESTATE_MFSSETUP())
if ($onoff eq "on");
push(@states, TBDB_NODESTATE_ISUP());
if (initStateWait(\@states, @nodes)) {
die("*** $0:\n".
" Failed to initialize the statewait library!\n");
}
}
# Reboot nodes *after* setting up statewait above.
if (system("$nodereboot @nodes")) {
die("*** $0:\n".
" WARNING: Could not reboot some nodes!\n");
if ($waitmode) {
#
# Initialize the statewait library.
#
my @finished = ();
my @failed = ();
my $timeout = 6 * 60;
print STDOUT "node_admin: Waiting for nodes to come up.\n";
# Now we can statewait.
if (waitForState(\@finished, \@failed, $timeout)) {
die("*** $0:\n".
" Failed in waitForState!\n");
}
endStateWait();
if (@failed) {
die("*** $0:\n".
" Failed to boot MFS: @failed\n");
}
}
exit(0);