Commit f2448717 authored by Kirk Webb's avatar Kirk Webb

Changes to Windows 7 client-side.

Updated prepare so that it can find windows tools in c:\windows\system32
and setup the EmulabStartup service (runs Emulab rc scripts) to delay
startup until after most other services are up and running.  Added creation
of load average performance counter to powershell node setup script which
is run during mini-setup.  Moved some files around.  Updated the unattended
setup file to reference the Windows 7 KMS setup key instead of a Utah-owned
key.  Also adjusted path to node setup powershell script and where logging
is done.  Updated the makefile for Win7 to install the powershell setup
script.  Lastly, removed the deprecated rc.firstboot script.
parent 3d6055ff
......@@ -39,6 +39,11 @@ RCDIR = $(SYSETCDIR)/rc.d
INSTALL = /usr/bin/install -c
COMMON = $(SRCDIR)/../common
SYSTEM32 = /cygdrive/c/Windows/System32
WBEM = $(SYSTEM32)/Wbem
SYSPREP = $(SYSTEM32)/sysprep
install client-install: baselinux-install common-install etc-install \
sup-install script-install ##bin-install
@echo "Remember to install the PEM files if necessary"
......@@ -57,8 +62,6 @@ common-install: dir-install
sup-install: dir-install
SYSTEM32 = /cygdrive/c/Windows/System32
WBEM = $(SYSTEM32)/Wbem
bin-install: dir-install
# These are found in the /share/windows directory.
$(INSTALL) -m 755 $(SRCDIR)/WSName.exe $(BINDIR)/WSName.exe
......@@ -94,12 +97,15 @@ script-install: dir-install $(SCRIPTS)
ln -f -s /bin/reboot /sbin/reboot
# Everybody is in the Administrators group already, so sudo is irrelevant.
$(INSTALL) -m 755 $(SRCDIR)/sudo.dummy /bin/sudo
$(INSTALL) -m 755 $(SRCDIR)/rc.firstboot $(BINDIR)/rc/rc.firstboot
#$(INSTALL) -m 755 $(SRCDIR)/rc.firstboot $(BINDIR)/rc/rc.firstboot
$(INSTALL) -m 755 $(SRCDIR)/rc.cygwinseven $(BINDIR)/rc/rc.cygwin
#$(INSTALL) -m 755 $(SRCDIR)/clean_logonui $(BINDIR)/clean_logonui
$(INSTALL) -m 755 $(SRCDIR)/rc.reboot $(BINDIR)/rc/rc.reboot
$(INSTALL) -m 755 $(SRCDIR)/rc.lmhosts $(BINDIR)/rc/rc.lmhosts
$(INSTALL) -m 755 $(SRCDIR)/netbt $(BINDIR)/netbt
$(INSTALL) -m 755 $(SRCDIR)/unattend-x86.xml $(SYSPREP)/unattend.xml
$(INSTALL) -c -m 755 -o Administrators -d $(SPSCRIPTS)
$(INSTALL) -m 755 $(SRCDIR)/setupnode.ps1 $(SPSCRIPTS)/setupnode.ps1
......@@ -15,7 +15,11 @@ require '';
$| = 1;
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/"; import emulabpaths; }
require "/etc/emulab/";
import emulabpaths;
$ENV{'PATH'} .= ":/cygdrive/c/Windows/System32:/cygdrive/c/Windows";
# Load the OS independent support library. It will load the OS dependent
......@@ -215,6 +219,7 @@ if (! $noredef) {
# " '( $firstboot; $bootsetup; $sshrun; $progrun ) >& $bootlog'\"");
system("cygrunsrv -VQ EmulabStartup");
system("sc config EmulabStartup start= delayed-auto");
if ($sysprep) {
# 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.
export PATH
# Enable logging.
chmod -f g+w $logfile
function logit () {
msg="`date`: $1"
echo "$msg" >> $logfile
echo "$msg"
logit "----------------------------------------------------------------"
logit "Entering rc.firstboot $*"
# Enable WINDOWS() in .
chmod -f g+w /etc/emulab
chmod -f g+w $iscygwin
uname -r > $iscygwin
chmod g+w $iscygwin
chmod -f g-w /etc/emulab
# 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
# 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.
# Special case while running "rc.firstboot -mini" from Cmdlines.txt under
# Mini-Setup after Sysprep.
if [ "$#" == 1 ] && [ "$1" == "-mini" ]; then
# Record the network interface state.
logit "================ Mini-Setup network state"
logit "id "`id`
ipconfig /all >> $logfile
getmac >> $logfile
ipconfig /all
logit "================"
# 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.
nodeid= intfcmap=/var/emulab/boot/intfcmap
if [[ -r $intfcmap && -s $intfcmap ]]; then
# We're running as SYSTEM under Mini-Setup. Can't write /var/emulab/boot.
# Grab the MAC addresses from ipconfig, without dashes and lowercased.
ipconfig /all | tr -d '\r' | grep 'Physical Address' |\
sed -e 's/.*: //' -e 's/-//g' -e 'y/ABCDEF/abcdef/' > $macs
# NIC's may have been physically moved, take a majority vote.
for intfc in `cat $macs`; do grep $intfc $intfcmap; done | \
cut -d ' ' -f 1 | uniq -c | sort -rn | tr -s ' ' > $macs.pc
logit "Mac addresses `cat $macs`"
logit "Node id votes `cat $macs.pc`"
nodeid=`cut -d ' ' -f 3 $macs.pc | head -1`
if [ "$nodeid" != "" ]; then
logit "Node id = $nodeid"
logit "Didn't get a nodeid."
exit 1
# 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
# ... source=static ..." in BOOTDIR/rc.ifc, which is generated in
# os_ifconfig_line() $IFCONFIG, invoked by rc.ifconfig .
ipconfig /all | tr -d '\r' | awk \
'/^Ethernet adapter/{ ifc = gensub("Ethernet adapter (.*):", "\\1", 1); next }\
/Dhcp Enabled.*No/{ \
cmd = sprintf("netsh interface ip set address \"%s\" dhcp", ifc);\
print cmd; stat = system(cmd);\
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.
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."
sleep 5
logit "nodeid = $nodeid"
# NetBT (Netbios over TCP) chatters, messes up slothd, and is not needed for
# 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.
ccs=/HKLM/SYSTEM/CurrentControlSet svcs=$ccs/Services cntl=$ccs/Control
nbtp=$svcs/NetBT/Parameters nbtif=$nbtp/Interfaces
for ifc in `regtool list $nbtif`; do
# 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
# 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
# Turn on IP forwarding if there is more than one experimental net interface.
# Also requires a reboot to take effect.
if [ `tmcc ifconfig | wc -l` \> 1 ]; then
regtool set -i $tp/IPEnableRouter 1
regtool set -i $tp/IPEnableRouter 0
logit "IPEnableRouter set to `regtool get $tp/IPEnableRouter`."
# 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.
host="Host name '$hostname'"
# Sysprep generates a temporary host name, so always do it under -mini.
if [[ $nodeid = $hostname && -z "$mini" ]]; then
logit "$host matches nodeid '$nodeid'."
logit "$host will be reset to nodeid '$nodeid'."
# 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'."
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 ."
# 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 &
logit "rc.firstboot finished."
# -*- powershell -*-
# Constants
$TMCCBIN = "C:\Cygwin\usr\local\etc\emulab\tmcc.bin"
$TMCCARGS = "-t","30"
$BINDIR = "C:\Cygwin\usr\local\etc\emulab"
$CYGBINPATH = "C:\Cygwin\bin"
$LOGFILE = "C:\Temp\setnodename.log"
$TMCCBIN = "tmcc.bin"
$TMCCARGS = "-t","30"
$LOGMANBIN = "logman"
$LDCNTRNAME = "ldavg"
$LDLOG = "C:\Cygwin\var\run\ldavg.csv"
$LDMETRIC = "\Processor(_Total)\% Processor Time"
$LOGFILE = "C:\Windows\Temp\setupnode.log"
$CNPATH = "HKLM:\System\CurrentControlSet\Control\ComputerName\ComputerName"
$HNPATH = "HKLM:\System\CurrentControlSet\Services\Tcpip\Parameters"
......@@ -14,8 +20,8 @@ Function log($msg) {
($time + ": " + $msg) | Out-File -append $LOGFILE
# Update the path to include Cygwin's /bin directory (including Cygwin1.dll)
$env:path += ";$CYGBINPATH"
# Update the path
$env:path += ";$BINDIR;$CYGBINPATH"
# XXX: This doesn't work under mini-setup
#$NameObj = Get-WmiObject Win32_ComputerSystem
......@@ -44,4 +50,8 @@ New-ItemProperty -Path $CNPATH -Name ComputerName -PropertyType String`
New-ItemProperty -Path $HNPATH -Name "NV Hostname" -PropertyType String`
-Value $nodeid -Force
# Create the load average performance counter
& $LOGMANBIN create counter $LDCNTRNAME -f csv -o $LDLOG --v -c $LDMETRIC`
-si $LDINTERVAL -ow -max 1 -cnf 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