Skip to content
Snippets Groups Projects
node_admin.in 4.85 KiB
Newer Older
Leigh B. Stoller's avatar
Leigh B. Stoller committed
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
# All rights reserved.
#
# Turn on/off admin mode for nodes and optionally reboot/wait.
    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";
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;

#
# 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;

#
# 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{"n"})) {
    $reboot = 0;
}
if (defined($options{"w"})) {
    $waitmode = 1;
}


if ($onoff ne "on" && $onoff ne "off") {
    usage();
}

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);
    }
    # 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.
    system("$osselect -t $ADMINOSID @nodes") and
	die("*** $0:\n".
	    "    Failed to set temp boot to $ADMINOSID for some nodes!\n");
    system("$osselect -c -t @nodes") and
	die("*** $0:\n".
	    "    Failed to clear temp boot for some nodes!\n");
DBQueryFatal("update nodes set startupcmd='', startstatus='none' ".
	     "where " . join(" or ", map("node_id='$_'", @nodes)));

	#
	# 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")) {
	    "    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");
	}
	if (@failed) {
	    die("*** $0:\n".
		"    Failed to boot MFS: @failed\n");
	}