Linux
Apache
MySQL
PHP

CSS
XHTML1.1
XML/RSS

Creative Commons

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. Let's get all of the files in place to install Linux machines since this is the easy part.

· 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. NOTE: The reason that I separated the "clean" function from the partition creation is because of the stupid card-reader. Windows PE assigned the letter C to one of the card slots, in addition to other weirdness, so doing this with two scripts allows the disk to be cleaned and diskpart to be closed/opened so that all disks/volumes get re-read. This ensures consistent drive lettering so that my -20 and -full scripts can remove all drive letters so that drive C is free to be used for the Windows 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: How about a nice game of chess?

Back

1 comments


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

Post a comment!

Name:
Comment: