Commit 6777d279 authored by Leigh Stoller's avatar Leigh Stoller

ElabInElab Addition: New script that uses the frisbee client to

download images from the outer emulab. This script is invoked from
frisbeelauncher when ELABINELAB=1 and the filename does not exist
(thus attempting to get the image file before bailing). The
frisbeeimage script uses a new method in the RPC server to fire up a
frisbeed (using frisbeelauncher on the outer Emulab), subject to the
usual permission checks against creator of the elabinelab experiment
(I assume that the creator will have access to any outer images that
are used inside the inner emulab). If outer frisbeelauncher succeeds,
its return value is the load_address (IP:port), which is used to fire
up a frisbee client to get the image file and write it out (using
Mike's new -N option that just dumps the raw data to file). Once the
image is downloaded, control returns to inner frisbeelauncher and
proceeds as normal.

I whacked this together pretty quickly. Under heavy usage it might hit
a race condition or two, but I do not expect that to happen in an
inner elab for a while.
parent cc47ed1f
......@@ -1502,7 +1502,8 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/webdelay_config tbsetup/webbatchexp tbsetup/webreport \
tbsetup/wanlinkinfo tbsetup/wanassign \
tbsetup/webswapexp tbsetup/swapexp \
tbsetup/endexp tbsetup/webendexp \
tbsetup/endexp tbsetup/webendexp tbsetup/elabinelab \
tbsetup/frisbeelauncher tbsetup/eventsys.proxy tbsetup/frisbeeimage \
tbsetup/snmpit.proxy tbsetup/snmpit_remote.pm \
tbsetup/snmpit tbsetup/ns2ir/GNUmakefile \
tbsetup/ns2ir/parse.tcl tbsetup/ns2ir/tb_compat.tcl \
......
......@@ -532,7 +532,8 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/webdelay_config tbsetup/webbatchexp tbsetup/webreport \
tbsetup/wanlinkinfo tbsetup/wanassign \
tbsetup/webswapexp tbsetup/swapexp \
tbsetup/endexp tbsetup/webendexp \
tbsetup/endexp tbsetup/webendexp tbsetup/elabinelab \
tbsetup/frisbeelauncher tbsetup/eventsys.proxy tbsetup/frisbeeimage \
tbsetup/snmpit.proxy tbsetup/snmpit_remote.pm \
tbsetup/snmpit tbsetup/ns2ir/GNUmakefile \
tbsetup/ns2ir/parse.tcl tbsetup/ns2ir/tb_compat.tcl \
......
......@@ -24,7 +24,7 @@ BIN_STUFF = power snmpit tbend tbprerun tbreport \
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 setgroups mkproj \
frisbeeimage rmgroup mkgroup setgroups mkproj \
exports_setup.proxy vnode_setup eventsys_start \
sfskey_update sfskey_update.proxy rmuser idleswap \
newnode_reboot savelogs.proxy eventsys.proxy \
......@@ -132,6 +132,8 @@ post-install:
chmod u+s $(INSTALL_SBINDIR)/mkgroup
chown root $(INSTALL_SBINDIR)/frisbeelauncher
chmod u+s $(INSTALL_SBINDIR)/frisbeelauncher
chown root $(INSTALL_SBINDIR)/frisbeeimage
chmod u+s $(INSTALL_SBINDIR)/frisbeeimage
chown root $(INSTALL_SBINDIR)/rmuser
chmod u+s $(INSTALL_SBINDIR)/rmuser
chown root $(INSTALL_SBINDIR)/idleswap
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002, 2004 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
#
# Ask outer emulab for an image we do not happen to have locally.
#
sub usage()
{
print STDOUT "Usage: frisbeeimage [-d] imageid\n";
exit(-1);
}
my $optlist = "d";
my $debug = 1;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $ELABINELAB = @ELABINELAB@;
my $RPCSERVER = "@OUTERBOSS_NODENAME@";
my $RPCPORT = "@OUTERBOSS_XMLRPCPORT@";
my $RPCCERT = "@OUTERBOSS_SSLCERTNAME@";
$RPCPORT = 7778;
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/usr/site/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("*** $0:\n".
" Must be root! Maybe its a development version?\n");
}
if (!$ELABINELAB) {
die("*** $0:\n".
" This script is for elabinelab systems only!\n");
}
# Load the Testbed support stuff.
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use libxmlrpc;
# Locals
my $FRISBEE = "$TB/sbin/frisbee";
my $SAVEUID = $UID;
my $loadaddr;
my $loadport;
my $mcastif;
#
# Parse command arguments. Once we return from getopts, all that should
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (! @ARGV) {
usage();
}
my ($imageid) = @ARGV;
#
# Untaint the arguments.
#
if ($imageid =~ /^([-\@\w\+\.]+)$/) {
$imageid = $1;
}
else {
die("Tainted argument $imageid!\n");
}
#
# Grab mcastif. This is has been set up for us, and its a serious kludge.
#
if (! -e "/etc/emulab/outer_ipaddr") {
die("*** $0:\n".
" /etc/emulab/outer_ipaddr does not exist!\n");
}
$mcastif = `cat /etc/emulab/outer_ipaddr`;
chomp($mcastif);
if ($mcastif =~ /^([\d\.]+)$/) {
$mcastif = $1;
}
else {
die("*** $0:\n".
" Could not parse outer IP: $mcastif\n!");
}
#
# Grab image info.
#
my $query_result =
DBQueryFatal("select path,creator,gid from images where imageid='$imageid'");
my ($filename,$creator,$gid) = $query_result->fetchrow();
#
# Ask the outer Emulab to lauch a frisbee and return the loadinfo to us.
#
libxmlrpc::Config({"server" => $RPCSERVER,
"verbose" => 1,
"cert" => $RPCCERT,
"portnum" => $RPCPORT});
my $rval = libxmlrpc::CallMethod("elabinelab", "frisbeelauncher",
{"imageid" => "$imageid"});
if (!defined($rval)) {
die("*** $0:\n".
" Could not fire up frisbee on outer Emulab!\n");
}
#
# The return value is the loadaddr. Parse that into something we
# can pass to the frisbee client.
#
if ($rval =~ /^(.*):(\d*)$/) {
$loadaddr = $1;
$loadport = $2;
}
else {
die("*** $0:\n".
" Could not parse loadinfo from server: $rval\n!");
}
if ($debug) {
print "$FRISBEE -N -i $mcastif -m $loadaddr -p $loadport $filename\n";
}
system("$FRISBEE -N -i $mcastif -m $loadaddr -p $loadport $filename");
if ($?) {
die("*** $0:\n".
" Error downloading image data from outer Emulab!\n");
}
exit(0);
......@@ -29,6 +29,7 @@ my $TBOPS = "@TBOPSEMAIL@";
my $BOSSNODE_IP = "@BOSSNODE_IP@";
my $BASEADDR = "@FRISEBEEMCASTADDR@";
my $BASEPORT = "@FRISEBEEMCASTPORT@";
my $ELABINELAB = @ELABINELAB@;
#
# Untaint the path
......@@ -48,6 +49,7 @@ use libtestbed;
# Defines
my $FRISBEED = "$TB/sbin/frisbeed";
my $LOGFILE = "$TB/log/frisbeelauncher";
my $FRISBEEIMAGE= "$TB/sbin/frisbeeimage";
my $STD_BW = 72000000; # 71.6Mb/sec w/1000HZ kernel
my $USR_BW = 54000000; # 53.7Mb/sec w/1000HZ kernel
......@@ -91,7 +93,7 @@ if (!TBImageIDAccessCheck($UID, $imageid,
" Not enough permission!\n");
}
if (!$killmode && ! -R $filename) {
if (!$killmode && !$ELABINELAB && ! -R $filename) {
die("*** You do not have permission to read the image file for\n".
"imageid $imageid: $filename\n");
}
......@@ -211,6 +213,21 @@ if (!$address) {
&set_address($imageid,$address);
&unlock_tables;
#
# When running inside an inner Emulab, try to get the image from the
# outer emulab when it does not exist locally. Of course, it could still
# be a bogus image.
#
if ($ELABINELAB && ! -e $filename) {
$EUID = $UID;
system("$FRISBEEIMAGE $imageid");
if ($?) {
die("*** $0:\n".
" No such image file: $filename\n!");
}
$EUID = 0;
}
# Run in the background
if (TBBackGround($LOGFILE)) {
exit(0);
......@@ -227,7 +244,7 @@ set_pid($imageid, $PID);
# Drop root permissions, if we have them
#
if ($EUID == 0) {
$EUID = $UID;
$EUID = $UID;
}
#
......
......@@ -3120,6 +3120,56 @@ class elabinelab:
return EmulabResponse(RESPONSE_SUCCESS, output=output)
#
# Fire up a frisbeed for an image,
#
def frisbeelauncher(self, version, argdict):
if version != self.VERSION:
return EmulabResponse(RESPONSE_BADVERSION,
output="Client version mismatch!")
try:
checknologins()
pass
except NoLoginsError, e:
return EmulabResponse(RESPONSE_REFUSED, output=str(e))
argerror = CheckRequiredArgs(argdict, ("imageid",))
if (argerror):
return argerror
if not re.match("^[-\@\w\+\.]*$", str(argdict["imageid"])):
return EmulabResponse(RESPONSE_BADARGS,
output="Improperly formed imageid value!")
verifyerror = self.verifystuff();
if (verifyerror):
return verifyerror
argstr = escapeshellarg(argdict["imageid"])
(exitval, output) = runcommand(TBDIR + "/sbin/frisbeelauncher " + argstr)
if exitval:
return EmulabResponse(RESPONSE_ERROR, exitval >> 8, output=output)
#
# Success. Must get the loadinfo out of the DB so we can pass it back.
#
res = DBQueryFatal("select load_address from images where imageid=%s",
(argdict["imageid"],))
# Hmm, something went wrong?
if len(res) == 0:
return EmulabResponse(RESPONSE_ERROR,
output="Imageid is gone: " +
argdict["imageid"])
if (res[0][0] == None or res[0][0] == ""):
return EmulabResponse(RESPONSE_ERROR,
output="No load_address in DB: " +
argdict["imageid"])
return EmulabResponse(RESPONSE_SUCCESS, str(res[0][0]), output=output)
pass
#
......
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