Diskless Windows 7 with iSCSI and gPXE

One of the things that makes virtual machines so great for development and testing is the ability to quickly and easily take snapshots and revert to earlier snapshots. With physical systems, this is more cumbersome. Sure, one could image the hard drive from a LiveCD, but these things take at least 10s of minutes with today’s giant disk drives, and physically moving disk drives around requires human intervention. Solutions like Intel’s AMT might be viable if all the machines are homogeneous, but that’s rarely the case. My goal is to setup automated regression testing of a hypervisor with multiple guest operating systems on hardware platforms from multiple vendors. To me, all of this screamed Network Boot / Disk-less systems. I’ve used PXE boot in the past with Linux systems, especially to launch FAI and automatically configure Linux. However, the only thing I’ve ever done with Windows that resembles automation is to “slipstream” a Windows XP install CD with BartPE, until now.

Other people have already figured out most of the hard stuff. Many thanks to all of them. Zorinaq’s Diskless Windows 7 iSCSI boot from OpenSolaris 2009.06 ZFS Server contained enough detail to make me confident enough to give all of this a try. Since 2009, however, the “Sun and Oracle thingy” happened. I didn’t want to have to depend on anything from Oracle, and though web searches lead me to learn about the existence of OpenIndiana, I ran into a viable Linux option: Using iSCSI On Debian Lenny (Initiator And Target). Though the instructions were somewhat dated, I had no trouble setting up Debian Squeeze as the Target (server). I connected from an Ubuntu 10.04 LTS Initiator (client) just to confirm that everything worked as expected before getting involved with Windows.

So here we are: Debian Squeeze iSCSI Target system successfully configured without any major snafus. Note that I did opt to use LVM to manage 1.9TB of unused space on the 2TB disk inside the fileserver I’m using.

Aside: I’ve only used LVM a few times in the past so I may update this with more information about some useful observations. One shortcoming I’ve observed so far (maybe? I’m still not fully convinced that this is correct) is that an LVM snapshot is not expected to live forever. Every howto I’ve read suggests, after taking a snapshot, that the contents of the snapshot should be copied elsewhere, and the snapshot deleted. This means it’s not possible to have the same workflow as I commonly use with VMware Fusion/Workstation. With VMware, I frequently take snapshots at interesting configuration points and keep them around indefinitely. I can easily rollback whenever I like, definitely without incurring the overhead of a full filesystem copy.

gPXE (part of the EtherBoot project) “implements PXE, the industry standard network booting specification, and extends it with a number of new protocols and features.” It can be chain-loaded from regular PXE. I did not bother trying to flash any NIC ROMs, again because I want my solution to work on as many different hardware platforms as possible. The gPXE feature of interest to us here is its ability to mount and boot from an iSCSI root filesystem.

Here are two more references that I found useful:

gPXE can get its configuration file from a webserver, instead of TFTP. I’m assuming, dear reader, that to even have an interest in diskless iSCSI boot, you can setup a LAMP stack or other webserver in your sleep.

I did not find a concrete example of a “gPXE” boot script (mine lives in /var/www/gpxe_boot_script.html), or a clear explanation in any documentation I could find that it’s a “shebang”-style file, so I post mine here for reference:

dhcp net0
set keep-san 1
sanboot iscsi:

Here is my (working with diskless Windows 7 booting via iSCSI) /etc/dhcp/dhcpd.conf:

ddns-update-style none;
option domain-name "example.com";
option domain-name-servers;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
option space gpxe;
option gpxe-encap-opts code 175 = encapsulate gpxe;
option gpxe.priority code 1 = signed integer 8;
option gpxe.keep-san code 8 = unsigned integer 8;
option gpxe.no-pxedhcp code 176 = unsigned integer 8;
option gpxe.bus-id code 177 = string;
option gpxe.bios-drive code 189 = unsigned integer 8;
option gpxe.username code 190 = string;
option gpxe.password code 191 = string;
option gpxe.reverse-username code 192 = string;
option gpxe.reverse-password code 193 = string;
option gpxe.version code 235 = string;
option iscsi-initiator-iqn code 203 = string;
subnet netmask {
option routers;
allow booting;
allow bootp;
next-server; # this server
if exists user-class and option user-class = "gPXE" {
filename "";
} else {
filename "undionly.kpxe";
option root-path "iscsi:";
option gpxe.keep-san 1;

In addition to providing the above information because I wished I had found such information before starting, I now detail the problems that I encountered and overcame.

Problem 1: The network card in my diskless client host is unsupported by Windows 7 out-of-the-box, preventing it from communicating via iSCSI. I worked around this by downloading the relevant driver from the HP/Intel website, and extracting the files onto a USB stick. When the installer asks when you would like to install Windows, there is an option to load a driver. It happily loads network drivers in addition to storage drivers.

Problem 2: The Windows 7 installer does not see the iSCSI target as a viable disk on which to install Windows, if I chainload gPXE from PXE. My diskless client host (an HP Elite 8100) has three options for network booting (Disabled, PXE, iSCSI). I was initially trying with it set to PXE, because my goal is to have the most general, cross-platform solution that I can. However, the Windows installer takes forever to load up to the screen where it looks for a disk onto which to install, and I didn’t have the patience to try too many different things. Plus, when I set the NIC to iSCSI, it just worked. Note that in iSCSI mode the BIOS settings for the NIC request the name of the iSCSI target. I entered them.

Configured thusly, at boot time the diskless system starts by issuing a DHCP request to connect the iSCSI volume, and then proceeds through the normal boot sequence. I put the DVD drive above the NIC, and the Windows 7 installer launched without issue. I was then able to successfully install Windows onto the iSCSI target (after loading the NIC driver from the USB stick), as it magically appeared in the list of possible disks onto which to install Windows.

Now, that worked to install windows, which is/was the hard part. Once Windows is installed on an iSCSI volume, it seems to work great. I switched my BIOS settings back to regular PXE chainloading gPXE and Windows boots just fine.

As the purpose of this exercise is to setup multiple machines for regression testing, I will be going through these steps again before too long. I hope to iteratively refine this post into very detail, effective instructions.

Some buzz-words that may help in web searches on this topic: iSCSI, gPXE, LVM, DHCP, TFTP, Apache2, Intel NIC Driver, Windows 7 32-bit CD.


1 thought on “Diskless Windows 7 with iSCSI and gPXE

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s