Commit fec93fd8 authored by Leigh B. Stoller's avatar Leigh B. Stoller
Browse files

First cut at automatic RPM installation and autorun of per-node

startup command execution.
parent 798b6f7f
......@@ -19,3 +19,12 @@ if [ -x /etc/testbed/rc.delay ]; then
/etc/testbed/rc.delay
fi
if [ -x /etc/testbed/rc.rpm ]; then
echo "Installing RPMS"
/etc/testbed/rc.rpm
fi
if [ -x /etc/testbed/startupcmd ]; then
echo "Scheduling startup command to run in a little bit"
echo "/etc/testbed/runstartup" | at 'now + 5 minutes'
fi
#!/usr/bin/perl -wT
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";
#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Disconnect from the caller (at daemon).
#
if (background()) {
#
# Parent exits normally
#
exit 0;
}
#
# Open up the command file, which tells us what to do.
#
open(CMD, "$TMSTARTUPCMD") or
fatal("Could not open $TMSTARTUPCMD: $!");
my $runcmd;
my $login;
while (<CMD>) {
if ($_ =~ /CMD=([-\@\w.\/ ]+) UID=([0-9a-z]+)/) {
$runcmd = $1;
$login = $2;
}
}
if (!defined($runcmd) || !defined($login)) {
fatal("$TMSTARTUPCMD not in proper format!");
}
if (($uid = getpwnam($login)) == 0) {
fatal("Could not determine UID for $login");
}
#
# Fork a child so that we can run the command as the user and wait for it.
#
$mypid = fork();
if ($mypid) {
#
# Parent waits for child.
#
waitpid($mypid, 0);
$stat = $?;
}
else {
#
# The child becomes the user and runs the command.
#
$EUID = $UID = $uid;
exec($runcmd);
fatal("Could not exec $runcmd");
}
print STDOUT "$runcmd returned $stat\n";
#
# Use the TMCC to tell the TMCD what the exit status was.
#
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($)
{
my($mesg) = $_[0];
print STDOUT "$mesg\n";
#
# Use the TMCC to tell the TMCD that we screwed the pooch.
#
system("$TMCC startstatus 666");
exit(-1);
}
#
# Put ourselves into the background so that caller sees immediate response.
#
sub background()
{
# Turn off line buffering on output
#
$| = 1;
$mypid = fork();
if ($mypid) {
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
# continue to wait even though the parent has exited.
#
open(STDIN, "< /dev/null") or
die("opening /dev/null for STDIN: $!");
#
# Create a temporary name for a log file and untaint it.
#
$logname = `mktemp /var/tmp/runlog-$nickname.XXXXXX`;
# Note different taint check (allow /).
if ($logname =~ /^([-\@\w.\/]+)$/) {
$logname = $1;
} else {
die "Bad data in $logname";
}
open(STDERR, ">> $logname") or die("opening $logname for STDERR: $!");
open(STDOUT, ">> $logname") or die("opening $logname for STDOUT: $!");
return 0;
}
......@@ -7,19 +7,25 @@ use English;
my $TMCC = "/etc/testbed/tmcc";
my $TMIFC = "/etc/testbed/rc.ifc";
my $TMDELAY = "/etc/testbed/rc.delay";
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 @CONFIGS = ($TMIFC, $TMDELAY);
my $TMNICKNAME = "/etc/testbed/nickname";
my @CONFIGS = ($TMIFC, $TMDELAY, $TMRPM, $TMSTARTUPCMD, $TMNICKNAME);
my $REBOOTCMD = "reboot";
my $STATCMD = "status";
my $IFCCMD = "ifconfig";
my $ACCTCMD = "accounts";
my $DELAYCMD = "delay";
my $HOSTSCMD = "hostnames";
my $RPMCMD = "rpms";
my $STARTUPCMD = "startupcmd";
my $IFCONFIG = "/sbin/ifconfig fxp%d inet %s netmask %s ".
"media 100baseTX mediaopt full-duplex\n";
my $RPMINSTALL = "/usr/local/bin/rpm -i %s\n";
my $CP = "/bin/cp -f";
my $MKDB = "/usr/sbin/pwd_mkdb -p";
my $PW = "/usr/sbin/pw";
......@@ -28,6 +34,8 @@ my $IFACE = "fxp";
my $CTLIFACENUM = "4";
my $CTLIFACE = "${IFACE}${CTLIFACENUM}";
my $project = "";
my $eid = "";
my $vname = "";
my $PROJDIR = "/proj";
my $MOUNTCMD = "/sbin/mount fs.emulab.net:/q/proj/";
my $HOSTNAME = "%s\t%s-%s %s\n";
......@@ -73,14 +81,25 @@ if ($_ =~ /^FREE/) {
print STDOUT " Free!\n";
exit(0);
}
if ($_ =~ /ALLOCATED=([-\@\w.]*)\/([-\@\w.]*)/) {
print STDOUT " Allocated: $1/$2!\n";
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");
}
#
# Stick our nickname in a file in case someone wants it.
#
open(NICK, ">$TMNICKNAME")
or die("Could not open $TMNICKNAME");
print NICK "$nickname\n";
close(NICK);
#
# Mount the project directory.
#
......@@ -332,6 +351,48 @@ while (<TM>) {
}
close(TM);
#
# RPM configuration. Done after account stuff!
#
print STDOUT "Checking Testbed RPM configuration ... \n";
open(TM, "$TMCC $NODE $RPMCMD |")
or die "Cannot start $TMCC: $!";
open(RPM, ">$TMRPM")
or die("Could not open $TMRPM");
print RPM "#!/bin/sh\n";
while (<TM>) {
if ($_ =~ /RPM=([-\@\w.\/]+)/) {
printf STDOUT " $RPMINSTALL", $1;
printf RPM "echo \"Installing RPM $1\"\n", $1;
printf RPM "$RPMINSTALL", $1;
}
}
close(TM);
close(RPM);
chmod(0755, "$TMRPM");
#
# Experiment startup Command.
#
print STDOUT "Checking Testbed Experiment Run Command configuration ... \n";
open(TM, "$TMCC $NODE $STARTUPCMD |")
or die "Cannot start $TMCC: $!";
open(RUN, ">$TMSTARTUPCMD")
or die("Could not open $TMSTARTUPCMD");
while (<TM>) {
if ($_ =~ /CMD=([-\@\w.\/ ]+) UID=([0-9a-z]+)/) {
print STDOUT " Will run $1 as $2\n";
print RUN "$_\n";
}
}
close(TM);
close(RUN);
chmod(0755, "$TMSTARTUPCMD");
#
# If node is free, reset to a moderately clean state.
#
......
......@@ -13,3 +13,13 @@ if [ -x /etc/rc.d/testbed/rc.ifc ]; then
echo "Setting up Testbed Interfaces"
/etc/rc.d/testbed/rc.ifc
fi
if [ -x /etc/rc.d/testbed/rc.rpm ]; then
echo "Installing RPMS"
/etc/rc.d/testbed/rc.rpm
fi
if [ -x /etc/rc.d/testbed/startupcmd ]; then
echo "Scheduling startup command to run in a little bit"
echo "/etc/rc.d/testbed/runstartup" | at 'now + 5 minutes'
fi
#!/usr/bin/perl -wT
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";
#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/rc.d/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Disconnect from the caller (at daemon).
#
if (background()) {
#
# Parent exits normally
#
exit 0;
}
#
# Open up the command file, which tells us what to do.
#
open(CMD, "$TMSTARTUPCMD") or
fatal("Could not open $TMSTARTUPCMD: $!");
my $runcmd;
my $login;
while (<CMD>) {
if ($_ =~ /CMD=([-\@\w.\/ ]+) UID=([0-9a-z]+)/) {
$runcmd = $1;
$login = $2;
}
}
if (!defined($runcmd) || !defined($login)) {
fatal("$TMSTARTUPCMD not in proper format!");
}
if (($uid = getpwnam($login)) == 0) {
fatal("Could not determine UID for $login");
}
#
# Fork a child so that we can run the command as the user and wait for it.
#
$mypid = fork();
if ($mypid) {
#
# Parent waits for child.
#
waitpid($mypid, 0);
$stat = $?;
}
else {
#
# The child becomes the user and runs the command.
#
$EUID = $UID = $uid;
exec($runcmd);
fatal("Could not exec $runcmd");
}
print STDOUT "$runcmd returned $stat\n";
#
# Use the TMCC to tell the TMCD what the exit status was.
#
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($)
{
my($mesg) = $_[0];
print STDOUT "$mesg\n";
#
# Use the TMCC to tell the TMCD that we screwed the pooch.
#
system("$TMCC startstatus 666");
exit(-1);
}
#
# Put ourselves into the background so that caller sees immediate response.
#
sub background()
{
# Turn off line buffering on output
#
$| = 1;
$mypid = fork();
if ($mypid) {
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
# continue to wait even though the parent has exited.
#
open(STDIN, "< /dev/null") or
die("opening /dev/null for STDIN: $!");
#
# Create a temporary name for a log file and untaint it.
#
$logname = `mktemp /var/tmp/runlog-$nickname.XXXXXX`;
# Note different taint check (allow /).
if ($logname =~ /^([-\@\w.\/]+)$/) {
$logname = $1;
} else {
die "Bad data in $logname";
}
open(STDERR, ">> $logname") or die("opening $logname for STDERR: $!");
open(STDOUT, ">> $logname") or die("opening $logname for STDOUT: $!");
return 0;
}
......@@ -6,13 +6,16 @@ use English;
#
my $TMCC = "/etc/rc.d/testbed/tmcc";
my $TMIFC = "/etc/rc.d/testbed/rc.ifc";
my $TMRPM = "/etc/rc.d/testbed/rc.rpm";
my $TMSTARTUPCMD= "/etc/rc.d/testbed/startupcmd";
my $TMGROUP = "/etc/rc.d/testbed/group";
my $TMPASSWD = "/etc/rc.d/testbed/passwd";
my $TMSHADOW = "/etc/rc.d/testbed/shadow";
my $TMGSHADOW = "/etc/rc.d/testbed/gshadow";
my $TMHOSTS = "/etc/rc.d/testbed/hosts";
my $TMNICKNAME = "/etc/rc.d/testbed/nickname";
my $HOSTSFILE = "/etc/hosts";
my @CONFIGS = ($TMIFC);
my @CONFIGS = ($TMIFC, $TMRPM, $TMSTARTUPCMD, $TMNICKNAME);
my @LOCKFILES = ("/etc/group.lock", "/etc/gshadow.lock");
my $REBOOTCMD = "reboot";
my $STATCMD = "status";
......@@ -20,7 +23,10 @@ my $IFCCMD = "ifconfig";
my $ACCTCMD = "accounts";
my $DELAYCMD = "delay";
my $HOSTSCMD = "hostnames";
my $RPMCMD = "rpms";
my $STARTUPCMD = "startupcmd";
my $IFCONFIG = "/sbin/ifconfig eth%d inet %s netmask %s\n";
my $RPMINSTALL = "/bin/rpm -i %s\n";
my $CP = "/bin/cp -f";
my $USERADD = "/usr/sbin/useradd";
my $USERMOD = "/usr/sbin/usermod";
......@@ -29,6 +35,8 @@ my $IFACE = "eth";
my $CTLIFACENUM = "4";
my $CTLIFACE = "${IFACE}${CTLIFACENUM}";
my $project = "";
my $eid = "";
my $vname = "";
my $PROJDIR = "/proj";
my $MOUNTCMD = "/bin/mount fs.emulab.net:/q/proj/";
my $HOSTNAME = "%s\t%s-%s %s\n";
......@@ -73,13 +81,24 @@ if ($_ =~ /^FREE/) {
print STDOUT " Free!\n";
exit(0);
}
if ($_ =~ /ALLOCATED=([-\@\w.]*)\/([-\@\w.]*)/) {
print STDOUT " Allocated: $1/$2!\n";
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");
}
#
# Stick our nickname in a file in case someone wants it.
#
open(NICK, ">$TMNICKNAME")
or die("Could not open $TMNICKNAME");
print NICK "$nickname\n";
close(NICK);
#
# Mount the project directory.
......@@ -210,6 +229,49 @@ while (<TM>) {
}
close(TM);
#
# RPM configuration. Done after account stuff!
#
print STDOUT "Checking Testbed RPM configuration ... \n";
open(TM, "$TMCC $NODE $RPMCMD |")
or die "Cannot start $TMCC: $!";
open(RPM, ">$TMRPM")
or die("Could not open $TMRPM");
print RPM "#!/bin/sh\n";
while (<TM>) {
if ($_ =~ /RPM=([-\@\w.\/]+)/) {
printf STDOUT " $RPMINSTALL", $1;
printf RPM "echo \"Installing RPM $1\"\n", $1;
printf RPM "$RPMINSTALL", $1;
}
}
close(TM);
close(RPM);
chmod(0755, "$TMRPM");
#
# Experiment startup Command.
#
print STDOUT "Checking Testbed Experiment Run Command configuration ... \n";
open(TM, "$TMCC $NODE $STARTUPCMD |")
or die "Cannot start $TMCC: $!";
open(RUN, ">$TMSTARTUPCMD")
or die("Could not open $TMSTARTUPCMD");
while (<TM>) {
if ($_ =~ /CMD=([-\@\w.\/ ]+) UID=([0-9a-z]+)/) {
print STDOUT " Will run $1 as $2\n";
print RUN "$_\n";
}
}
close(TM);
close(RUN);
chmod(0755, "$TMSTARTUPCMD");
#
# If node is free, reset to a moderately clean state.
#
......
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