From 2af0f7897fd5cdf35d6dbb489d130918c5807caa Mon Sep 17 00:00:00 2001 From: Mike Hibler <mike@flux.utah.edu> Date: Mon, 19 Aug 2002 22:43:21 +0000 Subject: [PATCH] Assorted cleanups for version 0.2: emulabboot.sh: make sure tbbootconfig is executable rc.emulab: fix exit code register.sh: pass netbed_IP on to register.pl waipconfig.pl: fix exit code attempt to intuit gateway: (addr & mask) | 1 code to set netmask based on network type, but for now stick with common 255.255.255.0 more exotic code for determining disk (grubs through dmesg output looking for disks, checks sizes to make sure they are big enough) register.pl: use IP address passed in rather than trying to resolve from hostname check hash of on CD image (we may want to disable this, takes a long time) get rid of hack when calling tbbootconfig since it is now fixed --- cdrom/waboot/emulabboot.sh | 2 +- cdrom/waboot/rc.emulab | 3 +- cdrom/waboot/register.pl | 63 ++++++------- cdrom/waboot/register.sh | 2 +- cdrom/waboot/waipconfig.pl | 180 ++++++++++++++++++++++++++++++------- 5 files changed, 183 insertions(+), 67 deletions(-) diff --git a/cdrom/waboot/emulabboot.sh b/cdrom/waboot/emulabboot.sh index 289e0f79e0..f8999446e5 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 dca51b5428..bce3ddd9e3 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 53dfbc1f32..3b7f3886bb 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 85c96e109f..2e5fba355a 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 056bbfbb73..ce2703af86 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. # -- GitLab