Commit 407cd1ac authored by Leigh B. Stoller's avatar Leigh B. Stoller

A set of change for exporting project and user directories only to

machines in the experiment. exports_setup runs on paper and queries
the DB, generating a set of export lines. That is sent over to
plastic, and piped into exports_setup.proxy, which generates a new
/etc/exports file and restarts mountd. All of the client setup scripts
have been changed to mount the project and user directories.
parent b60f9b65
......@@ -967,7 +967,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/ns2ir/parse.tcl tbsetup/ns2ir/tb_compat.tcl \
tbsetup/savevlans tbsetup/ir/extract_tb \
tbsetup/tbprerun tbsetup/tbrun tbsetup/tbend tbsetup/tbreport \
tbsetup/named_setup \
tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
......
......@@ -126,7 +126,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/ns2ir/parse.tcl tbsetup/ns2ir/tb_compat.tcl \
tbsetup/savevlans tbsetup/ir/extract_tb \
tbsetup/tbprerun tbsetup/tbrun tbsetup/tbend tbsetup/tbreport \
tbsetup/named_setup \
tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
......
......@@ -5,14 +5,15 @@ use English;
#
# Configure variables
#
my $TB = "@prefix@/libexec";
my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@";
my $dbh = Mysql->connect("localhost",$DBNAME,"script","none");
if ($#ARGV < 1) {die("Usage: nalloc <pid> <eid> <node> <node> <...>\n");}
my $consetup="$TB/console_setup";
my $consetup="$TB/libexec/console_setup";
my $exportsetup="$TB/sbin/exports_setup";
my $error = 0;
my $pid = shift;
my $eid = shift;
......@@ -111,6 +112,9 @@ if (!$error && @nodes) {
}
system("$consetup @conlist") == 0 or
print STDERR "WARNING: $consetup @conlist failed!\n";
system("$exportsetup") == 0 or
print STDERR "WARNING: $exportsetup failed!\n";
}
exit($error);
......@@ -17,6 +17,7 @@ if ($#ARGV < 1) {
my $error = 0;
my $consetup="$TB/libexec/console_setup";
my $exportsetup="$TB/sbin/exports_setup";
my $osload="$TB/bin/os_load";
my $reloadpid="testbed";
my $reloadeid="reloading";
......@@ -230,5 +231,10 @@ if (@freed_nodes) {
print STDERR "WARNING: $consetup @conlist failed!\n";
}
if (@freed_nodes || @reloaded) {
system("$exportsetup") == 0 or
print STDERR "WARNING: $exportsetup failed!\n";
}
exit($error);
......@@ -13,8 +13,10 @@ SUBDIRS = checkpass ir ns2ir
BIN_STUFF = power snmpit tbend tbrun tbprerun tbreport \
os_load savevlans startexp endexp batchexp killbatchexp
CONTROL_BIN = power snmpit os_load
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon
batch_daemon exports_setup
LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \
os_setup mkexpdir console_setup \
......@@ -71,6 +73,8 @@ post-install:
chmod u+s $(INSTALL_LIBEXECDIR)/os_setup
chown root $(INSTALL_SBINDIR)/named_setup
chmod u+s $(INSTALL_SBINDIR)/named_setup
chown root $(INSTALL_SBINDIR)/exports_setup
chmod u+s $(INSTALL_SBINDIR)/exports_setup
chown root $(INSTALL_BINDIR)/os_load
chmod u+s $(INSTALL_BINDIR)/os_load
chown root $(INSTALL_BINDIR)/savevlans
......@@ -83,7 +87,8 @@ post-install:
#
# Control node installation (okay, plastic)
#
control-install: $(addprefix $(INSTALL_SBINDIR)/, console_setup.proxy)
control-install: $(addprefix $(INSTALL_SBINDIR)/, console_setup.proxy) \
$(addprefix $(INSTALL_SBINDIR)/, exports_setup.proxy)
cd $(INSTALL_BINDIR) && \
list='$(BIN_STUFF)'; for file in $$list; do \
rm -f $$file; \
......
#!/usr/bin/perl -wT
use English;
use Fcntl ':flock';
#
# Create an /etc/exports.tail file based on current reserved table and project
# members. Fire that tail over to the fileserver where it is concatenated with
# the head file to become the new /etc/exports
#
# usage: exports_setup
#
#
# Configure variables
#
my $TB = "@prefix@";
my $DBNAME = "@TBDBNAME@";
my $TBOPS = "@TBOPSEMAIL@";
# Note no -n option. We redirect stdin from the new exports file below.
my $SSH = "sshtb -q -l root fs.emulab.net";
my $PROG = "/usr/testbed/sbin/exports_setup.proxy";
my $exportstail = "/var/tmp/exports.tail";
my $lockfile = "/var/tmp/testbed_exports_lockfile";
my $projdir = "/proj";
my $usersdir = "/users";
my $dbg = 0;
my @row;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("Must be root! Maybe its a development version?");
}
# XXX Hacky!
#if ($TB ne "/usr/testbed") {
# die("Wrong version. Maybe its a development version?");
#}
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output
#
# Set up for querying the database.
#
use Mysql;
my $DB = Mysql->connect("localhost", $DBNAME, "script", "none");
#
# This script always does the right thing, so it does not matter who
# calls it.
#
#
# We need to serialize this script to avoid a trashed map file. Use
# a dummy file in /var/tmp, opened for writing and flock'ed.
#
open(LOCK, ">>$lockfile") || fatal("Couldn't open $lockfile\n");
$count = 0;
while (flock(LOCK, LOCK_EX|LOCK_NB) == 0) {
print "Another /etc/exports update in progress. Waiting a moment ...\n";
if ($count++ > 20) {
fatal("Could not get the lock after a long time!\n");
}
sleep(1);
}
#
# We stick the new map entries into the tail file. First zero it out.
#
open(MAP, ">$exportstail") || fatal("Couldn't open $exportstail\n");
print MAP "\n";
print MAP "#\n";
print MAP "# DO NOT EDIT below this point. Auto generated entries!\n";
print MAP "#\n";
print MAP "\n";
#
# We export to particular nodes, based on the experiment that is allocated
# to the node. Since we want the exports file to be based on IP numbers,
# we need this crazy join to find out the type of the node, so we can find
# the control network card number, so we can find the IP address for that
# card.
#
$db_result =
DBquery("select reserved.node_id,reserved.pid,interfaces.IP ".
"from reserved ".
"left join nodes on reserved.node_id=nodes.node_id ".
"left join node_types on node_types.type=nodes.type ".
"left join interfaces on reserved.node_id=interfaces.node_id and ".
"interfaces.card=node_types.control_net ".
"where interfaces.IP!='NULL' order by reserved.pid,interfaces.IP");
#
# Generate a per project directory line, listing all of the nodes for
# that project. We could do it one per line, but too messy.
#
if ($db_result->numrows > 0) {
my $lastpid = 0;
my @hostlist = ();
print MAP "#\n";
print MAP "# Export Project directories\n";
print MAP "#\n";
while (@row = $db_result->fetchrow_array) {
my $node_id = $row[0];
my $pid = $row[1];
my $ip = $row[2];
if (!$lastpid) {
$lastpid = $pid;
push(@hostlist, $ip);
next;
}
if ($pid ne $lastpid) {
print MAP "$projdir/$lastpid -maproot=root @hostlist\n";
@hostlist = ();
$lastpid = $pid;
}
push(@hostlist, $ip);
}
print MAP "$projdir/$lastpid -maproot=root @hostlist\n";
}
#
# Now we need the users list for exporting from /users. We need to export
# all of the project members to all of the machines in that projects
# experiments. Also, since we again want the IPs, we need all of that crazy
# join again. Silly!
#
$db_result =
DBquery("select proj_memb.uid,interfaces.IP from reserved ".
"left join proj_memb on proj_memb.pid=reserved.pid ".
"left join nodes on reserved.node_id=nodes.node_id ".
"left join node_types on node_types.type=nodes.type ".
"left join interfaces on reserved.node_id=interfaces.node_id ".
"and interfaces.card=node_types.control_net ".
"where interfaces.IP!='NULL' and proj_memb.trust!='none' ".
"order by proj_memb.uid");
#
# Generate a per user directory line, listing all of the nodes for
# that user. We could do it one per line, but too messy.
#
if ($db_result->numrows > 0) {
my $lastuid = 0;
my @hostlist = ();
print MAP "#\n";
print MAP "# Export User directories\n";
print MAP "#\n";
while (@row = $db_result->fetchrow_array) {
my $uid = $row[0];
my $ip = $row[1];
if (!$lastuid) {
$lastuid = $uid;
push(@hostlist, $ip);
next;
}
if ($uid ne $lastuid) {
print MAP "$usersdir/$lastuid -maproot=root @hostlist\n";
@hostlist = ();
$lastuid = $uid;
}
push(@hostlist, $ip);
}
print MAP "$usersdir/$lastuid -maproot=root @hostlist\n";
}
print MAP "\n";
close(MAP);
#
# Fire the new tail file over to the fileserver to finish. We cat the file
# right into it.
#
$UID = 0;
system("$SSH $PROG < $exportstail") == 0 or
fatal("Failed: $SSH $PROG < $exportstail: $?");
unlink("$exportstail");
#
# Close the lock file. Exiting releases it, but might as well.
#
close(LOCK);
exit(0);
sub fatal {
local($msg) = $_[0];
system("echo \"$msg\" | /usr/bin/mail ".
"-s 'TESTBED: Named Setup Failed' $TBOPS");
die($msg);
}
sub DBquery($)
{
my($query) = $_[0];
my($result);
$result = $DB->query($query);
if (! $result) {
print "DB Query failed: $query\n";
}
return $result;
}
#!/usr/bin/perl -wT
use English;
use Fcntl ':flock';
#
# Create and /etc/exports file based on current reserved table and project
# members.
#
# usage: exports_setup
#
#
# Configure variables
#
my $TBOPS = "testbed-ops\@fast.cs.utah.edu";
my $etcdir = "/etc";
my $exports = "$etcdir/exports";
my $exportsnew = "$etcdir/exports.new";
my $exportsback = "$etcdir/exports.backup";
my $exportshead = "$etcdir/exports.head";
my $exportstail = "$etcdir/exports.tail";
my $dbg = 0;
my @row;
#
# We don't want to run this script unless its the real version.
#
if ($UID != 0) {
die("Must be root!");
}
# un-taint path
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output
#
# Take our input and write it to the tail file.
#
open(TAIL, ">$exportstail") || fatal("Couldn't open $exportstail\n");
while (<STDIN>) {
print TAIL $_;
}
close(TAIL);
chmod(0444, $exportstail);
#
# Generate a warning so that no one tries to edit the file by hand
#
open(MAP, ">$exportsnew") || fatal("Couldn't open $exportsnew\n");
print MAP
"#\n".
"# ******************************************************************\n".
"# DO NOT EDIT THIS FILE. IT IS A CREATION, A FIGMENT, A CONTRIVANCE!\n".
"#\n".
"# Edit $exportshead, then run exports_setup on paper.\n".
"# ******************************************************************\n".
"#\n";
close(MAP);
chmod(0644, $exportsnew);
#
# Now tack on the head part of the file.
#
system("cat $exportshead >> $exportsnew") == 0 or
fatal("Failed to concat $exportshead to $exportsnew\n");
#
# Now the tail of the file.
#
system("cat $exportstail >> $exportsnew") == 0 or
fatal("Failed to concat $exportstail to $exportsnew\n");
#
# Back up the existing exports, and then mv in the new one.
#
system("cp $exports $exportsback") == 0 or
fatal("Could not back up $exports to $exportsback\n");
system("mv $exportsnew $exports") == 0 or
fatal("Could not mv $exportsnew to $exports\n");
# Avoid accidental editing.
chmod(0444, $exports);
#
# I have little faith in HUPing mountd. Kill it and restart.
#
$mpid = `cat /var/run/mountd.pid`;
$mpid =~ s/\n//;
# untaint
if ($mpid =~ /^([-\@\w.]+)$/) {
$mpid = $1;
}
kill('TERM', $mpid) or
die("Could not kill(TERM) process $mpid (mountd): $!");
# Allow time to react before starting it again.
select(undef, undef, undef, 0.5);
system("mountd") == 0 or
fatal("Failed to restart mountd! $!\n");
exit(0);
sub fatal {
local($msg) = $_[0];
system("echo \"$msg\" | /usr/bin/mail ".
"-s 'TESTBED: Named Setup Failed' $TBOPS");
die($msg);
}
#!/usr/bin/perl -wT
use English;
use Fcntl ':flock';
#
# Create and /etc/exports file based on current reserved table and project
# members.
#
# usage: exports_setup
#
#
# Configure variables
#
my $TBOPS = "testbed-ops\@fast.cs.utah.edu";
my $etcdir = "/etc";
my $exports = "$etcdir/exports";
my $exportsnew = "$etcdir/exports.new";
my $exportsback = "$etcdir/exports.backup";
my $exportshead = "$etcdir/exports.head";
my $exportstail = "$etcdir/exports.tail";
my $dbg = 0;
my @row;
#
# We don't want to run this script unless its the real version.
#
if ($UID != 0) {
die("Must be root!");
}
# un-taint path
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$| = 1; #Turn off line buffering on output
#
# Take our input and write it to the tail file.
#
open(TAIL, ">$exportstail") || fatal("Couldn't open $exportstail\n");
while (<STDIN>) {
print TAIL $_;
}
close(TAIL);
chmod(0444, $exportstail);
#
# Generate a warning so that no one tries to edit the file by hand
#
open(MAP, ">$exportsnew") || fatal("Couldn't open $exportsnew\n");
print MAP
"#\n".
"# ******************************************************************\n".
"# DO NOT EDIT THIS FILE. IT IS A CREATION, A FIGMENT, A CONTRIVANCE!\n".
"#\n".
"# Edit $exportshead, then run exports_setup on paper.\n".
"# ******************************************************************\n".
"#\n";
close(MAP);
chmod(0644, $exportsnew);
#
# Now tack on the head part of the file.
#
system("cat $exportshead >> $exportsnew") == 0 or
fatal("Failed to concat $exportshead to $exportsnew\n");
#
# Now the tail of the file.
#
system("cat $exportstail >> $exportsnew") == 0 or
fatal("Failed to concat $exportstail to $exportsnew\n");
#
# Back up the existing exports, and then mv in the new one.
#
system("cp $exports $exportsback") == 0 or
fatal("Could not back up $exports to $exportsback\n");
system("mv $exportsnew $exports") == 0 or
fatal("Could not mv $exportsnew to $exports\n");
# Avoid accidental editing.
chmod(0444, $exports);
#
# I have little faith in HUPing mountd. Kill it and restart.
#
$mpid = `cat /var/run/mountd.pid`;
$mpid =~ s/\n//;
# untaint
if ($mpid =~ /^([-\@\w.]+)$/) {
$mpid = $1;
}
kill('TERM', $mpid) or
die("Could not kill(TERM) process $mpid (mountd): $!");
# Allow time to react before starting it again.
select(undef, undef, undef, 0.5);
system("mountd") == 0 or
fatal("Failed to restart mountd! $!\n");
exit(0);
sub fatal {
local($msg) = $_[0];
system("echo \"$msg\" | /usr/bin/mail ".
"-s 'TESTBED: Named Setup Failed' $TBOPS");
die($msg);
}
......@@ -61,6 +61,12 @@ if (&tbs_exec("savevlans")) {
&tbs_out("WARNING: Failed to back up VLAN configuration\n");
}
&tbs_out("Setting up mountpoints\n");
if (&tbs_exec("exports_setup")) {
&tbs_out("Failed to setup mountpoints.\n");
exit(1);
}
&tbs_out("Resetting OS and rebooting.\n");
if (&tbs_exec("os_setup $pid $eid $irfile")) {
&tbs_out("Failed to reset OS and reboot nodes.\n");
......
......@@ -39,7 +39,9 @@ my $project = "";
my $eid = "";
my $vname = "";
my $PROJDIR = "/proj";
my $MOUNTCMD = "/sbin/mount fs.emulab.net:/q/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";
......@@ -113,7 +115,7 @@ if (! -e "$PROJDIR/$project") {
}
}
if (system("$MOUNTCMD/$project $PROJDIR/$project") != 0) {
if (system(sprintf($PROJMOUNTCMD, $project, $project)) != 0) {
print STDERR "Could not mount project directory on $PROJDIR/$project.\n";
}
......@@ -329,6 +331,21 @@ while (<TM>) {
}
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) {
......@@ -347,7 +364,7 @@ while (<TM>) {
}
if (system("$PW useradd $login -u $uid -g $gid $GLIST ".
"-d /users/$login -s /bin/tcsh -c \"$name\"") != 0) {
"-d $USERDIR/$login -s /bin/tcsh -c \"$name\"") != 0) {
print STDERR "Error adding new user $login\n";
next;
}
......
......@@ -2,4 +2,4 @@
# When the release is bumped, be sure to remove sup/sup/FBSD40-STD/checkouts
# on the client.
#
FBSD40-STD host=boss.emulab.net base=/etc/testbed/sup prefix=/ preserve release=20010325
FBSD40-STD host=boss.emulab.net base=/etc/testbed/sup prefix=/ preserve release=20010329
......@@ -38,7 +38,9 @@ my $project = "";
my $eid = "";
my $vname = "";
my $PROJDIR = "/proj";
my $MOUNTCMD = "/bin/mount fs.emulab.net:/q/proj/";
my $USERDIR = "/users";
my $PROJMOUNTCMD= "/bin/mount fs.emulab.net:/q/$PROJDIR/%s $PROJDIR/%s";
my $USERMOUNTCMD= "/bin/mount fs.emulab.net:$USERDIR/%s $USERDIR/%s";
my $HOSTNAME = "%s\t%s-%s %s\n";
#
......@@ -111,7 +113,7 @@ if (! -e "$PROJDIR/$project") {
}
}
if (system("$MOUNTCMD/$project $PROJDIR/$project") != 0) {
if (system(sprintf($PROJMOUNTCMD, $project, $project)) != 0) {
print STDERR "Could not mount project directory on $PROJDIR/$project.\n";
}
......@@ -202,6 +204,21 @@ while (<TM>) {
}
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 -q ' $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) {
......@@ -220,7 +237,8 @@ while (<TM>) {
}
if (system("$USERADD -u $uid -g $gid -p $pswd $GLIST ".
"-d /users/$login -s /bin/tcsh -c \"$name\" $login") != 0) {
"-d $USERDIR/$login -s /bin/tcsh -c \"$name\" $login")
!= 0) {
print STDERR "Error adding new user $login\n";
next;
}
......
......@@ -2,4 +2,4 @@
# When the release is bumped, be sure to remove sup/sup/RHL62-STD/checkouts
# on the client.
#
RHL62-STD host=boss.emulab.net base=/etc/rc.d/testbed/sup prefix=/ preserve release=20010325
RHL62-STD host=boss.emulab.net base=/etc/rc.d/testbed/sup prefix=/ preserve release=20010329
......@@ -35,7 +35,9 @@ my $project = "";
my $eid = "";
my $vname = "";
my $PROJDIR = "/proj";
my $MOUNTCMD = "/sbin/mount fs.emulab.net:/q/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";
#
......@@ -108,7 +110,7 @@ if (! -e "$PROJDIR/$project") {
}
}
if (system("$MOUNTCMD/$project $PROJDIR/$project") != 0) {
if (system(sprintf($PROJMOUNTCMD, $project, $project)) != 0) {
print STDERR "Could not mount project directory on $PROJDIR/$project.\n";
}
......@@ -205,6 +207,21 @@ while (<TM>) {
}
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 -q ' $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) {
......@@ -223,7 +240,7 @@ while (<TM>) {
# Do not give the -d argument. Breaks on netbsd, leaving the field
# empty in the password file. Instead, I changed /etc/usermgmt.conf
# on all the nodes so that home dirs default to /users, and that
# seems to work okay
# seems to work okay.
#
if (system("$USERADD -u $uid -g $gid -p $pswd $GLIST ".
"-s /bin/tcsh -c \"$name\" $login") != 0) {
......
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