From be4eb7bb62dd74c7ea4ad4450bbe976eeaadd613 Mon Sep 17 00:00:00 2001 From: "Leigh B. Stoller" Date: Wed, 8 May 2002 17:41:10 +0000 Subject: [PATCH] Add vnode_setup script to setup/teardown the vnode configuration on a remote node. Called out of os_setup and tbswapout (-k option to tear down the vnodes). Invokes the proper script on the remote node, with the vnodeid (vronXXX) as the key (which is passed along in tmcc to distinguish vnodes from each other). --- configure | 2 +- configure.in | 2 +- tbsetup/GNUmakefile.in | 4 +- tbsetup/vnode_setup.in | 237 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 tbsetup/vnode_setup.in diff --git a/configure b/configure index 04c49ef65..4a5b19af3 100755 --- a/configure +++ b/configure @@ -1221,7 +1221,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ tbsetup/webmkgroup tbsetup/mkgroup \ tbsetup/webmkacct tbsetup/mkacct tbsetup/eventsys_control \ tbsetup/webmkproj tbsetup/mkproj tbsetup/libtestbed.pm \ - tbsetup/portstats \ + tbsetup/portstats tbsetup/vnode_setup \ tbsetup/console_setup.proxy tbsetup/exports_setup.proxy \ tip/GNUmakefile \ tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \ diff --git a/configure.in b/configure.in index 2259d4786..e70a2dde6 100755 --- a/configure.in +++ b/configure.in @@ -293,7 +293,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ tbsetup/webmkgroup tbsetup/mkgroup \ tbsetup/webmkacct tbsetup/mkacct tbsetup/eventsys_control \ tbsetup/webmkproj tbsetup/mkproj tbsetup/libtestbed.pm \ - tbsetup/portstats \ + tbsetup/portstats tbsetup/vnode_setup \ tbsetup/console_setup.proxy tbsetup/exports_setup.proxy \ tip/GNUmakefile \ tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \ diff --git a/tbsetup/GNUmakefile.in b/tbsetup/GNUmakefile.in index f8f75341d..0cf052a10 100644 --- a/tbsetup/GNUmakefile.in +++ b/tbsetup/GNUmakefile.in @@ -23,7 +23,7 @@ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \ batch_daemon exports_setup reload_daemon sched_reserve \ console_reset db2ns bwconfig frisbeelauncher \ rmgroup mkgroup mkacct setgroups mkproj eventsys_control \ - exports_setup.proxy + exports_setup.proxy vnode_setup LIBEXEC_STUFF = rmproj rmacct-ctrl wanlinksolve wanlinkinfo \ os_setup mkexpdir console_setup webnscheck webreport \ @@ -103,6 +103,8 @@ post-install: chmod u+s $(INSTALL_BINDIR)/node_reboot chown root $(INSTALL_BINDIR)/node_update chmod u+s $(INSTALL_BINDIR)/node_update + chown root $(INSTALL_SBINDIR)/vnode_setup + chmod u+s $(INSTALL_SBINDIR)/vnode_setup chown root $(INSTALL_SBINDIR)/eventsys_control chmod u+s $(INSTALL_SBINDIR)/eventsys_control diff --git a/tbsetup/vnode_setup.in b/tbsetup/vnode_setup.in new file mode 100644 index 000000000..dbdbab911 --- /dev/null +++ b/tbsetup/vnode_setup.in @@ -0,0 +1,237 @@ +#!/usr/bin/perl -wT +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] \n"; + exit(-1); +} +my $optlist = "fdk"; + +# +# Configure variables +# +my $TB = "@prefix@"; +my $TESTMODE = @TESTMODE@; +my $TBOPS = "@TBOPSEMAIL@"; +my $TBLOGS = "@TBLOGSEMAIL@"; + +my $ssh = "$TB/bin/sshtb -n"; +my $sshremote = "$TB/bin/sshremote -n"; +my $debug = 0; +my $force = 0; +my $failed = 0; +my $killmode = 0; +my $mode = "setup"; +my $dbuid; + +# +# 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. +# +if ($UID && !TBAdmin($UID)) { + if (!$killmode) { + # + # Only leader can setup experiments. + # + my $leader = ExpLeader($pid, $eid); + + if ($dbuid ne $leader) { + die("*** $0:\n". + " You do not have permission for $pid/$eid!\n"); + } + } + else { + if (! TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_DESTROY)) { + die("*** $0:\n". + " You do not have permission to destroy $pid/$eid!\n"); + } + } +} + +# +# A sanity check. Lets make sure the experiment is in the proper state. +# +if (!$force) { + if (($killmode && ExpState($pid, $eid) ne EXPTSTATE_SWAPPING) || + (!$killmode && ExpState($pid, $eid) ne EXPTSTATE_ACTIVATING)) { + die("*** $0:\n". + " The experiment $pid/$eid is not in the proper state!\n"); + } +} + +# +# 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; + + if (! TBIsNodeVirtual($node)) { + next; + } + + if (! TBPhysNodeID($node, \$pnode)) { + die("*** $0:\n". + " No physical node for $node!\n"); + } + TBSetNodeEventState($node, TBDB_NODESTATE_REBOOTING); + + print STDOUT "Doing $mode of vnode $node on $pnode ...\n"; + + # + # We need to know if its a remote or local node, so we know how + # to update it. This info needs to be in the DB at some point. + # + my $isremote = TBIsNodeRemote($pnode); + + # + # 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); }; + alarm 10; + waitpid($syspid, 0); + alarm 0; + + print STDERR "vnode $mode on $pnode returned $?.\n" if $debug; + + # + # If either ssh is not running or it timed out, + # send it a ping of death. + # + if ($? == 256 || $? == 15) { + if ($? == 256) { + print STDERR "$node is not running sshd.\n" if $debug; + } else { + 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". + "$pid/$eid has failed!\n"); + + if (!$killmode) { + die("*** $0:\n". + " Virtual node $node setup failure!\n"); + } + else { + warn("*** $0:\n". + " Virtual node $node teardown failure!\n"); + } + } + } + else { + my $args = ($killmode ? "-k" : ""); + $args = "$args $node"; + + # Must change our real UID to root so that ssh will work. + $UID = 0; + + if ($isremote) { + exec("$sshremote $pnode /usr/local/etc/testbed/vnodesetup $args"); + } + else { + exec("$ssh $pnode /etc/testbed/vnodesetup $args"); + } + die("*** $0:\n". + " exec failed!\n"); + } +} + +# +# Only if all nodes setup okay. +# +print STDOUT "Vnode Setup Done!\n"; +exit 0; -- GitLab