Commit 231ffb8f authored by Leigh B. Stoller's avatar Leigh B. Stoller

Some minor changes for startup command; stash log file in /proj/pid/logs.

parent 8c6eb224
......@@ -118,6 +118,16 @@ if (! chown($uid, $gid, "$PROJROOT/$pid/images")) {
die("Could not chown $PROJROOT/$pid/images to $uid/$gid: $!\n");
}
if (! mkdir("$PROJROOT/$pid/logs", 0770)) {
die("Could not make directory $PROJROOT/$pid/logs: $!\n");
}
if (! chmod(0770, "$PROJROOT/$pid/logs")) {
die("Could not chmod directory $PROJROOT/$pid/logs: $!\n");
}
if (! chown($uid, $gid, "$PROJROOT/$pid/logs")) {
die("Could not chown $PROJROOT/$pid/logs to $uid/$gid: $!\n");
}
#
# Create a tftp directory for oskit kernels.
#
......
......@@ -5,9 +5,14 @@ use English;
# We are run out of the at daemon as root.
#
my $TMCC = "/etc/testbed/tmcc";
my $TMNICKNAME = "/etc/testbed/nickname";
my $TMSTARTUPCMD = "/etc/testbed/startupcmd";
#$TMRUNCMD = "/tmp/startupcmd";
my $logname;
#
# Load the testbed library.
#
push(@INC, "/etc/testbed");
require setuplib;
#
# Untaint path
......@@ -15,6 +20,15 @@ my $TMSTARTUPCMD = "/etc/testbed/startupcmd";
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Get the config parameters so we can open up a log file in the proper
# location. See below.
#
my ($pid, $eid, $vname) = check_status();
if (! defined($pid)) {
fatal("Could not determine pid/eid");
}
#
# Disconnect from the caller (at daemon).
#
......@@ -44,9 +58,12 @@ while (<CMD>) {
if (!defined($runcmd) || !defined($login)) {
fatal("$TMSTARTUPCMD not in proper format!");
}
(undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($login) or
(undef,undef,$uid,$gid,undef,undef,undef,undef) = getpwnam($login) or
fatal("Could not determine UID for $login");
chown($uid, $gid, $logname) or
fatal("Could not chown $logname to $uid/$gid: $!\n");
#
# Fork a child so that we can run the command as the user and wait for it.
#
......@@ -57,7 +74,7 @@ if ($mypid) {
#
waitpid($mypid, 0);
$stat = $?;
$stat = $? >> 8;
}
else {
#
......@@ -77,12 +94,6 @@ print STDOUT "$runcmd returned $stat\n";
#
system("$TMCC startstatus $stat");
#
# Put the log file in the callers home dir! Hmm, what about name clashes?
#
(undef,undef,undef,undef,undef,undef,undef,$homedir) = getpwnam($login);
system("/bin/cp", "$logname", "$homedir");
exit(0);
sub fatal($)
......@@ -113,21 +124,6 @@ sub background()
return $mypid;
}
#
# Open up the nickname file so we can generate a meaningfull filename.
#
$nickname = `hostname -s`;
if (open(NICK, "$TMNICKNAME")) {
$nickname = <NICK>;
close(NICK);
}
# Taint check (strips newline too)
if ($nickname =~ /^([-\@\w.]+)$/) {
$nickname = $1;
} else {
die "Bad data in $nickname";
}
#
# We have to disconnect from the caller by redirecting both STDIN and
# STDOUT away from the pipe. Otherwise the caller (the web server) will
......@@ -139,7 +135,10 @@ sub background()
#
# Create a temporary name for a log file and untaint it.
#
$logname = `mktemp /var/tmp/runlog-$nickname.XXXXXX`;
$logname = `mktemp /proj/$pid/logs/runlog-$eid.$vname.XXXXXX`;
if ($?) {
die("mktemp failed!");
}
# Note different taint check (allow /).
if ($logname =~ /^([-\@\w.\/]+)$/) {
......@@ -148,8 +147,10 @@ sub background()
die "Bad data in $logname";
}
chmod(0644, $logname);
open(STDERR, ">> $logname") or die("opening $logname for STDERR: $!");
open(STDOUT, ">> $logname") or die("opening $logname for STDOUT: $!");
return 0;
}
......@@ -45,7 +45,11 @@ my $USERDIR = "/users";
my $PROJMOUNTCMD= "/sbin/mount fs.emulab.net:/q/$PROJDIR/%s $PROJDIR/%s";
my $USERMOUNTCMD= "/sbin/mount fs.emulab.net:$USERDIR/%s $USERDIR/%s";
my $HOSTNAME = "%s\t%s-%s %s\n";
my $kernel = "/kernel.100HZ";
my $KERNEL100 = "/kernel.100HZ";
my $KERNEL1000 = "/kernel.1000HZ";
my $KERNEL10000 = "/kernel.10000HZ";
my @KERNELS = ($KERNEL100, $KERNEL1000, $KERNEL10000);
my $kernel = $KERNEL100;
#
# This is a debugging thing for my home network.
......@@ -94,7 +98,7 @@ sub check_status ()
else {
die("Error getting reservation status\n");
}
return 1;
return ($project, $eid, $vname);
}
#
......@@ -196,6 +200,7 @@ sub dohostnames ()
sub dodelays ()
{
my @delays;
my $checkreplace;
print STDOUT "Checking Testbed delay configuration ... \n";
......@@ -281,41 +286,50 @@ sub dodelays ()
# we needed to know the minimum delay. Eventually we will boot the
# correct kernel to start with via PXE.
#
if ($mindelay >= 50) {
$kernel = "/kernel.100HZ";
}
elsif ($mindelay >= 3) {
$kernel = "/kernel.1000HZ";
}
else {
$kernel = "/kernel.10000HZ";
$kernel = $KERNEL1000;
$checkreplace = 1;
}
else {
#
# Make sure we are running the correct non delay kernel. This
# is really only necessary in the absence of disk reloading.
# Further, we don't want to replace a user supplied kernel.
#
$kernel = $KERNEL100;
$checkreplace = 0;
foreach $kern (@KERNELS) {
if (system("cmp -s /kernel $kern") == 0) {
$checkreplace = 1;
}
}
}
#
# Make sure we are running the correct kernel
#
print STDOUT "Checking kernel configuration ... \n";
if (-e $kernel) {
if (system("cmp -s /kernel $kernel") != 0) {
if (system("cp -f /kernel /kernel.save")) {
print STDOUT
"Could not backup /kernel! Aborting kernel change\n";
}
else {
if (system("cp -f $kernel /kernel")) {
print STDOUT "Could not cp $kernel to /kernel! ".
"Aborting kernel change\n";
if ($checkreplace) {
#
# Make sure we are running the correct kernel.
#
if (-e $kernel) {
if (system("cmp -s /kernel $kernel") != 0) {
if (system("cp -f /kernel /kernel.save")) {
print STDOUT
"Could not backup /kernel! Aborting kernel change\n";
}
else {
system("sync");
system("reboot");
if (system("cp -f $kernel /kernel")) {
print STDOUT "Could not cp $kernel to /kernel! ".
"Aborting kernel change\n";
}
else {
system("sync");
system("reboot");
}
}
}
}
}
else {
print STDOUT "Kernel $kernel does not exist!\n";
else {
print STDOUT "Kernel $kernel does not exist!\n";
}
}
return 0;
......
......@@ -5,9 +5,14 @@ use English;
# We are run out of the at daemon as root.
#
my $TMCC = "/etc/rc.d/testbed/tmcc";
my $TMNICKNAME = "/etc/rc.d/testbed/nickname";
my $TMSTARTUPCMD = "/etc/rc.d/testbed/startupcmd";
#$TMRUNCMD = "/tmp/startupcmd";
my $logname;
#
# Load the testbed library.
#
push(@INC, "/etc/rc.d/testbed");
require setuplib;
#
# Untaint path
......@@ -15,6 +20,15 @@ my $TMSTARTUPCMD = "/etc/rc.d/testbed/startupcmd";
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/rc.d/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Get the config parameters so we can open up a log file in the proper
# location. See below.
#
my ($pid, $eid, $vname) = check_status();
if (! defined($pid)) {
fatal("Could not determine pid/eid");
}
#
# Disconnect from the caller (at daemon).
#
......@@ -44,9 +58,12 @@ while (<CMD>) {
if (!defined($runcmd) || !defined($login)) {
fatal("$TMSTARTUPCMD not in proper format!");
}
(undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($login) or
(undef,undef,$uid,$gid,undef,undef,undef,undef) = getpwnam($login) or
fatal("Could not determine UID for $login");
chown($uid, $gid, $logname) or
fatal("Could not chown $logname to $uid/$gid: $!\n");
#
# Fork a child so that we can run the command as the user and wait for it.
#
......@@ -57,7 +74,7 @@ if ($mypid) {
#
waitpid($mypid, 0);
$stat = $?;
$stat = $? >> 8;
}
else {
#
......@@ -77,11 +94,6 @@ print STDOUT "$runcmd returned $stat\n";
#
system("$TMCC startstatus $stat");
#
# Put the log file in the callers home dir! Hmm, what about name clashes?
#
system("/bin/cp", "$logname", "$homedir");
exit(0);
sub fatal($)
......@@ -112,21 +124,6 @@ sub background()
return $mypid;
}
#
# Open up the nickname file so we can generate a meaningfull filename.
#
$nickname = `hostname -s`;
if (open(NICK, "$TMNICKNAME")) {
$nickname = <NICK>;
close(NICK);
}
# Taint check (strips newline too)
if ($nickname =~ /^([-\@\w.]+)$/) {
$nickname = $1;
} else {
die "Bad data in $nickname";
}
#
# We have to disconnect from the caller by redirecting both STDIN and
# STDOUT away from the pipe. Otherwise the caller (the web server) will
......@@ -138,7 +135,10 @@ sub background()
#
# Create a temporary name for a log file and untaint it.
#
$logname = `mktemp /var/tmp/runlog-$nickname.XXXXXX`;
$logname = `mktemp /proj/$pid/logs/runlog-$eid.$vname.XXXXXX`;
if ($?) {
die("mktemp failed!");
}
# Note different taint check (allow /).
if ($logname =~ /^([-\@\w.\/]+)$/) {
......@@ -147,8 +147,10 @@ sub background()
die "Bad data in $logname";
}
chmod(0644, $logname);
open(STDERR, ">> $logname") or die("opening $logname for STDERR: $!");
open(STDOUT, ">> $logname") or die("opening $logname for STDOUT: $!");
return 0;
}
......@@ -92,7 +92,7 @@ sub check_status ()
else {
die("Error getting reservation status\n");
}
return 1;
return ($project, $eid, $vname);
}
#
......
......@@ -5,9 +5,14 @@ use English;
# We are run out of the at daemon as root.
#
my $TMCC = "/etc/testbed/tmcc";
my $TMNICKNAME = "/etc/testbed/nickname";
my $TMSTARTUPCMD = "/etc/testbed/startupcmd";
#$TMRUNCMD = "/tmp/startupcmd";
my $logname;
#
# Load the testbed library.
#
push(@INC, "/etc/testbed");
require setuplib;
#
# Untaint path
......@@ -15,6 +20,15 @@ my $TMSTARTUPCMD = "/etc/testbed/startupcmd";
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Get the config parameters so we can open up a log file in the proper
# location. See below.
#
my ($pid, $eid, $vname) = check_status();
if (! defined($pid)) {
fatal("Could not determine pid/eid");
}
#
# Disconnect from the caller (at daemon).
#
......@@ -44,9 +58,12 @@ while (<CMD>) {
if (!defined($runcmd) || !defined($login)) {
fatal("$TMSTARTUPCMD not in proper format!");
}
(undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($login) or
(undef,undef,$uid,$gid,undef,undef,undef,undef) = getpwnam($login) or
fatal("Could not determine UID for $login");
chown($uid, $gid, $logname) or
fatal("Could not chown $logname to $uid/$gid: $!\n");
#
# Fork a child so that we can run the command as the user and wait for it.
#
......@@ -57,7 +74,7 @@ if ($mypid) {
#
waitpid($mypid, 0);
$stat = $?;
$stat = $? >> 8;
}
else {
#
......@@ -77,12 +94,6 @@ print STDOUT "$runcmd returned $stat\n";
#
system("$TMCC startstatus $stat");
#
# Put the log file in the callers home dir! Hmm, what about name clashes?
#
(undef,undef,undef,undef,undef,undef,undef,$homedir) = getpwnam($login);
system("/bin/cp", "$logname", "$homedir");
exit(0);
sub fatal($)
......@@ -113,21 +124,6 @@ sub background()
return $mypid;
}
#
# Open up the nickname file so we can generate a meaningfull filename.
#
$nickname = `hostname -s`;
if (open(NICK, "$TMNICKNAME")) {
$nickname = <NICK>;
close(NICK);
}
# Taint check (strips newline too)
if ($nickname =~ /^([-\@\w.]+)$/) {
$nickname = $1;
} else {
die "Bad data in $nickname";
}
#
# We have to disconnect from the caller by redirecting both STDIN and
# STDOUT away from the pipe. Otherwise the caller (the web server) will
......@@ -139,7 +135,10 @@ sub background()
#
# Create a temporary name for a log file and untaint it.
#
$logname = `mktemp /var/tmp/runlog-$nickname.XXXXXX`;
$logname = `mktemp /proj/$pid/logs/runlog-$eid.$vname.XXXXXX`;
if ($?) {
die("mktemp failed!");
}
# Note different taint check (allow /).
if ($logname =~ /^([-\@\w.\/]+)$/) {
......@@ -148,8 +147,10 @@ sub background()
die "Bad data in $logname";
}
chmod(0644, $logname);
open(STDERR, ">> $logname") or die("opening $logname for STDERR: $!");
open(STDOUT, ">> $logname") or die("opening $logname for STDOUT: $!");
return 0;
}
#!/usr/pkg/bin/perl -wT
use English;
#
# Initialize at boot time.
#
my $TMCC = "/etc/testbed/tmcc";
my $TMIFC = "/etc/testbed/rc.ifc";
my $TMRPM = "/etc/testbed/rc.rpm";
my $TMSTARTUPCMD= "/etc/testbed/startupcmd";
my $TMGROUP = "/etc/testbed/group";
my $TMPASSWD = "/etc/testbed/master.passwd";
my $TMHOSTS = "/etc/testbed/hosts";
my $HOSTSFILE = "/etc/hosts";
my $TMNICKNAME = "/etc/testbed/nickname";
my @CONFIGS = ($TMIFC, $TMRPM, $TMSTARTUPCMD, $TMNICKNAME);
my $REBOOTCMD = "reboot";
my $STATCMD = "status";
my $IFCCMD = "ifconfig";
my $ACCTCMD = "accounts";
my $HOSTSCMD = "hostnames";
my $RPMCMD = "rpms";
my $STARTUPCMD = "startupcmd";
my $IFCONFIG = "/sbin/ifconfig cs%d alias %s netmask %s ".
"media 10baseT mediaopt full-duplex\n";
my $CP = "/bin/cp -f";
my $MKDB = "/usr/sbin/pwd_mkdb -p";
my $USERADD = "/usr/sbin/useradd";
my $USERMOD = "/usr/sbin/usermod";
my $GROUPADD = "/usr/sbin/groupadd";
my $IFACE = "cs";
my $CTLIFACENUM = "0";
my $CTLIFACE = "${IFACE}${CTLIFACENUM}";
my $project = "";
my $eid = "";
my $vname = "";
my $PROJDIR = "/proj";
my $USERDIR = "/users";
my $PROJMOUNTCMD= "/sbin/mount fs.emulab.net:/q/$PROJDIR/%s $PROJDIR/%s";
my $USERMOUNTCMD= "/sbin/mount fs.emulab.net:$USERDIR/%s $USERDIR/%s";
my $HOSTNAME = "%s\t%s-%s %s\n";
#
# This is a debugging thing for my home network.
#
my $NODE = "MYIP=155.99.214.136";
$NODE = "";
#
# Inform the master we have rebooted.
#
sub inform_reboot()
{
open(TM, "$TMCC $NODE $REBOOTCMD |")
or die "Cannot start $TMCC: $!";
close(TM)
or die $? ? "$TMCC exited with status $?" : "Error closing pipe: $!";
return 0;
}
#
# Check node allocation. Returns 0/1 for free/allocated status.
#
sub check_status ()
{
print STDOUT "Checking Testbed reservation status ... \n";
open(TM, "$TMCC $NODE $STATCMD |")
or die "Cannot start $TMCC: $!";
$_ = <TM>;
close(TM)
or die $? ? "$TMCC exited with status $?" : "Error closing pipe: $!";
if ($_ =~ /^FREE/) {
print STDOUT " Free!\n";
return 0;
}
if ($_ =~ /ALLOCATED=([-\@\w.]*)\/([-\@\w.]*) NICKNAME=([-\@\w.]*)/) {
$project = $1;
$eid = $2;
$vname = $3;
$nickname= "$vname.$eid.$project";
print STDOUT " Allocated! PID: $1, EID: $2, NickName: $nickname\n";
}
else {
die("Error getting reservation status\n");
}
return ($project, $eid, $vname);
}
#
# Stick our nickname in a file in case someone wants it.
#
sub create_nicknames()
{
open(NICK, ">$TMNICKNAME")
or die("Could not open $TMNICKNAME: $!");
print NICK "$nickname\n";
close(NICK);
return 0;
}
#
# Mount the project directory.
#
sub mount_projdir()
{
print STDOUT "Mounting the project directory on $PROJDIR/$project ... \n";
if (! -e "$PROJDIR/$project") {
if (! mkdir("$PROJDIR/$project", 0770)) {
print STDERR "Could not make directory $PROJDIR/$project: $!\n";
}
}
if (system("mount | egrep -s -q ' $PROJDIR/$project '")) {
if (system(sprintf($PROJMOUNTCMD, $project, $project)) != 0) {
print STDERR
"Could not mount project directory on $PROJDIR/$project.\n";
}
}
return 0;
}
1;
......@@ -446,15 +446,18 @@ NFS. This is either the project's <tt>/proj</tt> directory, or a
project member's home directory in <tt>/users</tt>.
<p>
The exit value of the startup command is reported back to the Web
Interface, and is made available to you via the "Experiment
Information" link. There is a listing for all of the nodes in the
experiment, and the exit value is recorded in this listing. The
special symbol <tt>none</tt> indicates that the node is still running
the startup command. The startup command is especially useful when
combined with <a href="#BatchMode"><i>batch mode</i></a> experiments.
the startup command. A log file containing the output of the startup
command is created in the project's <tt>logs</tt> directory
(<tt>/proj/pid/logs</tt>).
<p>
The startup command is especially useful when
combined with <a href="#BatchMode"><i>batch mode</i></a> experiments.
<p>
<li> <a NAME="ReadyBits"></a>
......@@ -572,7 +575,9 @@ sudo /usr/local/bin/create-delta /proj/testbed/foo.delta </code></pre>
The argument to the <tt>create-delta</tt> command is a complete
pathname, which <b>must</b> reside someplace in your /proj directory
(a subdirectory is fine). You cannot write the delta file to any
other filesystem. It should be noted that a delta created on one OS
other filesystem. This restriction is enforced so that diskspace (and
resources in general) can be accounted for on a per-project basis.
It should be noted that a delta created on one OS
cannot be installed on another. In other words, a delta created on a
FreeBSD machine can only be installed on a FreeBSD machine. If you
need the same software installed on a Linux machine as well, you will
......
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