diff --git a/cdrom/waboot/emulabboot.sh b/cdrom/waboot/emulabboot.sh index 289e0f79e0d76d67880c16baff0ec43f09cac027..f8999446e5e3b6b47c825f0ff5be6da2740a6b44 100755 --- a/cdrom/waboot/emulabboot.sh +++ b/cdrom/waboot/emulabboot.sh @@ -19,7 +19,7 @@ # case "$1" in start) - if [ -f /usr/site/sbin/tbbootconfig ]; then + if [ -x /usr/site/sbin/tbbootconfig ]; then /usr/site/sbin/tbbootconfig -c 1 $netbed_disk case $? in diff --git a/cdrom/waboot/rc.emulab b/cdrom/waboot/rc.emulab index dca51b54285623ffcfd42385483b6bd70dd80a8b..bce3ddd9e359d2bb910b822ca0102430dc8d2759 100755 --- a/cdrom/waboot/rc.emulab +++ b/cdrom/waboot/rc.emulab @@ -28,8 +28,9 @@ EmulabCheckIPConfig() case $? in 0) ;; - -277) + 13) echo 'Installation aborted' + echo 'Remove the CD and reboot' exit 1 ;; *) diff --git a/cdrom/waboot/register.pl b/cdrom/waboot/register.pl index 53dfbc1f328e80ef612cad619a9069f57ce830ec..3b7f3886bbb60c1a303f3c8979d05d0733eeaed0 100755 --- a/cdrom/waboot/register.pl +++ b/cdrom/waboot/register.pl @@ -19,7 +19,7 @@ use Socket; # sub usage() { - print("Usage: register.pl <bootdisk>\n"); + print("Usage: register.pl <bootdisk> <ipaddr>\n"); exit(-1); } my $optlist = ""; @@ -108,10 +108,11 @@ my %weberrors = if (! getopts($optlist, \%options)) { usage(); } -if (@ARGV != 1) { +if (@ARGV != 2) { usage(); } my $rawbootdisk = $ARGV[0]; +my $IP = $ARGV[1]; # # Untaint the arguments. @@ -122,6 +123,12 @@ if ($rawbootdisk =~ /^([\w\/]+)$/) { else { fatal("Tainted argument $rawbootdisk!"); } +if ($IP =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/) { + $IP = $1; +} +else { + fatal("Tainted argument $IP!"); +} # # See if we want to continue. Useful for debugging. @@ -144,27 +151,6 @@ my $blockdevice = $rawdevice; # $fromscratch = mysystem("$tbboot -v $rawbootdisk"); -# -# We need our IP. -# -my $hostname = `hostname`; -if (!defined($hostname)) { - fatal("No hostname!"); -} -# Untaint and strip newline. -if ($hostname =~ /^([-\w\.]+)$/) { - $hostname = $1; -} -else { - fatal("Tainted argument $hostname!\n"); -} - -my (undef,undef,undef,undef,@ipaddrs) = gethostbyname($hostname); -if (!defined(@ipaddrs)) { - fatal("Could not map $hostname to IP address!"); -} -my $IP = inet_ntoa($ipaddrs[0]); - GetInstructions(); # @@ -313,6 +299,23 @@ for ($i = 1; $i <= 4; $i++) { # If told to load a local image from the CDROM, its really easy! # if (! ($image =~ /^http:.*$/ || $image =~ /^ftp:.*$/)) { + # + # First, check the hash if provided. + # + if (defined($hash)) { + print "Checking MD5 hash of the CDROM image.\n"; + print $PATIENCEMSG; + + my $hval = `md5 -q /$image`; + chomp($hval); + + fatal("CDROM image has invalid hash!") + if ($hash ne $hval); + } + + # + # Then load up the disk straight from the CDROM. + # print "Loading image for slice $i from $image.\n"; print $PATIENCEMSG; @@ -509,8 +512,8 @@ sub GetInstructions() } else { while (!defined($privkey)) { - $privkey = Prompt("Please enter your 16 character CD password", - undef); + $privkey = Prompt("Please enter your 16 character CD password". + " (no spaces)", undef); } } @@ -899,15 +902,7 @@ sub WriteConfigBlock() { my $cmd; - # XXX for now hack, tbbootconfig doesn't know about 'bootdisk' - if (1) { - mysystem("grep -v bootdisk $softconfig > /tmp/softcfg"); - fatal("Could not prepare $softconfig for writing!") - if ($?); - $cmd = "$tbboot -f -d -w /tmp/softcfg -k 1 -c 0 "; - } else { - $cmd = "$tbboot -f -d -w $softconfig -k 1 -c 0 "; - } + $cmd = "$tbboot -f -d -w $softconfig -k 1 -c 0 "; if (defined($config{privkey})) { $cmd .= "-e $config{privkey} "; diff --git a/cdrom/waboot/register.sh b/cdrom/waboot/register.sh index 85c96e109f64fbc90a4e3905096cfbf02426eb51..2e5fba355af671522f06d52ba000dda5f8ef0f4a 100755 --- a/cdrom/waboot/register.sh +++ b/cdrom/waboot/register.sh @@ -17,7 +17,7 @@ case "$1" in start) if [ -f /usr/site/sbin/register.pl ]; then - /usr/site/sbin/register.pl $netbed_disk + /usr/site/sbin/register.pl $netbed_disk $netbed_IP exit $? fi ;; diff --git a/cdrom/waboot/waipconfig.pl b/cdrom/waboot/waipconfig.pl index 056bbfbb73d48a963d3bdafff7a2591f1a54fb2b..ce2703af86e275807c405850411c0713e3bdd387 100755 --- a/cdrom/waboot/waipconfig.pl +++ b/cdrom/waboot/waipconfig.pl @@ -13,6 +13,24 @@ use Getopt::Std; use Fcntl; use IO::Handle; +# +# Disk related parameters +# + +# where to find kernel config output +my $dmesgcmd = "/sbin/dmesg"; +my $dmesgfile = "/var/run/dmesg.boot"; + +# preferred ordering of disks to use +my @preferred = ("ar", "aacd", "amrd", "mlxd", "twed", "ad", "da"); + +# ordered list of disks found and hash of sizes +my @disklist; +my %disksize; + +# min disk size we can use (in MB) +my $MINDISKSIZE = 8000; + # # Boot configuration for the CDROM. Determine the IP configuration, either # from the floopy or from the user interactively. @@ -196,7 +214,7 @@ sub GetNewConfig() print "\n"; if (Prompt("Continue with installation?", "No") =~ /no/i) { - exit(-277); + exit(13); } # @@ -231,8 +249,8 @@ sub GetUserConfig() $config{'domain'} = Prompt("Domain", $config{'domain'}); $config{'IP'} = Prompt("IP Address", $config{'IP'}); $config{'netmask'} = Prompt("Netmask", WhichNetMask()); + $config{'gateway'} = Prompt("Gateway IP", WhichGateway()); $config{'nameserver'}= Prompt("Nameserver IP", $config{'nameserver'}); - $config{'gateway'} = Prompt("Gateway IP", $config{'gateway'}); # XXX $rawbootdisk = $config{'bootdisk'}; @@ -326,12 +344,11 @@ sub WhichInterface() } } - return "fxp0"; + return undef; } # -# Which network mask. Make the standard class C guess and let the caller -# spit that out in a prompt for verification. +# Which network mask. Default based on the network number. # sub WhichNetMask() { @@ -340,9 +357,47 @@ sub WhichNetMask() return $config{'netmask'}; } + # + # XXX this is a nice idea, but will likely be wrong for large + # institutions that subdivide class B's (e.g., us!) + # + if (0 && defined($config{'IP'})) { + my ($net) = split(/\./, $config{'IP'}); + return "255.0.0.0" if $net < 128; + return "255.255.0.0" if $net < 192; + } + return "255.255.255.0"; } +# +# Which gateway IP. Use the more or less traditional .1 for the network +# indicated by (IP & netmask). +# +sub WhichGateway() +{ + # XXX + if (defined($config{'gateway'})) { + return $config{'gateway'}; + } + + # + # Grab IP and netmask, combine em, stick 1 in the low quad, + # make sure the result isn't the IP, and return that. + # Parsing tricks from the IPv4Addr package. + # + if (defined($config{'IP'}) && defined($config{'netmask'})) { + my $addr = unpack("N", pack("CCCC", split(/\./, $config{'IP'}))); + my $mask = unpack("N", pack("CCCC", split(/\./, $config{'netmask'}))); + my $gw = ($addr & $mask) | 1; + if ($gw != $addr) { + return join(".", unpack("CCCC", pack("N", $gw))); + } + } + + return undef; +} + # # Which raw disk. Prompt if we cannot come up with a good guess. # Note: raw and block devices are one in the same now. @@ -350,41 +405,40 @@ sub WhichNetMask() sub WhichRawDisk() { # - # Search the drives until we find a valid header. - # Order is: IDE, SCSI, IDE RAID, SCSI RAID + # Find the list of configured disks + # + my @list = DiskList(); + + # + # Search the drives looking for one with a valid header. # - foreach my $disk ("ad", "da", "ar", "aacd") { - foreach my $drive (0) { - my $guess = "/dev/${disk}${drive}"; + foreach my $disk (@list) { + my $guess = "/dev/${disk}"; - system("$tbboot -v $guess"); - if (! $?) { - # - # Allow for overiding the guess, with short timeout. - # - $rawbootdisk = - Prompt("Which Disk Device is the boot device?", - "$guess", 10); - goto gotone; - } + system("$tbboot -v $guess"); + if (! $?) { + # + # Allow for overiding the guess, with short timeout. + # + $rawbootdisk = Prompt("Which Disk Device is the boot device?", + "$guess", 10); + goto gotone; } } # - # Okay, no candidates. Lets find the first real disk. Use dd - # to see if the drive is configured. + # None with configuration info, just use the first existing disk + # which is large enough and is actually accessible. # - foreach my $disk ("ad0", "da0", "ar0", "aacd0") { + foreach my $disk (@list) { my $guess = "/dev/${disk}"; - system("dd if=$guess of=/dev/null bs=512 count=32 >/dev/null 2>&1"); - if (! $?) { + if (DiskSize($disk) >= $MINDISKSIZE && DiskReadable($disk)) { # # Allow for overiding the guess, with short timeout. # - $rawbootdisk = - Prompt("Which Disk Device is the boot device?", - "$guess", 10); + $rawbootdisk = Prompt("Which Disk Device is the boot device?", + "$guess", 10); goto gotone; } } @@ -394,12 +448,78 @@ sub WhichRawDisk() # If still not defined, then loop forever. # while (!defined($rawbootdisk) || ! -e $rawbootdisk) { - $rawbootdisk = - Prompt("Which Disk Device is the boot device?", $defrawdisk); + $rawbootdisk = Prompt("Which Disk Device is the boot device?", + $defrawdisk); } return $rawbootdisk; } +# +# Create a list of all disks and their sizes. +# +sub DiskList() +{ + if (-x $dmesgcmd) { + GetDisks($dmesgcmd); + } + + # if we didn't grab anything there, try the /var/run file + if (@disklist == 0 && -r $dmesgfile) { + GetDisks("cat $dmesgfile"); + } + + return @disklist; +} + +sub DiskSize($) +{ + my ($name) = @_; + + if (defined($disksize{$name})) { + return $disksize{$name}; + } + return 0; +} + +sub DiskReadable($) +{ + my ($disk) = @_; + my $dev = "/dev/$disk"; + + if (!system("dd if=$dev of=/dev/null bs=512 count=32 >/dev/null 2>&1")) { + return(1); + } + return(0); +} + +sub GetDisks($) +{ + my ($cmd) = @_; + my @units = (0, 1, 2, 3); + my @cmdout = `$cmd`; + + # + # Arbitrary: we prefer disk type over unit number; + # e.g. ad1 is better than da0. + # + foreach my $disk (@preferred) { + foreach my $unit (@units) { + my $dmesgpat = "^($disk$unit):.* (\\d+)MB.*\$"; + foreach my $line (@cmdout) { + if ($line =~ /$dmesgpat/) { + my $name = $1; + my $size = $2; + if (!defined($disksize{$name})) { + push(@disklist, $name); + } + $disksize{$name} = $size; + } + } + } + } +} + + # # Write a config file suitable for input to the testbed boot header program. #