vnode_setup.in 4.95 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2 3 4

#
# EMULAB-COPYRIGHT
5
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
6 7 8
# All rights reserved.
#

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
use English;
use Getopt::Std;

#
# Set up the vnode state on a virtual (multiplexed) node.
#
# XXX - This script should only be run from os_setup!
#
# The output is all jumbled together since the updates are issued in parallel.
# Might be a pain when debugging. 
# 
sub usage()
{
    print STDOUT "Usage: vnode_setup [-f] [-k] <pid> <eid>\n";
    exit(-1);
}
my  $optlist = "fdk";
  
#
# Configure variables
#
my $TB		= "@prefix@";
my $TESTMODE    = @TESTMODE@;
my $TBOPS       = "@TBOPSEMAIL@";
my $TBLOGS      = "@TBLOGSEMAIL@";
34
my $CLIENT_BIN  = "@CLIENT_BINDIR@";
35 36 37 38 39 40 41 42

my $ssh		= "$TB/bin/sshtb -n";
my $debug       = 0;
my $force       = 0;
my $failed      = 0;
my $killmode    = 0;
my $mode        = "setup";
my $dbuid;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
43
my $exptstate;
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 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

#
# Load the Testbed support stuff. 
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;

# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

# Turn off line buffering on output
$| = 1; 

#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (@ARGV != 2) {
    usage();
}
if (defined($options{"f"})) {
    $force = 1;
}
if (defined($options{"d"})) {
    $debug = 1;
}
if (defined($options{"k"})) {
    $killmode = 1;
    $mode = "teardown";
}
my $pid   = $ARGV[0];
my $eid   = $ARGV[1];

#
# Untaint the arguments.
#
if ($pid =~ /^([-\@\w]+)$/) {
    $pid = $1;
}
else {
    die("*** Bad data in pid: $pid\n");
}	
if ($eid =~ /^([-\@\w]+)$/) {
    $eid = $1;
}
else {
    die("*** Bad data in eid: $eid\n");
}	

#
# We don't want to run this script unless its the real version.
# That is, it must be setuid root. 
#
if ($EUID != 0) {
    die("*** $0:\n".
	"    Must be root! Maybe its a development version?\n");
}

#
# Verify actual user and get his DB uid.
#
if (! UNIX2DBUID($UID, \$dbuid)) {
    die("*** $0:\n".
	"    You do not exist in the Emulab Database.\n");
}

#
# Verify permission to muck with this experiment.
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
119 120 121 122
if (!TBAdmin($UID) &&
    !TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_DESTROY)) {
    die("*** $0:\n".
	"    You do not have permission to mess with $pid/$eid!\n");
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
}

#
# Get the list of nodes.
# 
my @nodes = ExpNodes($pid, $eid);
if (! @nodes) {
    warn("*** $0:\n".
	 "    No allocated nodes in experiment $pid/$eid!\n");
    exit(0);
}

# Just the vnodes mam.
foreach my $node (@nodes) {
    my $pnode;
138
    my $jailed;
139
    
140
    if (! TBIsNodeVirtual($node, \$jailed)) {
141 142
	next;
    }
143 144 145 146
    if (! TBPhysNodeID($node, \$pnode)) {
	die("*** $0:\n".
	    "    No physical node for $node!\n");
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
147 148 149 150 151 152 153
    if (!TBIsNodeRemote($node) && !$force) {
	#
	# A local vnode. If the experiment is activating, then the
	# underlying physnode will setup the vnode as it boots, so
	# no need to do anything. Ditto for swapping out; the vnode
	# will get torn down when the node goes down, obviously. 
	#
154 155 156 157
	my $exptstate = ExpState($pid, $eid);

	if ($exptstate eq EXPTSTATE_SWAPPING ||
	    $exptstate eq EXPTSTATE_ACTIVATING) {
158
	    print "$node will automatically $mode with local node $pnode\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
159 160 161 162 163 164 165 166 167 168 169
	    next;
	}
    }

    #
    # When setting up a vnode, force its event state into SHUTDOWN since
    # no telling what its initial state is. 
    # 
    if (!$killmode) {
	TBSetNodeEventState($node, TBDB_NODESTATE_SHUTDOWN);
    }
170 171 172 173 174 175 176 177 178 179 180 181
    
    print STDOUT "Doing $mode of vnode $node on $pnode ...\n";

    #
    # Run an ssh command in a child process, protected by an alarm to
    # ensure that the ssh is not hung up forever if the machine is in
    # some funky state.
    # 
    my $syspid = fork();

    if ($syspid) {
	local $SIG{ALRM} = sub { kill("TERM", $syspid); };
182
	alarm 60;
183 184 185 186 187 188
	waitpid($syspid, 0);
	alarm 0;

	print STDERR "vnode $mode on $pnode returned $?.\n" if $debug;
    
	#
189
	# Look for setup failure, reported back through ssh.
190
	# 
191 192 193 194
	if ($?) {
	    my $exitstatus = $?;

	    if ($exitstatus == 256) {
195
		print STDERR "$node is not running sshd.\n" if $debug;
196 197
	    }
	    elsif ($exitstatus == 15) {
198 199 200 201 202 203
		print STDERR "$node is wedged.\n" if $debug;
	    }
	    
	    # Send mail to testbed-ops about it
	    SENDMAIL($TBOPS, "Virtual Node $node $mode failure",
	     "Virtual node $node $mode (on physical node $pnode) in pid/eid\n".
204
	     "$pid/$eid has failed! Exit status was $exitstatus.\n");
205 206 207 208 209 210 211 212 213 214 215 216

	    if (!$killmode) {
		die("*** $0:\n".
		    "    Virtual node $node setup failure!\n");
	    }
	    else {
		warn("*** $0:\n".
		    "    Virtual node $node teardown failure!\n");
	    }
	}
    }
    else {
217 218 219
	my $args = ($killmode ? "-k " : " ");
	$args   .= ($jailed   ? "-j " : " ");
	$args   .= "$node ";
220 221 222 223
	
	# Must change our real UID to root so that ssh will work.
	$UID = 0;
    
224
	exec("$ssh -host $pnode $CLIENT_BIN/vnodesetup $args");
225 226 227 228 229 230 231 232 233 234
	die("*** $0:\n".
	    "    exec failed!\n");
    }
}

#
# Only if all nodes setup okay.
# 
print STDOUT "Vnode Setup Done!\n";
exit 0;