rc.firstboot 7.98 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
#!/bin/bash
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
# rc.firstboot - CygWin-specific startup.  

# Run by EmulabStartup before rc.bootsetup on CygWin.  Since Windows needs a
# reboot to change some network settings (including the host name), do this
# first and force the reboot.  It was separated out from rc.cygwinxp, which is
# run by rc.bootsetup, because of a race condition on the required reboot: if
# the rc.cygwin child process is killed before rc.bootsetup, rc.bootsetup may
# get a chance to report TBFAILED to Emulab, killing off the whole swap-in.

PATH=/usr/local/etc/emulab:/bin:$SYSTEMROOT/system32:$PATH
export PATH

# Enable logging.
logfile=/var/log/EmulabStartup.log
chmod -f g+w $logfile
function logit () {
    msg="`date`: $1"
    echo "$msg" >> $logfile
    echo "$msg"
}

Russ Fish's avatar
Russ Fish committed
28 29
logit "----------------------------------------------------------------"
logit "Entering rc.firstboot $*"
30

31 32 33 34 35 36 37 38
# Enable WINDOWS() in libsetup.pm .
iscygwin=/etc/emulab/iscygwin
chmod -f g+w /etc/emulab
chmod -f g+w $iscygwin
uname -r > $iscygwin
chmod g+w $iscygwin
chmod -f g-w /etc/emulab

39 40 41 42
# If 'prepare' wasn't executed before pulling an image, tmcc will be confused
# by the cached info from tmcd.  Clean up like bootsetup()/tmccclrconfig().
rm -rf /var/emulab/boot/tmcc

Russ Fish's avatar
Russ Fish committed
43 44 45 46 47
# Capture the hostname early on, for use later.  This avoids confusion in the
# case where we are going to the same node as the image was saved from.
hostname=`/bin/hostname`

# Special case while running "rc.firstboot -mini" from Cmdlines.txt under
48
# Mini-Setup after Sysprep.
Russ Fish's avatar
Russ Fish committed
49
if [ "$#" == 1 ] && [ "$1" == "-mini" ]; then
50
    mini=1
51

52
    # Record the network interface state.
Russ Fish's avatar
Russ Fish committed
53 54
    logit "================  Mini-Setup network state"
    logit "id "`id`
55 56 57 58
    ipconfig /all >> $logfile
    getmac >> $logfile
    ipconfig /all
    getmac
Russ Fish's avatar
Russ Fish committed
59
    logit "================"
60

61 62 63 64 65 66 67 68 69 70 71 72
    # The network is set up but not running yet, so we can't contact tmcc to
    # find out the host name.
    # 
    # While running "prepare", before doing Sysprep we cached a static mapping
    # of node names and the MAC addresses of their interfaces.  We can use it
    # to set the host name, so that when XP is booted for the first time,
    # rc.firstboot will find that the host name has already been set to the
    # right thing and go on without rebooting.
    # 
    # Worst case, if the majority of the NICs on the node have been moved
    # since the image was made, the static table will be wrong and we'll still
    # have to change the hostname and reboot again.
Russ Fish's avatar
Russ Fish committed
73
    nodeid= intfcmap=/var/emulab/boot/intfcmap 
74
    if [[ -r $intfcmap && -s $intfcmap ]]; then
Russ Fish's avatar
Russ Fish committed
75 76 77 78
        # We're running as SYSTEM under Mini-Setup.  Can't write /var/emulab/boot.
        macs=/tmp/macs

        # Grab the MAC addresses from ipconfig, without dashes and lowercased.
79 80
        ipconfig /all | tr -d '\r' | grep 'Physical Address' |\
            sed -e 's/.*: //' -e 's/-//g' -e 'y/ABCDEF/abcdef/' > $macs
Russ Fish's avatar
Russ Fish committed
81 82

        # NIC's may have been physically moved, take a majority vote.
83
        for intfc in `cat $macs`; do grep $intfc $intfcmap; done | \
Russ Fish's avatar
Russ Fish committed
84 85 86 87 88
            cut -d ' ' -f 1 | uniq -c | sort -rn | tr -s ' ' > $macs.pc

        logit "Mac addresses `cat $macs`"
        logit "Node id votes `cat $macs.pc`"

89 90 91 92 93 94 95
        nodeid=`cut -d ' ' -f 3 $macs.pc | head -1`
        if [ "$nodeid" != "" ]; then
            logit "Node id = $nodeid"
        else
            logit "Didn't get a nodeid."
            exit 1
        fi
96
    fi
97 98 99 100 101 102 103 104 105 106
else
    # Make sure all NIC's are up at the start, so they show up on ipconfig.
    devcon enable =net 'PCI*'

    # Make sure DHCP is enabled on all connected interfaces.  Windows only enables
    # it on the first one to come up.  Otherwise tmcc will fail on the control net
    # interface, and we don't know which one that is yet.
    # 
    # Unused interfaces will be disabled below.  DHCP will be disabled on the
    # experimental net interfaces by "netsh interface ip set address
107
    # ... source=static ..." in BOOTDIR/rc.ifc, which is generated in
108 109 110
    # liblocsetup.pm os_ifconfig_line() $IFCONFIG, invoked by rc.ifconfig .
    ipconfig /all | tr -d '\r' | awk \
        '/^Ethernet adapter/{ ifc = gensub("Ethernet adapter (.*):", "\\1", 1); next }\
111 112 113
         /Dhcp Enabled.*No/{ \
             cmd = sprintf("netsh interface ip set address \"%s\" dhcp", ifc);\
             print cmd; stat = system(cmd);\
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
             printf("Enabled DHCP on %s, status %d.\n", ifc, stat) }'

    # Get the desired node name from tmcc, and make sure we have a connection.
    # There is a swap-in race condition where tmcc nodeid at first returns nothing.
    nodeid=
    while [ -z $nodeid ]; do
        nodeid=`tmcc nodeid`
        if [ -z $nodeid ]; then
            logit "Null nodeid returned from tmcc.  Trying again."
            sleep 5
        elif [ "$nodeid" == UNKNOWN ]; then
            logit "UNKNOWN nodeid returned from tmcc.  Trying again."
            nodeid=
            sleep 5
        fi
    done
    logit "nodeid = $nodeid"
fi
132 133

# NetBT (Netbios over TCP) chatters, messes up slothd, and is not needed for
134 135 136
# SMB, so disable it by default.  This doesn't take effect until TCP/IP is
# restarted, so do it before the computer name change below, which reboots the
# first time.
137
ccs=/HKLM/SYSTEM/CurrentControlSet svcs=$ccs/Services cntl=$ccs/Control
138
nbtp=$svcs/NetBT/Parameters nbtif=$nbtp/Interfaces
139
for ifc in `regtool list $nbtif`; do
140 141 142 143 144 145
    # Set the NetBT interface NetbiosOptions to Disable (2) or Enable (1.)
    if regtool get -q $nbtp/EmulabOn; then able=1; else able=2; fi
    regtool set -i $nbtif/$ifc/NetbiosOptions $able

    # Also turn off outgoing DNS registration traffic.
    regtool set -i $nbtif/$ifc/DisableDynamicUpdate 1
146 147
done

148 149 150 151
# Enable LMHOSTS file lookup on the client side, in case the user runs "netbt"
# to turn NetBT back on again on a server node to share files between nodes.
# rc.lmhosts transforms the /etc/hosts file into a Windows lmhosts file.
regtool set -i $nbtp/EnableLMHOSTS 1
152

153 154 155 156 157 158 159 160 161 162
# Turn on IP forwarding if there is more than one experimental net interface.
# Also requires a reboot to take effect.
tp=$svcs/Tcpip/Parameters
if [ `tmcc ifconfig | wc -l` \> 1 ]; then
    regtool set -i $tp/IPEnableRouter 1
else
    regtool set -i $tp/IPEnableRouter 0
fi
logit "IPEnableRouter set to `regtool get $tp/IPEnableRouter`."

163 164 165 166 167 168 169 170
# I'd rather not have it put MSN and Windows Media Player icons on my desktop...
logit "Clearing the MSN and WMP Desktop shortcuts."
rm -f /cygdrive/c/"Documents and Settings/All Users/Desktop/MSN Explorer.lnk"
rm -f /cygdrive/c/"Documents and Settings/Default User/Desktop"/*.lnk
regtool -s set /HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Run/CleanWMP \
  'DEL "%USERPROFILE%\Desktop\Windows Media Player.lnk"'

# Reset the host name if it hasn't been done yet.  Requires a reboot.
171
host="Host name '$hostname'"
Russ Fish's avatar
Russ Fish committed
172 173
# Sysprep generates a temporary host name, so always do it under -mini.
if [[ $nodeid = $hostname && -z "$mini" ]]; then
174 175
    logit "$host matches nodeid '$nodeid'."
else
Russ Fish's avatar
Russ Fish committed
176
    logit "$host will be reset to nodeid '$nodeid'."
177 178 179 180 181 182 183 184 185 186

    # Mash the hostname in all the places it shows up in the registry.
    regtool set -s $tp/Hostname $nodeid
    regtool set -s $tp/"NV Hostname" $nodeid
    cn=ComputerName NODEID=`echo $nodeid | tr 'a-z' 'A-Z'`
    regtool set -s $cntl/$cn/Active$cn/$cn $NODEID
    regtool set -s $cntl/$cn/$cn/$cn $NODEID
    regtool set -s $svcs/Eventlog/$cn $NODEID

    logit "Rebooting as '$nodeid'/'$NODEID'."
Russ Fish's avatar
Russ Fish committed
187 188 189 190 191 192 193
    if [ -n "$mini" ]; then 
        # Under Mini-Setup/Cmdlines.txt, it's going to reboot as soon as we exit.
        logit "Returning to Mini-Setup/Cmdlines.txt ."
        exit
    else
        /usr/local/etc/emulab/rc/rc.reboot
    fi
194 195
fi

196 197 198 199 200 201 202
# Spawn a script to kill the logonui.exe task periodically.  It is instantly
# restarted by Windows, but is "cleaned out" in the process.  This works
# around the 15-second "sawtooth" pattern that shows up in the load average
# after reboot and can eat most of the CPU.
logit "Starting clean_logonui in the background."
/bin/sh clean_logonui >& /dev/null &

Russ Fish's avatar
Russ Fish committed
203
logit "rc.firstboot finished."