All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit aef08532 authored by Leigh B. Stoller's avatar Leigh B. Stoller

* Removed startexp, and merged its contents into batchexp. There has been

  no reason for the separation for a long time, and it made maintence more
  difficult cause of duplication between batchexp and startexp (batch was
  the sole user of startexp). Cleaner solution.

* Check argument processing for batchexp, swapexp, endexp to make sure the
  taint checks are correct. All three of these scripts will now be
  available from ops. I especially watch the filename processing, which was
  pretty loose before and could allow some to grab a file on boss by trying
  to use it as an NS file (scripts all runs as user of course). The web
  interface generates filenames that are hard to guess, so rather then
  wrapping these scripts when invoked from ops, just allow the usual paths
  (/proj, /groups, /users) but also /tmp/$uid-XXXXXX.nsfile pattern, which
  should be hard enough to guess that users will not be able to get
  anything they are not supposed to.

* Add -w (waitmode) options to all three scripts. In waitmode, the backend
  detaches, but the parent remains waiting for the child to finish so it
  can exit with the appropriate status (for scripting). The user can
  interrupt (^C), but it has no effect on the backend; it just kills the
  parent side that is waiting (backend is in a new session ID). Log outout
  still goes to the file (available from web page) and is emailed.
parent f014e8b0
......@@ -16,14 +16,15 @@ include $(OBJDIR)/Makeconf
SUBDIRS = checkpass ns2ir ipassign nseparse
BIN_STUFF = power snmpit tbend tbprerun tbreport \
os_load startexp endexp batchexp swapexp \
os_load endexp batchexp swapexp \
node_reboot nscheck node_update savelogs node_control \
portstats checkports eventsys_control os_select tbrestart \
tbswap nseswap tarfiles_setup
# Stuff that mere users get on plastic.
USERBINS = os_load node_reboot nscheck node_update savelogs \
node_control portstats batchexp eventsys_control
node_control portstats batchexp eventsys_control \
swapexp endexp
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \
......@@ -35,7 +36,7 @@ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \
os_setup mkexpdir console_setup webnscheck webreport \
webstartexp webendexp webbatchexp \
webendexp webbatchexp \
assign_wrapper assign_prepass ptopgen webnodeupdate \
webdelay_config \
webrmgroup webswapexp webnodecontrol \
......
This diff is collapsed.
......@@ -2,7 +2,7 @@
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2003 University of Utah and the Flux Group.
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -22,10 +22,12 @@ use Getopt::Std;
#
sub usage()
{
print STDOUT "Usage: endexp [-b] <pid> <eid>\n";
print STDOUT "Usage: endexp [-b | -w] <pid> <eid>\n";
exit(-1);
}
my $optlist = "b";
my $optlist = "bw";
my $waitmode = 0;
my $batch = 0;
#
# Exit codes are important; they tell the web page what has happened so
......@@ -72,7 +74,6 @@ $libdb::DBQUERY_MAXTRIES = 30;
my $tbdir = "$TB/bin/";
my $projroot = "/proj";
my $tbdata = "tbdata";
my $batch = 0;
my $nextstate;
my $logname;
my $dbuid;
......@@ -105,19 +106,24 @@ if (@ARGV != 2) {
my $pid = $ARGV[0];
my $eid = $ARGV[1];
if (defined($options{"b"})) {
$batch = $options{"b"};
$batch = 1;
}
if (defined($options{"w"})) {
$waitmode = 1;
}
usage()
if ($waitmode && $batch);
#
# Untaint the arguments.
#
if ($pid =~ /^([-\@\w.]+)$/) {
if ($pid =~ /^([-\w\.]+)$/) {
$pid = $1;
}
else {
die("Tainted argument $pid!\n");
}
if ($eid =~ /^([-\@\w.]+)$/) {
if ($eid =~ /^([-\w\.]+)$/) {
$eid = $1;
}
else {
......@@ -152,6 +158,14 @@ if ($UID && !TBAdmin($UID) &&
" You do not have permission to end this experiment!\n");
}
#
# In wait mode, block interrupt until we spin off the background process.
#
if ($waitmode) {
$SIG{TERM} = 'IGNORE';
$SIG{QUIT} = 'IGNORE';
$SIG{INT} = 'IGNORE';
}
#
# We have to protect against trying to end an experiment that is currently
......@@ -328,17 +342,49 @@ if (! $batch) {
TBExptSetLogFile($pid, $eid, $logname);
TBExptOpenLogFile($pid, $eid);
if (TBBackGround($logname)) {
if (my $childpid = TBBackGround($logname)) {
#
# Parent exits normally, except if in waitmode.
#
if (!$waitmode) {
ExitWithStatus(0,
"Experiment $pid/$eid is now terminating.\n".
"You will be notified via email when the experiment has been\n".
"torn down, and you can reuse the experiment name.\n");
}
print("Waiting for experiment $eid to finish terminating.\n");
print("You may type ^C at anytime; you will be notified via email;\n".
"later; you will not actually interrupt the experiment itself.\n");
# Give child a chance to run.
select(undef, undef, undef, 0.25);
#
# Reset signal handlers. User can now kill this process, without
# stopping the child.
#
$SIG{TERM} = 'DEFAULT';
$SIG{INT} = 'DEFAULT';
$SIG{QUIT} = 'DEFAULT';
#
# Parent exits normally
# Wait until child exits or until user gets bored and types ^C.
#
ExitWithStatus(0,
"Experiment $pid/$eid is now terminating.\n".
"You will be notified via email when the experiment has been\n".
"torn down, and you can reuse the experiment name.\n");
waitpid($childpid, 0);
print("Done. Exited with status: $?\n");
exit($? >> 8);
}
}
#
# When in waitmode, must put ourselves in another process group so that
# an interrupt to the parent will not have any effect on the backend.
#
if ($waitmode) {
POSIX::setsid();
}
#
# Sanity check states in case someone changes something.
#
......
This diff is collapsed.
......@@ -8,6 +8,7 @@
use English;
use Getopt::Std;
use POSIX qw(setsid);
#
# This gets invoked from the Web interface.
......@@ -16,11 +17,11 @@ use Getopt::Std;
sub usage()
{
print STDOUT "Usage: swapexp [-b] [-i | -a | -f] [-r] [-e] ".
print STDOUT "Usage: swapexp [-b | -w] [-i | -a | -f] [-r] [-e] ".
"<-s in | out | restart | modify | pause> <pid> <eid> [<nsfile>]\n";
exit(-1);
}
my $optlist = "biafres:";
my $optlist = "biafres:w";
#
# Exit codes are important; they tell the web page what has happened so
......@@ -69,6 +70,7 @@ my $idleswap = 0;
my $autoswap = 0;
my $force = 0;
my $reboot = 0;
my $waitmode = 0;
my $eventsys_restart = 0;
my $errorstat= -1;
my $modifyHosed = 0;
......@@ -113,6 +115,9 @@ if (! getopts($optlist, \%options)) {
if (defined($options{"i"})) {
$idleswap = 1;
}
if (defined($options{"w"})) {
$waitmode = 1;
}
if (defined($options{"a"})) {
$autoswap = 1;
}
......@@ -143,9 +148,11 @@ else {
usage();
}
if ($inout ne "modify" && @ARGV != 2) {
usage();
}
usage()
if (($waitmode && $batch) ||
($inout ne "modify" && @ARGV != 2) ||
(($waitmode || $batch) && ($idleswap || $autoswap || $force)));
if ($eventsys_restart && $inout ne "modify") {
print STDOUT "Usage: swapexp: -e (eventsys_restart) can be used ".
"only with -s modify\n";
......@@ -157,13 +164,13 @@ my $eid = $ARGV[1];
#
# Untaint the arguments.
#
if ($pid =~ /^([-\@\w.]+)$/) {
if ($pid =~ /^([-\w\.]+)$/) {
$pid = $1;
}
else {
die("Tainted argument $pid!\n");
}
if ($eid =~ /^([-\@\w.]+)$/) {
if ($eid =~ /^([-\w\.]+)$/) {
$eid = $1;
}
else {
......@@ -181,13 +188,42 @@ if ($inout eq "modify" && @ARGV > 2) {
#
# Untaint nsfile argument; Allow slash.
#
if ($tempnsfile =~ /^([-\w.\/]+)$/) {
if ($tempnsfile =~ /^([-\w\.\/]+)$/) {
$tempnsfile = $1;
}
else {
die("Tainted nsfile name: $tempnsfile");
die("Tainted nsfile name: $tempnsfile\n");
}
#
# Called from ops interactively. Make sure NS file in /proj or /users.
#
# Use realpath to resolve any symlinks.
#
my $translated = `realpath $tempnsfile`;
if ($translated =~ /^([-\w\.\/]+)$/) {
$tempnsfile = $1;
}
if (! -f $tempnsfile || -z $tempnsfile) {
else {
die("Tainted nsfile returned by realpath: $translated\n");
}
#
# The file must reside in /proj, /groups, or /users. Since this script
# runs as the caller, regular file permission checks ensure its a file
# the user is allowed to use. /tmp/$guid-$nsref.nsfile also allowed
# since this script is invoked directly from web interface, which generates
# a name that should not be guessable, so as long as it looks to be in
# proper format, we accept it.
#
if (! ($tempnsfile =~ /^\/tmp\/[-\w]+-\d+\.nsfile/) &&
! ($tempnsfile =~ /^\/var\/tmp\/php\w+/) &&
! ($tempnsfile =~ /^\/proj/) &&
! ($tempnsfile =~ /^\/groups/) &&
! ($tempnsfile =~ /^\/users/)) {
die("$tempnsfile does not resolve to an appropriate directory!\n");
}
if (! -f $tempnsfile || -z $tempnsfile || ! -r $tempnsfile) {
die("*** $0:\n".
" $tempnsfile does not look like an NS file!\n");
}
......@@ -224,6 +260,15 @@ if ($UID && !TBAdmin($UID) &&
# idleswap is in minutes, threshold is in hours
$idleswap_time = 60 * TBGetSiteVar("idle/threshold");
#
# In wait mode, block interrupt until we spin off the background process.
#
if ($waitmode) {
$SIG{TERM} = 'IGNORE';
$SIG{QUIT} = 'IGNORE';
$SIG{INT} = 'IGNORE';
}
#
# We have to protect against trying to end an experiment that is currently
# in the process of being terminated. We use a "wrapper" state (actually
......@@ -553,16 +598,48 @@ if (! $batch) {
TBExptSetLogFile($pid, $eid, $logname);
TBExptOpenLogFile($pid, $eid);
if (TBBackGround($logname)) {
if (my $childpid = TBBackGround($logname)) {
#
# Parent exits normally, except if in waitmode.
#
if (!$waitmode) {
print "Experiment $pid/$eid is now being $action.\n".
"You will be notified via email when the this is done.\n";
exit(0);
}
print("Waiting for experiment $eid to finish its swap${action}\n");
print("You may type ^C at anytime; you will be notified via email;\n".
"later; you will not actually interrupt the experiment itself.\n");
# Give child a chance to run.
select(undef, undef, undef, 0.25);
#
# Reset signal handlers. User can now kill this process, without
# stopping the child.
#
$SIG{TERM} = 'DEFAULT';
$SIG{INT} = 'DEFAULT';
$SIG{QUIT} = 'DEFAULT';
#
# Parent exits normally
# Wait until child exits or until user gets bored and types ^C.
#
print "Experiment $pid/$eid is now being $action.\n".
"You will be notified via email when the this is done.\n";
exit(0);
waitpid($childpid, 0);
print("Done. Exited with status: $?\n");
exit($? >> 8);
}
}
#
# When in waitmode, must put ourselves in another process group so that
# an interrupt to the parent will not have any effect on the backend.
#
if ($waitmode) {
POSIX::setsid();
}
#
# Gather stats; start clock ticking
#
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
#
# This gets invoked from the Web interface. Simply a wrapper for experiment
# creation.
#
# usage: webstartexp arguments ...
#
#
# Configure variables
#
my $TB = "@prefix@";
#
# Run the real thing, and never return.
#
exec "$TB/bin/startexp", @ARGV;
die("webstartexp: Could not exec startexp: $!");
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