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

Convert the setup script into a bunch of little subroutines in a perl

module file. Setup is now very short and simple, calling functions in
the library. The prepare script and the new rc.delta script load the
setuplib.pm module and use functions in there. Eventually, the library
should be common to all three OSs, but that was too much to deal with
today.
parent a9d61389
#!/usr/bin/perl -wT
use English;
#
# Load Deltas.
#
my $reboot = 0;
#
# Load the testbed library.
#
push(@INC, "/etc/testbed");
require setuplib;
#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Inform the master that we have rebooted.
#
#
# Inform the master that we have rebooted.
#
inform_reboot();
#
# Check allocation. Exit now if not allocated.
#
if (! check_status()) {
exit(0);
}
#
# Mount the project directory.
#
mount_projdir();
#
# Delta configuration.
#
$reboot = install_deltas();
if ($reboot) {
system("sync");
system("reboot");
}
exit 0;
#!/usr/bin/perl -wT
use English;
#
# Initialize at boot time.
#
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 $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 $STARTSTATCMD= "startstatus";
my $READYCMD = "ready";
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";
my $CHPASS = "/usr/bin/chpass";
my $IFACE = "fxp";
my $CTLIFACENUM = "4";
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";
my $kernel = "/kernel.100HZ";
#
# This is a debugging thing for my home network.
#
my $NODE = "MYIP=155.101.132.101";
$NODE = "";
push(@INC, "/etc/testbed");
require setuplib;
#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/rc.d/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
......@@ -65,385 +18,53 @@ cleanup_node();
#
# Inform the master that we have rebooted.
#
open(TM, "$TMCC $NODE $REBOOTCMD |")
or die "Cannot start $TMCC: $!";
close(TM)
or die $? ? "$TMCC exited with status $?" : "Error closing pipe: $!";
inform_reboot();
#
# See if this node is allocated to an experiment.
# Check allocation. Exit now if not allocated.
#
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";
if (! check_status()) {
exit(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");
}
#
# Stick our nickname in a file in case someone wants it.
# Setup a nicknames file.
#
open(NICK, ">$TMNICKNAME")
or die("Could not open $TMNICKNAME");
print NICK "$nickname\n";
close(NICK);
create_nicknames();
#
# Mount the project directory.
#
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(sprintf($PROJMOUNTCMD, $project, $project)) != 0) {
print STDERR "Could not mount project directory on $PROJDIR/$project.\n";
}
#
mount_projdir();
#
# Okay, lets find out about interfaces.
# Write a file of ifconfig lines, which will get executed.
#
print STDOUT "Checking Testbed interface configuration ... \n";
#
# Open a connection to the TMCD, and then open a local file into which
# we write ifconfig commands (as a shell script).
#
open(TM, "$TMCC $NODE $IFCCMD |")
or die "Cannot start $TMCC: $!";
open(IFC, ">$TMIFC")
or die("Could not open $TMIFC");
print IFC "#!/bin/sh\n";
while (<TM>) {
$_ =~ /INTERFACE=(\d*) INET=([0-9.]*) MASK=([0-9.]*)/;
printf STDOUT " $IFCONFIG", $1, $2, $3;
printf IFC $IFCONFIG, $1, $2, $3;
}
close(TM);
close(IFC);
chmod(0755, "$TMIFC");
doifconfig();
#
# Host names configuration (/etc/hosts).
#
print STDOUT "Checking Testbed /etc/hosts configuration ... \n";
open(TM, "$TMCC $NODE $HOSTSCMD |")
or die "Cannot start $TMCC: $!";
open(HOSTS, ">>$HOSTSFILE")
or die("Could not open $HOSTSFILE");
#
# Now convert each hostname into hosts file representation and write
# it to the hosts file.
#
while (<TM>) {
$_ =~ /NAME=([-\@\w.]+) LINK=([0-9]*) IP=([0-9.]*) ALIAS=([-\@\w.]*)/;
printf STDOUT " $1, $2, $3, $4\n";
printf HOSTS $HOSTNAME, $3, $1, $2, $4;
}
close(TM);
close(HOSTS);
dohostnames();
#
# Delay node configuration
# Check for delay config.
#
print STDOUT "Checking Testbed delay configuration ... \n";
my @delays;
open(TM, "$TMCC $NODE $DELAYCMD |")
or die "Cannot start $TMCC: $!";
while (<TM>) {
push(@delays, $_);
}
close(TM);
if (@delays) {
$count = 69;
$mindelay = 10000;
# foreach $delay (@delays) {
# print $delay;
# }
open(DEL, ">$TMDELAY")
or die("Could not open $TMDELAY");
print DEL "#!/bin/sh\n";
print DEL "sysctl -w net.link.ether.bridge=0\n";
print DEL "sysctl -w net.link.ether.bridge_ipfw=0\n";
print DEL "sysctl -w net.link.ether.bridge_cfg=${CTLIFACE}:6,";
foreach $delay (@delays) {
$delay =~ /DELAY INT0=(\d) INT1=(\d) DELAY/;
print DEL "$IFACE$1:$count,$IFACE$2:$count,";
$count++;
}
print DEL "\n";
print DEL "sysctl -w net.link.ether.bridge=1\n";
print DEL "sysctl -w net.link.ether.bridge_ipfw=1\n";
print DEL "ipfw -f flush\n";
$count = 69;
$pipe = 100;
foreach $delay (@delays) {
$delay =~
/DELAY INT0=(\d) INT1=(\d) DELAY=(\d+) BW=([\d\.]+) PLR=([\d\.]+)/;
$iface1 = "$IFACE$1";
$iface2 = "$IFACE$2";
$p1 = $pipe += 10;
$p2 = $pipe += 10;
$delay = $3;
$bandw = $4;
$plr = $5;
#
# We want to know what the minimum delay is so we can boot the
# the correct kernel.
#
if ($delay < $mindelay) {
$mindelay = $delay;
}
dodelays();
print DEL "ifconfig $iface1 media 100baseTX mediaopt full-duplex\n";
print DEL "ifconfig $iface2 media 100baseTX mediaopt full-duplex\n";
print DEL "ipfw add pipe $p1 ip from any to any in recv $iface1\n";
print DEL "ipfw add pipe $p2 ip from any to any in recv $iface2\n";
print DEL "ipfw pipe $p1 config delay ${delay}ms bw ${bandw}Mbit/s ";
print DEL "plr $plr\n";
print DEL "ipfw pipe $p2 config delay ${delay}ms bw ${bandw}Mbit/s ";
print DEL "plr $plr\n";
print STDOUT " $iface1/$iface2 pipe $p1/$p2 config delay ";
print STDOUT "${delay}ms bw ${bandw}Mbit/s plr $plr\n";
$count++;
}
#
# If a delay node, then lets report status and ready in so that batch
# experiments do not become stuck.
#
print DEL "$TMCC $READYCMD\n";
print DEL "$TMCC $STARTSTATCMD 0\n";
print DEL "echo \"Delay Configuration Complete\"\n";
close(DEL);
chmod(0755, "$TMDELAY");
#
# Now do kernel configuration. All of the above work is wasted, but
# we needed to know the minimum delay. Eventually we will boot the
# correct kernel to start with via PXE.
#
if ($mindelay >= 20) {
$kernel = "/kernel.100HZ";
}
elsif ($mindelay >= 3) {
$kernel = "/kernel.1000HZ";
}
else {
$kernel = "/kernel.10000HZ";
}
}
#
# 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";
}
else {
system("sync");
system("reboot");
}
}
}
}
else {
print STDOUT "Kernel $kernel does not exist!\n";
}
#
# Account stuff. Again, open a connection to the TMCD, and receive
# ADDGROUP and ADDUSER commands. We turn those into "pw" commands.
#
print STDOUT "Checking Testbed group/user configuration ... \n";
open(TM, "$TMCC $NODE $ACCTCMD |")
or die "Cannot start $TMCC: $!";
while (<TM>) {
if ($_ =~ /^ADDGROUP NAME=([-\@\w.]+) GID=([0-9]+)/) {
print STDOUT " Group: $1/$2\n";
$group = $1;
$gid = $2;
($exists) = getgrgid($gid);
if ($exists) {
next;
}
if (system("$PW groupadd $group -g $gid") != 0) {
print STDERR "Error adding new group $1/$2: $!\n";
}
next;
}
if ($_ =~
/^ADDUSER LOGIN=([0-9a-z]+) PSWD=([^:]+) UID=(\d+) GID=(\d+) ROOT=(\d) NAME="(.*)"/)
{
$login = $1;
$pswd = $2;
$uid = $3;
$gid = $4;
$root = $5;
$name = $6;
if ( $name =~ /^(([^:]+$|^))$/ ) {
$name = $1;
}
print STDOUT " User: $login/$uid/$gid/$root/$name\n";
if (! -e "$USERDIR/$login") {
if (! mkdir("$USERDIR/$login", 0770)) {
print STDERR "Could not mkdir $USERDIR/$login: $!\n";
next;
}
}
if (system("mount | egrep -s ' $USERDIR/$login '")) {
if (system(sprintf($USERMOUNTCMD, $login, $login)) != 0) {
print STDERR
"Could not mount users directory on $USERDIR/$login.\n";
next;
}
}
($exists) = getpwuid($uid);
if ($exists) {
if ($root) {
$GLIST = "-G wheel,$gid";
}
else {
$GLIST = "-G $gid";
}
system("$PW usermod $login $GLIST");
next;
}
$GLIST = " ";
if ($root) {
$GLIST = "-G wheel";
}
if (system("$PW useradd $login -u $uid -g $gid $GLIST ".
"-d $USERDIR/$login -s /bin/tcsh -c \"$name\"") != 0) {
print STDERR "Error adding new user $login\n";
next;
}
if (system("$CHPASS -p $pswd $login") != 0) {
print STDERR "Error changing password for user $login\n";
}
next;
}
}
close(TM);
# Do account stuff.
#
doaccounts();
#
# RPM configuration. Done after account stuff!
# RPMS
#
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");
dorpms();
#
# 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.
#
sub cleanup_node () {
print STDOUT "Cleaning node; removing configuration files ...\n";
unlink @CONFIGS;
printf STDOUT "Resetting /etc/hosts file\n";
if (system("$CP -f $TMHOSTS $HOSTSFILE") != 0) {
print STDERR "Could not copy default /etc/hosts file into place: $!\n";
exit(1);
}
printf STDOUT "Resetting passwd and group files\n";
if (system("$CP -f $TMGROUP /etc/group") != 0) {
print STDERR "Could not copy default group file into place: $!\n";
exit(1);
}
if (system("$CP -f $TMPASSWD /etc/master.passwd_testbed") != 0) {
print STDERR "Could not copy default passwd file into place: $!\n";
exit(1);
}
if (system("$MKDB /etc/master.passwd_testbed") != 0) {
print STDERR "Failure running pwd_mkdb on default password file: $!\n";
exit(1);
}
}
dostartupcmd();
exit(0);
#!/usr/bin/perl -wT
use English;
#
# Initialize at boot time.
#
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 $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 $DELTACMD = "deltas";
my $STARTSTATCMD= "startstatus";
my $READYCMD = "ready";
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";
my $CHPASS = "/usr/bin/chpass";
my $DELTAINSTALL= "/usr/local/bin/install-delta";
my $IFACE = "fxp";
my $CTLIFACENUM = "4";
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";
my $kernel = "/kernel.100HZ";
#
# This is a debugging thing for my home network.
#
my $NODE = "MYIP=155.101.132.101";
$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 1;
}