setup 6.58 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#!/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 $TMGROUP     = "/etc/testbed/group";
my $TMPASSWD    = "/etc/testbed/master.passwd";
my @CONFIGS	= ($TMIFC, $TMDELAY);
my $REBOOTCMD   = "reboot";
my $STATCMD     = "status";
my $IFCCMD      = "ifconfig";
my $ACCTCMD     = "accounts";
my $DELAYCMD    = "delay";
my $IFCONFIG    = "/sbin/ifconfig fxp%d inet %s netmask %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 $CTLIFACE    = "fxp4";
my $project     = "";
my $PROJDIR     = "/proj";
my $MOUNTCMD	= "/sbin/mount 155.99.214.74:/q/proj/";

#
# This is a debugging thing for my home network.
# 
my $NODE	= "MYIP=155.99.214.136";
$NODE		= "";

#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# First clean up the node.
#
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: $!";

#
# See if this node is allocated to an experiment.
#
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";
    exit(0);
}
69
if ($_ =~ /ALLOCATED=([-\@\w.]*)\/([-\@\w.]*)/) {
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    print STDOUT "  Allocated: $1/$2!\n";
    $project = $1;
}
else {
    die("Error getting reservation status\n");
}

#
# Mount the project directory.
# 
print STDOUT "Mounting the project directory on $PROJDIR/$project ... \n";

if (! mkdir("$PROJDIR/$project", 0770)) {
    print STDERR "Could not make directory $PROJDIR/$project: $!\n";
}

if (system("$MOUNTCMD/$project $PROJDIR/$project") != 0) {
    print STDERR "Could not mount project directory on $PROJDIR/$project.\n";
}

#
# 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");

#
# Delay node configuration
#
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;
    
#    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;
	
	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++;
    }
    print DEL "echo \"Delay Configuration Complete\"\n";

    close(DEL);
    chmod(0755, "$TMDELAY");
}

#
# 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>) {
193
    if ($_ =~ /^ADDGROUP NAME=([-\@\w.]+) GID=([0-9]+)/) {
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
	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";
222

223 224
	($exists) = getpwuid($uid);
	if ($exists) {
225 226 227 228 229 230 231
	    if ($root) {
		$GLIST = "-G wheel,$gid";
	    }
	    else {
		$GLIST = "-G $gid";
	    }
	    system("$PW usermod $login $GLIST");
232 233 234 235 236
	    next;
	}

	$GLIST = " ";
	if ($root) {
237
	    $GLIST = "-G wheel";
238
	}
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
	if (system("$PW useradd $login -u $uid -g $gid $GLIST ".
	           "-d /users/$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);

#
# 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 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);
    }
}