Commit 41e88087 authored by Russ Fish's avatar Russ Fish

Add support for hardware-independent image using Sysprep/Mini-Setup.

Also ensure DHCP is enabled on all connected interfaces.  Otherwise tmcc will fail.
parent cc7d19d8
......@@ -167,7 +167,11 @@ Intel PRO/1000 gigabit ether drivers, installed on the pc3000's.
Intel9.1/PRO1000/WS03XP2K -> xpsp2_support_tools_deploy/pro1000
LSI Logic Ultra320 SCSI 2000 drivers, installed on the pc3000's.
symmpi_xp_1.20.18.zip
symmpi_xp_1.20.18 -> xpsp2_support_tools_deploy/symmpi_xp_1.20.18
symmpi_xp_1.20.18.zip - Unsigned, but newer driver.
LSI21320_50700IO_01016100IO_1090200_676995.zip and
symmpi_xp_10902.zip - Older, but signed, driver.
Need to use the unsigned driver with Sysprep/Mini-Setup for
hardware-independent images.
symmpi_xp_10902 -> xpsp2_support_tools_deploy/symmpi
================================================================
......@@ -5,11 +5,39 @@
# All rights reserved.
#
use English;
use Getopt::Std;
require 'ctime.pl';
#
# Prepare the node for cutting a new image. Should be run just prior.
#
sub usage()
{
print("Usage: " . scriptname() . " [-p Rootpwd] [-n] [-s] \n" .
" -p Rootpwd : Root password, for Emulab services redef.\n" .
" If not present, and not -n, will be prompted-for.\n" .
" -s : Make a hardware-independent image using Sysprep.\n" .
" -n : Root password was not changed, don't redef services.\n");
exit(1);
}
my $optlist = "p:ns";
my $rootpwd = "";
my $rootpwd2 = "";
my $noredef = 0;
my $sysprep = 0;
# Turn off line buffering on output
$| = 1;
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
# Only root.
if ($EUID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
# Note: No /etc/dumpdates support on CygWin, and no /etc/fstab or /var/account either.
my @DBFILES = ();
my @VARDIRS = ("logs", "db", "jails", "boot", "lock", "lib/dhcp");
......@@ -35,70 +63,179 @@ my @DEADFILES = ("rc.agents", "rc.delayagent", "rc.delta", "rc.healthd",
"startssh", "stopssh", "rc/rc.cygwinxp-user"
);
# Drag in path stuff so we can find emulab stuff.
BEGIN { require "/etc/emulab/paths.pm"; import emulabpaths; }
# Parse command line.
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{'p'})) {
$rootpwd = $rootpwd2 = $options{'p'};
}
if (defined($options{'n'})) {
$noredef = 1;
}
if (defined($options{'s'})) {
$sysprep = 1;
}
# Only root.
if ($EUID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
sub do_cmd ($)
{
my($cmd) = @_;
print " $cmd\n";
system($cmd);
}
my $windir = "/cygdrive/c/WINDOWS";
my $sysdir = "$windir/system32";
my $infdir = "$windir/inf";
my $netcmd = "$sysdir/net.exe";
# Could use /share/windows/sysprep, but prepare may have been run once
# already, and unmounted /share. We mount Z: to authenticate, so use that.
my $sysprep_src = "/cygdrive/z/windows/sysprep";
my $sysprep_dst = "/cygdrive/c/sysprep";
my $sysprep_cmd = "$sysprep_dst/sysprep.exe";
my $drivers_dst = "/cygdrive/c/drivers";
#
# Need the current root password to re-define the Emulab services to match.
# Must be logged in on the serial console to run Sysprep. Check for it.
#
use Term::ReadKey;
my $rootpwd = "";
while ($rootpwd eq "") {
print "Enter the root password: ";
ReadMode 'noecho';
$rootpwd = ReadLine 0;
chomp $rootpwd;
ReadMode 'normal';
print "\n";
}
my $rootpwd2 = "";
while ($rootpwd2 eq "" || $rootpwd ne $rootpwd2) {
print "Didn't match, try again.\n"
if $rootpwd2 ne "" && $rootpwd ne $rootpwd2;
print "Re-enter the root password: ";
ReadMode 'noecho';
$rootpwd2 = ReadLine 0;
chomp $rootpwd2;
ReadMode 'normal';
print "\n";
if ($sysprep) {
#
# Just "tty" doesn't work in Cygwin; it doesn't show the real device.
# Use "last" to find the current root logins on ttyS0 and match "tty".
#
my $tty = `tty`; chomp $tty;
open LAST, "last root|";
while (my $last = <LAST>) {
if ($last =~ m/^root +(tty[0-9]) +ttyS0 .*still logged in/) {
#
# Now we know where root is logged in. See if we're the one.
#
if ( $tty ne "/dev/$1" ) {
print "*** Sysprep shuts down the network.\n";
print "*** prepare -s must be run on the serial console\n";
print "*** not on an ssh connection tty ($tty).\n";
exit 1;
}
}
elsif ($last =~ m/^gone - no logout/) {
#
# RDP sessions re-use tty devs, but "last" doesn't see logins.
# If they ever fix it, this case won't work right and we could
# be confused by a root login under RDP. Meanwhile, it works.
#
print "*** Sysprep shuts down the network.\n";
print "*** prepare -s must be run on the serial console,\n";
print "*** not in an RDP session tty ($tty).\n";
exit 1;
}
}
close LAST;
print "Authenticating for read-only access to /share/windows.\n";
do_cmd "$netcmd use Z: /DELETE >& /dev/null";
do_cmd "$netcmd use Z: '\\\\fs\\share' PublicOnly /persistent:no";
die "*** Cannot access sysprep tools from $sysprep_src."
if (! -e $sysprep_src);
print "Setting up for Sysprep/Mini-Setup.\n";
#
# Get the right flavor of tools for the SP level.
#
my $cv = "/HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion";
my $sp = `regtool get "$cv/CSDVersion"`;
chomp $sp;
my $deploy_src;
if ($sp eq "Service Pack 2") {
$deploy_src = "$sysprep_src/xpsp2_support_tools_deploy";
}
elsif ($sp eq "Service Pack 1") {
$deploy_src = "$sysprep_src/xpsp1_support_tools_deploy";
}
else {
$deploy_src = "$sysprep_src/xp_support_tools_deploy";
}
print "$sp sysprep from $deploy_src\n";
print "Copying deploy tools to $sysprep_dst\n";
do_cmd "rm -rf $sysprep_dst"; # Removed by Mini-Setup, make sure.
do_cmd "cp -rp $deploy_src $sysprep_dst";
do_cmd "cp -p $sysprep_src/sysprep.inf $sysprep_dst";
die "*** Didn't get sysprep!\n"
if (! -x $sysprep_cmd);
print "Copying drivers directories to C:/drivers.\n";
do_cmd "rm -rf $drivers_dst";
do_cmd "cp -rp $sysprep_src/drivers $drivers_dst";
# Special case for non-Microsoft boot disk or SCSI controller drivers.
# OemPnpDriversPath in sysprep.inf evidently doesn't work for the boot
# disk driver when starting Mini-setup. Pre-install it by hand.
my $driver = "symmpi";
my $drvdir = "$drivers_dst/$driver";
my $inf = "$driver.inf";
if (-e $drvdir) {
print "Pre-installing the $drvdir driver for Mini-Setup.\n";
# Must be a signed driver, with CatalogFile no-op'ed in the inf file.
do_cmd "sed 's/CatalogFile/;;;&/' $drvdir/$inf > $infdir/$inf";
do_cmd "cp -p $drvdir/* $sysdir";
}
}
#
# Windows stores the password as part of the definition of services that run
# as a real user, such as root, rather than as SYSTEM. Redefine them with the
# current password. Otherwise, Windows will refuse to start them up at reboot.
#
print "\nRedefining EmulabShutdown.\n";
# Have to remove a service before you can redefine it.
system("cygrunsrv -R EmulabShutdown");
system("cygrunsrv -I EmulabShutdown -u root -w \"$rootpwd\"" .
" -p /cygdrive/c/cygwin/bin/bash" .
" --shutdown --type manual" .
" -a \"--norc --noprofile -c '/usr/local/etc/emulab/tbshutdown'\"");
system("cygrunsrv -VQ EmulabShutdown");
print "\nRedefining EmulabStartup.\n";
my $firstboot = "/usr/local/etc/emulab/rc/rc.firstboot";
my $bootsetup = "/usr/local/etc/emulab/rc/rc.bootsetup";
my $progrun = "cygrunsrv -S ProgAgent";
my $bootlog = "/var/log/bootsetup.log";
system("cygrunsrv -R EmulabStartup");
system("cygrunsrv -I EmulabStartup -u root -w \"$rootpwd\"" .
" --dep DHCP --dep elvinsvc.exe --dep W32Time" .
" -p /cygdrive/c/cygwin/bin/bash" .
" -a \"--norc --noprofile -c " .
" '( $firstboot; $bootsetup; $progrun ) >& $bootlog'\"");
system("cygrunsrv -VQ EmulabStartup");
if (! $noredef) {
#
# Need the current root password to re-define the Emulab services to match.
# (May already have one from a -p argument. Prompt if not.)
#
use Term::ReadKey;
while ($rootpwd eq "") {
print "Enter the root password: ";
ReadMode 'noecho';
$rootpwd = ReadLine 0;
chomp $rootpwd;
ReadMode 'normal';
print "\n";
}
while ($rootpwd2 eq "" || $rootpwd ne $rootpwd2) {
print "Didn't match, try again.\n"
if $rootpwd2 ne "" && $rootpwd ne $rootpwd2;
print "Re-enter the root password: ";
ReadMode 'noecho';
$rootpwd2 = ReadLine 0;
chomp $rootpwd2;
ReadMode 'normal';
print "\n";
}
#
# Turn off line buffering on output
#
$| = 1;
#
# Windows stores the password as part of the definition of services that
# run as a real user, such as root, rather than as SYSTEM. Redefine them
# with the current password. Otherwise, Windows will refuse to start them
# up at reboot.
#
print "\nRedefining EmulabShutdown.\n";
# Have to remove a service before you can redefine it.
system("cygrunsrv -R EmulabShutdown");
system("cygrunsrv -I EmulabShutdown -u root -w \"$rootpwd\"" .
" -p /cygdrive/c/cygwin/bin/bash" .
" --shutdown --type manual" .
" -a \"--norc --noprofile -c '/usr/local/etc/emulab/tbshutdown'\"");
system("cygrunsrv -VQ EmulabShutdown");
print "\nRedefining EmulabStartup.\n";
my $firstboot = "/usr/local/etc/emulab/rc/rc.firstboot";
my $bootsetup = "/usr/local/etc/emulab/rc/rc.bootsetup";
my $progrun = "cygrunsrv -S ProgAgent";
my $bootlog = "/var/log/bootsetup.log";
system("cygrunsrv -R EmulabStartup");
system("cygrunsrv -I EmulabStartup -u root -w \"$rootpwd\"" .
" --dep DHCP --dep elvinsvc.exe --dep W32Time" .
" -p /cygdrive/c/cygwin/bin/bash" .
" -a \"--norc --noprofile -c " .
" '( $firstboot; $bootsetup; $progrun ) >& $bootlog'\"");
system("cygrunsrv -VQ EmulabStartup");
}
#
# Load the OS independent support library. It will load the OS dependent
......@@ -219,8 +356,8 @@ system("chown -R root /local/logs");
system("rm -rf /local/logs/* /local/logs/.??*");
print "Cleaning out Windows logs ...\n";
system("chown root C:/windows/{iis6,setupapi}.log");
system("rm -f C:/windows/{iis6,setupapi}.log");
system("chown root C:/windows/iis6.log");
system("rm -f C:/windows/iis6.log");
print "Clearing out C:/TEMP ...\n";
system("chown -R root C:/TEMP");
......@@ -281,3 +418,17 @@ system("rm -rf C:/WINDOWS/SoftwareDistribution/Download/*");
print "Re-enable all network interfaces.\n";
system("devcon enable =net 'PCI*'");
#
# Windows wires the boot disk driver in to the NT loader, and wires
# the hardware network device instances into the network settings.
# Run Sysprep to make hardware-independent images with a sysprep.inf
# file controlling an unattended Mini-Setup to install all drivers.
#
if ($sysprep) {
print "Executing sysprep. Takes a couple of minutes.\n";
do_cmd "$sysprep_cmd -nosidgen -noreboot -reseal -mini -quiet";
}
print "\nDone!\n";
......@@ -49,7 +49,7 @@ logit "nodeid = $nodeid"
# status on the interfaces than 'netsh interface show interface'. This might help.
netsh interface reset all
# Windows DHCP doesn't make a /etc/resolv.h, which tmcc needs for bossinfo.
# Windows DHCP doesn't make an /etc/resolv.conf, which tmcc needs for bossinfo.
# Make one from ipconfig output.
ipconfig /all | tr -d '\r' | awk \
'/^ *Connection-specific DNS Suffix.*: ./{print "search", $NF} \
......@@ -63,8 +63,6 @@ tp=$svcs/Tcpip/Parameters
regtool set -s $tp/Domain $domain
logit "domain = $domain"
# Make sure all NIC's are up at the start, so they show up on ifconfig.
devcon enable =net 'PCI*'
# Cache getmac output while all interfaces are still enabled. Used by rc.ifconfig .
bootdir=/var/emulab/boot
getmac /nh /v /fo csv > $bootdir/getmac-cache
......
......@@ -37,6 +37,15 @@ chmod -f g-w /etc/emulab
# by the cached info from tmcd. Clean up like bootsetup()/tmccclrconfig().
rm -rf /var/emulab/boot/tmcc
# 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. Otherwise tmcc will fail.
ipconfig /all | tr -d '\r' | awk \
'/^Ethernet adapter/{ ifc = gensub("Ethernet adapter (.*):", "\\1", 1); next }\
/Dhcp Enabled.*No/{ stat = system("netsh interface ip set address \"$ifc\" dhcp");\
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=
......@@ -81,6 +90,14 @@ else
fi
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.
hostname=`/bin/hostname`
host="Host name '$hostname'"
if [ $nodeid = $hostname ]; then
......@@ -88,7 +105,7 @@ if [ $nodeid = $hostname ]; then
else
logit "$host differs from nodeid '$nodeid'."
# A reboot will be required.
tmcd state SHUTDOWN
tmcc state SHUTDOWN
logit "Remove a redirect switch to make sure we come back with a serial console."
bootcfg /ems OFF /id 1
......
......@@ -265,6 +265,6 @@ Log of XP images produced (most recent first.)
- Need to install pro2kxp.exe drivers.
- Install Cygwin rpm package.
. WINXP-10-24 - Windows XP SP1, host rename at boot, user dir mounts.
. WINXP-10-24 - Windows XP SP1, host rename at boot, /users NFS mounts.
prtn 1, whole disk, OS other, 5.1.2, node pc174, ping/ssh, MINIMAL, pc2000.
Leave shared and global bits off until production images are being done.
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