2013-06-26 14:03:51
Deconstructing K.E.V.I.N.
Ever since I started teaching I have always dreaded one aspect of lab classes, OS installation. It takes forever. You have to have the right CDs/DVDs, drivers, and hope that all of the students are following along so that all systems are configured the same. Things never go perfectly but one thing is always certain, an entire class is wasted on setup. Not to mention when things break throughout the semester and students have to reinstall everything from scratch.So I embarked on a [very long] journey to create a system that could build our entire lab from the ground up in as automated fashion as possible. I wanted OS installation to take <20 minutes, not >1 hour. I wanted to forget about CDs and DVDs. I wanted everything to happen with a single keystroke. I wanted this to work for every version of Windows and Linux that we use in our classes. Most of all, however, I wanted it to be as streamlined and customizable as possible, which meant not using any of Microsoft's tools (like SCCM) to get the job done. This meant one thing, I had to write my own imaging system.
Welcome to K.E.V.I.N. (cue Jurassic Park theme music)
Below are the basic instructions to get everything up and running. I will assume a basic knowledge of Linux and Windows, so this will not be a step-by-step, type-everything-I-do guide. I will do my best, however, to tell you what you need to do.
NOTE: My lab consists of Lenovo Thinkstation E30's, which contain a built-in 4-slot card reader. This is important during the Windows portion because some clever DISKPARTing needs to be done to work around Windows being stupid and assigning drive letters to the card reader slots even there is no media present. Depending on the machines you're imaging, YMMV with the DISKPART scripts.
· Install CentOS 6.4 x64 onto your imaging server, choosing Basic Server once you get to package selection, and be sure to give it a static IP that you'll reference many times throughout this document. (We don't need a GUI. If you do, please stop reading this guide now and go give Bill Gates a hug).
· Login as root.
· Install the necessary items for creating a PXE server to install Linux machines (TFTP, DHCP, Syslinux, and NFS).
yum install tftp-server dhcp dhcp-common syslinux nfs-utils nfs-utils-lib
· TFTP gets installed as an XINETD service, so we need to ensure XINETD is set to start on boot and TFTP is enabled.
# chkconfig xinetd on
# vi /etc/xinetd.d/tftp
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /var/lib/tftpboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
# service xinetd restart
· Put the PXE files into place, make the PXE directory structure, and configure the PXE menu.
# cd /usr/share/syslinux
# cp chain.c32 mboot.c32 memdisk menu.c32 pxelinux.0 /var/lib/tftpboot
# cd /var/lib/tftpboot
# mkdir -p images/cent64_x64 images/winpe_x64 pxelinux.cfg
# vi /var/lib/tftpboot/pxelinux.cfg/default
default menu.c32
prompt 0
timeout 300
ONTIMEOUT local
MENU TITLE PXE Menu
LABEL Local Hard Disk
MENU LABEL Local Hard Disk
localboot 0
LABEL CentOS 6.4 x64 - Entire Disk
MENU LABEL CentOS 6.4 x64 - Entire Disk
kernel images/cent64_x64/vmlinuz
APPEND ks initrd=images/cent64_x64/initrd.img ramdisk_size=100000 ksdevice=eth0 ip=dhcp ks=nfs:10.85.10.225:/ks/cent64.cfg
LABEL CentOS 6.4 x64 - Dual Boot
MENU LABEL CentOS 6.4 x64 - Dual Boot
kernel images/cent64_x64/vmlinuz
APPEND ks initrd=images/cent64_x64/initrd.img ramdisk_size=100000 ksdevice=eth0 ip=dhcp ks=nfs:10.85.10.225:/ks/cent64-dual.cfg
LABEL WinPE x64
MENU LABEL WinPE x64
LINUX memdisk
APPEND iso
INITRD images/winpe_x64/pe_x64.iso
There are 4 boot options from the PXE menu.
- Local Hard Disk: Bypasses PXE in case you accidentally booted into it.
- CentOS 6.4 x64 - Entire Disk: Formats the entire hard drive and installs linux.
- CentOS 6.4 x64 - Dual Boot: Assumes you've already installed Windows into a small partition and have free space at the end of the disk. Linux will be installed into the free space.
- WinPE x64: Boot to Windows PE 4.0 to start the automated Windows imaging process.
· Mount the CentOS ISO to a folder (or mount the DVD) and copy the boot files for TFTP and all files for installation.
# mount -o loop -t iso9660 /var/tmp/CentOS.iso /mnt/tmp
# cd /mnt/tmp/isolinux
# cp initrd.img vmlinuz /var/lib/tftpboot/images/cent64_x64/
# mkdir -p /ks/isolinux/cent64_x64
# cd /mnt/tmp
# cp -r * /ks/isolinux/cent64_x64/
# cd ; umount /mnt/tmp
· The last thing to do for Linux installations is to create the 2 kickstart files we referenced earlier. In case you were wondering, the root password is "password".
# vi /ks/cent64.cfg
#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Firewall configuration
firewall --disabled
# Install OS instead of upgrade
install
# Use NFS installation media
nfs --server=10.85.10.225 --dir=/ks/isolinux/cent64_x64
# Root password
rootpw --iscrypted $1$LXANEN1B$UYLYwE1gpKZzSR35/RdUi/
# System authorization information
auth --useshadow --passalgo=sha512
# Use text mode install
text
firstboot --disable
# System keyboard
keyboard us
# System language
lang en_US
# SELinux configuration
selinux --disabled
# Installation logging level
logging --level=info
# Reboot after installation
reboot
# System timezone
timezone --isUtc America/New_York
# Network information
network --bootproto=dhcp --device=eth0 --onboot=on
# System bootloader configuration
bootloader --location=mbr
# Clear the Master Boot Record
zerombr
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part swap --fstype="swap" --size=1024
part / --fstype="ext4" --grow --size=1
%post
chkconfig ip6tables off
chkconfig iptables off
chkconfig postfix off
chkconfig rpcbind off
chkconfig rpcgssd off
chkconfig rpcidmapd off
chkconfig rpcsvcgssd off
chkconfig xinetd off
%end
%packages
@base
@console-internet
@debugging
@legacy-unix
@network-file-system-client
@network-tools
dos2unix
ftp
genisoimage
jwhois
mtools
nmap
squashfs-tools
telnet
unix2dos
-trace-cmd
-valgrind
%end
# vi /ks/cent64-dual.cfg
#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Firewall configuration
firewall --disabled
# Install OS instead of upgrade
install
# Use NFS installation media
nfs --server=10.85.10.225 --dir=/ks/isolinux/cent64_x64
# Root password
rootpw --iscrypted $1$LXANEN1B$UYLYwE1gpKZzSR35/RdUi/
# System authorization information
auth --useshadow --passalgo=sha512
# Use text mode install
text
firstboot --disable
# System keyboard
keyboard us
# System language
lang en_US
# SELinux configuration
selinux --disabled
# Installation logging level
logging --level=info
# Reboot after installation
reboot
# System timezone
timezone --isUtc America/New_York
# Network information
network --bootproto=dhcp --device=eth0 --onboot=on
# System bootloader configuration
bootloader --location=mbr
# Partition clearing information
clearpart --linux
# Disk partitioning information
part swap --fstype="swap" --size=1024
part / --fstype="ext4" --grow --size=1
%post
chkconfig ip6tables off
chkconfig iptables off
chkconfig postfix off
chkconfig rpcbind off
chkconfig rpcgssd off
chkconfig rpcidmapd off
chkconfig rpcsvcgssd off
chkconfig xinetd off
%end
%packages
@base
@console-internet
@debugging
@legacy-unix
@network-file-system-client
@network-tools
dos2unix
ftp
genisoimage
jwhois
mtools
nmap
squashfs-tools
telnet
unix2dos
-trace-cmd
-valgrind
%end
· Configure your DHCP server to give out IPs on your subnet and point to the TFTP/PXE server (for us, it's the same box) when a client sends a BOOTP request:
# vi /etc/dhcp/dhcpd.conf
allow booting;
allow bootp;
option option-128 code 128 = string;
option option-129 code 129 = text;
next-server 10.85.10.225;
filename "/pxelinux.0";
subnet 10.85.10.0 netmask 255.255.255.0
{
range 10.85.10.150 10.85.10.199;
option routers 10.85.10.1;
option domain-name-servers 8.8.8.8;
}
# service dhcpd restart
At this point in time you can now PXE boot and install CentOS machines. But we want to keep going and get Windows imaging working.
· We need to ensure that all files we'll use to do Windows imaging are shared via CIFS/SAMBA so that our WinPE PXE image can access them. Since the Samba conf file is huge, I'm only going to show the relevant sections that need modified.
# yum install samba samba4-libs samba-client samba-common samba-winbind samba-winbind-clients
# vi /etc/samba/smb.conf
<<<SNIPPED>>>
security = share
guest account = root
passdb backend = tdbsam
<<<SNIPPED>>>
[Windows]
comment = Windows Install Files
path = /ks/windows
read only = yes
guest ok = yes
browseable = yes
<<<EOF>>>
# chkconfig smb on
# service smb restart
NOTE: Keep the CIFS share in read only mode so random people can't delete your stuff. You will, however, need to change it to "read only = no" and restart the service before you perform an image capture since that will need to write to the share. Just remember to put it back to "read only = yes" and restart the service when you're done capturing.
· My system can install 4 versions of Windows: Server 2008 R2, Server 2012, 7, and 8. We will offer "CD" installs, which require all files from each CD/DVD, and also image deployments. Let's set up the CD installs first since they are the easiest.
# mkdir -p /ks/windows
# cd /ks/windows
# mkdir images win2008sp1r2x64 win2012x64 win7sp1x64 win8x64
· Copy the files from each CD into their respective folder. I don't care how you do it. You're smart. Figure it out. (If you go the ISO mount route, the filesystem type of Windows DVDs is UDF, not ISO9660).
Now let's get all of our scripts in place on the server.
- menu.bat: This is the main script that the WinPE image launches that contains all of the logic.
- diskpart-listvol.txt: This lists all volumes (drive letters) on the machine so you know which one you want to capture.
- diskpart-clean.txt: This wipes the disk.
- diskpart-20.txt: This creates a 20GB NTFS partition.
- diskpart-full.txt: This fills the disk with an NTFS partition.
NOTE: You'll see that I use the Z drive for images in this script. The 'pushd' command used later in the PE image automatically connects the server to the Z drive every time, so this will work for everyone.
# vi menu.bat
@echo off
:MENU
cls
echo ###############################################################################
echo # #
echo # Welcome to... #
echo # #
echo # K.E.V.I.N. #
echo # #
echo # Kevin's Educational Verbose Imaging Network #
echo # #
echo ###############################################################################
echo.
echo Windows 7 SP1 x64 Windows 8 x64 Windows Server 2008 R2 x64
echo A) CD Install D) CD Install G) CD Install
echo B) Image - Entire Disk E) Image - Entire Disk H) Image - Entire Disk
echo C) Image - 20GB F) Image - 20GB I) Image - 20GB
echo.
echo Windows Server 2012 x64 Tools
echo J) CD Install V) Partition - Entire Disk
echo K) Image - Entire Disk W) Partition - 20GB
echo L) Image - 20GB X) Exit to Shell
echo Y) Capture Windows Image
echo Z) Reboot
echo.
set /p choice= Select Option:
IF /I "%choice%"=="A" GOTO :WIN7SP1X64CD
IF /I "%choice%"=="B" GOTO :WIN7SP1X64IFULL
IF /I "%choice%"=="C" GOTO :WIN7SP1X64I20
IF /I "%choice%"=="D" GOTO :WIN8X64CD
IF /I "%choice%"=="E" GOTO :WIN8X64IFULL
IF /I "%choice%"=="F" GOTO :WIN8X64I20
IF /I "%choice%"=="G" GOTO :WIN2008R2SP1X64CD
IF /I "%choice%"=="H" GOTO :WIN2008R2SP1X64IFULL
IF /I "%choice%"=="I" GOTO :WIN2008R2SP1X64I20
IF /I "%choice%"=="J" GOTO :WIN2012X64CD
IF /I "%choice%"=="K" GOTO :WIN2012X64IFULL
IF /I "%choice%"=="L" GOTO :WIN2012X64I20
IF /I "%choice%"=="V" GOTO :DISKFULL
IF /I "%choice%"=="W" GOTO :DISK20
IF /I "%choice%"=="X" GOTO :END
IF /I "%choice%"=="Y" GOTO :CAPTURE
IF /I "%choice%"=="Z" GOTO :REBOOT
GOTO :MENU
REM ---------
REM Windows 7
REM ---------
:WIN7SP1X64CD
win7sp1x64\setup.exe
GOTO :END
:WIN7SP1X64IFULL
echo.
echo This will destroy all data on the hard drive.
echo Windows will consume the entire disk.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-full.txt
dism /apply-image /imagefile:z:\images\win7sp1x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
:WIN7SP1X64I20
echo.
echo This will destroy all data on the hard drive.
echo Windows will be copied into a 20GB partition.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-20.txt
dism /apply-image /imagefile:z:\images\win7sp1x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
REM ---------
REM Windows 8
REM ---------
:WIN8X64CD
win8x64\setup.exe
GOTO :END
:WIN8X64IFULL
echo.
echo This will destroy all data on the hard drive.
echo Windows will consume the entire disk.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-full.txt
dism /apply-image /imagefile:z:\images\win8x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
:WIN8X64I20
echo.
echo This will destroy all data on the hard drive.
echo Windows will be copied into a 20GB partition.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-20.txt
dism /apply-image /imagefile:z:\images\win8x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
REM ----------------------
REM Windows Server 2008 R2
REM ----------------------
:WIN2008R2SP1X64CD
win2008sp1r2x64\setup.exe
GOTO :END
:WIN2008R2SP1X64IFULL
echo.
echo This will destroy all data on the hard drive.
echo Windows will consume the entire disk.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-full.txt
dism /apply-image /imagefile:z:\images\win2008r2sp1x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
:WIN2008R2SP1X64I20
echo.
echo This will destroy all data on the hard drive.
echo Windows will be copied into a 20GB partition.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-20.txt
dism /apply-image /imagefile:z:\images\win2008r2sp1x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
REM -------------------
REM Windows Server 2012
REM -------------------
:WIN2012X64CD
win2012x64\setup.exe
GOTO :END
:WIN2012X64IFULL
echo.
echo This will destroy all data on the hard drive.
echo Windows will consume the entire disk.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-full.txt
dism /apply-image /imagefile:z:\images\win2012x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
:WIN2012X64I20
echo.
echo This will destroy all data on the hard drive.
echo Windows will be copied into a 20GB partition.
echo Press CTRL+C to quit!
echo.
pause
diskpart /s diskpart-clean.txt
diskpart /s diskpart-20.txt
dism /apply-image /imagefile:z:\images\win2012x64.wim /index:1 /applydir:c:\
GOTO :FIXMBR
REM -----
REM Tools
REM -----
:CAPTURE
cls
echo Current Images:
echo ---------------
dir /b /on images
echo.
echo Current Local Volumes:
echo ----------------------
diskpart /s diskpart-listvol.txt
echo.
set /p iname= Enter New Image Name (no spaces):
set /p letter= Enter Drive Letter:
echo.
dism /capture-image /imagefile:z:\images\%iname%.wim /capturedir:%letter%:\ /name:%iname% /compress:max
echo.
pause
GOTO :MENU
:REBOOT
echo.
echo Your system will now reboot...
echo.
pause
wpeutil reboot
:FIXMBR
bcdedit /set {default} device partition=c:
bcdedit /set {default} osdevice partition=c:
bcdedit /set {bootmgr} device partition=c:
GOTO :REBOOT
:DISKFULL
diskpart /s diskpart-clean.txt
diskpart /s diskpart-full.txt
GOTO :MENU
:DISK20
diskpart /s diskpart-clean.txt
diskpart /s diskpart-20.txt
GOTO :MENU
:END
echo.
echo Type 'menu' to restart the image process...
echo.
:EOF
# vi diskpart-listvol.txt
list volume
# vi diskpart-clean.txt
select disk 0
clean
exit
# vi diskpart-20.txt
select volume 0
remove all noerr
select volume 1
remove all noerr
select volume 2
remove all noerr
select volume 3
remove all noerr
select volume 4
remove all noerr
select disk 0
create partition primary size=20480
format fs=ntfs quick
assign letter=c
active
exit
# vi diskpart-full.txt
select volume 0
remove all noerr
select volume 1
remove all noerr
select volume 2
remove all noerr
select volume 3
remove all noerr
select volume 4
remove all noerr
select disk 0
create partition primary
format fs=ntfs quick
assign letter=c
active
exit
At this point almost all of our server-side configuration is done. We only need to generate our Windows PE image and place it in our TFTP directory so that our machines can PXE boot to it.
· Build a separate Windows 8 machine (yes, I'm serious... yay, Microsoft!) then download and install the ADK for Windows 8.
· Open the ADK Command Prompt (I think it's called Windows Deployment... something... crappy...) and generate your PE build environment.
> copype.cmd amd64 c:\pe_x64
To save you time, you're probably going to need to add the NIC drivers for your machines to the PE image because unlike every other operating system in the world, ones made by Microsoft don't contain the drivers that you need. So if you have to do this step, here's how.
· Go download the NIC drivers for your machine(s) from the manufacturer's website and extract them into a folder on your hard drive (C:\Drivers works fine). Find the proper INF file for your specific NIC in the hot mess you just extracted and note the full path for later.
· From an ADMINISTRATOR command prompt (have fun figuring that one out on Windows 8), mount the PE image so we can edit it and install the NIC drivers.
# dism /mount-image /imagefile:c:\pe_x64\media\sources\boot.wim /index:1 /mountdir:c:\pe_x64\mount
# dism /image:c:\pe_x64\mount /add-driver /driver:C:\DRIVERS\PRO1000\Winx64\NDIS62\e1c62x64.inf
· Now we need to make it so that as soon as this PE image boots it will automatically connect to our imaging server and run our menu.bat script. We'll need to modify a file already in the PE image (startnet.cmd) and make one of our own (c208.bat).
# cd c:\pe_x64\mount\Windows\System32
# notepad startnet.cmd
wpeinit
start c208
# notepad c208.bat
@echo off
echo Initializing network...
REM Wait 2 seconds to ensure the network starts
ping 192.0.2.2 -n 1 -w 2000 > nul
:TESTNET
echo Testing for connectivity...
ping -n 1 10.85.10.225 | find "Reply from " >NUL
IF NOT ERRORLEVEL 1 GOTO :CONNECT
IF ERRORLEVEL 1 GOTO :TESTNET
:CONNECT
echo Connecting to deployment server...
pushd \\10.85.10.225\Windows
menu
:EOF
NOTE: Do not attempt to put all of that code into startnet.cmd. In Microsoft's infinite wisdom, the network will not start until startnet.cmd has completely finished. Thus, the "start c208" line at the end will pop a new command prompt for the rest of the logic allowing startnet.cmd to gracefully exit.
· For our last trick on the Windows 8 machine, we have to unmount the PE image, set the locale, and generate the ISO.
# dism /unmount-image /mountdir:c:\pe_x64\mount /commit
# bcdedit /store c:\pe_x64\media\EFI\Microsoft\Boot\BCD /set {bootmgr} locale en-us
> makewinpemedia /iso c:\pe_x64 c:\pe_x64\pe_win8_x64.iso
NOTE: Did you notice that prompts starting with a # were administrative and prompts starting with a > were the ADK prompt?
· Get the ISO you just made onto your linux server. Again, I don't care how, but here's one way if you download pscp.exe onto your Windows machine.
> pscp c:\pe_x64\pe_win8_x64.iso root@10.85.10.225:/var/lib/tftpboot/images/winpe_x64/pe_x64.iso
Congratulations, you now have a fully functional imaging server that can deploy Linux and Windows machines.
But wait, there's more. We didn't actually make any Windows images that we can deploy. I'll let most of that up to you, but here's the basic process:
- Install the machine of your choosing and configure it however you want.
- Make/copy an unattended XML file into C:\Windows\System32\Sysprep (I've attached my 4, the admin password is abcABC123).
- Make SetupComplete.cmd in c:\windows\setup\scripts to contain 2 lines:
- From an admin command prompt, cd to the sysprep folder and execute:
- Turn the machine back on ensuring you go straight to PXE (don't let it boot into Windows!), boot WinPE, and capture it.
- Make sure to name it exactly what's in menu.bat (the folder names are the same, too) and don't append .wim (e.g., win7sp1x64).
del /Q /F c:\windows\system32\sysprep\unattended-7.xml
del /Q /F c:\windows\panther\unattended-7.xml
# sysprep /generalize /oobe /unattend:unattended-7.xml /shutdown
Back
2013-06-30 08:07:25
john w currie says...
A lot of work put into this but i would be singing the 1978 Song by warren zevon "Send lawyers guns and money" get me out of this rewriting this scripts. Ouch