I wanted to boot Windows 7 from an iSCSI SAN, implemented with an OpenSolaris 2009.06 ZFS server. In theory, Windows 7, like Vista, 2008, 2008 R2, can be installed directly to an iSCSI target, but these instructions did not work for me. They require booting from LAN to register the iSCSI target as BIOS drive 0x80 with gPXE, and letting gPXE exit to rely on the BIOS then falling back gracefully to DVD-ROM boot in order to launch the Windows installer which would then detect BIOS drive 0x80 —the iSCSI target— and install on it. The first problem was that when gPXE exited, the BIOS would not fall back to DVD-ROM boot. Instead it forced me to press a key to reboot. So I wrote a custom COM32 program to, from gPXE, call into the BIOS via interrupt 19h to "load the OS". This worked. Interrupt 19h forced my BIOS to boot from DVD-ROM, launching the Windows installer. But then, even though the installer detected the iSCSI target, saw the correct size, was able to partition and format it, it refused to install on it. "This computer's hardware may not support booting to this disk. Ensure that the disk's controller is enabled in the computer's BIOS menu". All I saw, after pressing shift+F10 to get a shell and read setupact.log, was the same error message and that the drive did not have the "canInstall" capability. There was not a single clue of what was wrong. KB933925 was unhelpful.
Frustrated, and vividly reminded why I despise Windows (an open source OS would have let me inspect the code and fix the bug), I did not want to have to install Windows 7 on iSCSI via WinPE as it seemed too much work. So I resigned to install the OS on a regular physical disk first, then to transfer the image to an iSCSI target. Of course more hurdles came on the way, but I was able to resolve them. Hopefully my documented experience will save trouble to others who would like to enjoy the convenience of diskless booting Windows 7 via iSCSI:
- Install Windows 7 on a physical disk. When selecting a partition size (eg. 30000MB), if the disk is unpartitioned, the installer may forcefully create a small ~100MB system partition and a larger one of size 30000MB minus ~100MB. Be aware of this detail when transferring the image to the iSCSI target in later steps.
- Disable the LightWeight Filter (LWF) driver for the NIC that will be
used for iSCSI boot. As explained in
KB976042 this driver
cannot start at boot time and would prevent the NIC from being available
during iSCSI boot.
One way to unbind the LWF driver from the NIC is to use bindview.exe which has to
be compiled from the Windows Developer Kit(!) If you are like me and prefer easier
solutions, do this by editing the registry (thanks to
Takahiro
Wagatsuma for this information):
- Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}
- Find and open the subkey for the NIC (eg. 0007)
- Open the subkey Linkage
- Edit the value FilterList. Delete the line that refers to the
LWF driver UUID {B70D6460-3635-4D42-B866-B8AB1A24454C}. In my case
I had to delete the second line. Before:
After:{158B0494-2576-4DE5-9E32-98DB9E177DD8}-{B5F4D659-7DAA-4565-8E41-BE220ED60542}-0000 {158B0494-2576-4DE5-9E32-98DB9E177DD8}-{B70D6460-3635-4D42-B866-B8AB1A24454C}-0000
{158B0494-2576-4DE5-9E32-98DB9E177DD8}-{B5F4D659-7DAA-4565-8E41-BE220ED60542}-0000
- On OpenSolaris: enable iSCSI, create a ZFS filesystem.
I use OpenSolaris 2009.06, but any recent Solaris version should work the same.
Enable the iSCSI target daemon and create a
filesystem that will be dedicated to hosting the Windows image,
so it can be independently snapshotted, cloned, etc:
$ svcadm enable iscsitgt $ svcs iscsitgt STATE STIME FMRI online Jun_26 svc:/system/iscsitgt:default $ zfs create tank/win7 $ zfs list tank/win7
- Transfer the disk image to OpenSolaris.
I boot the Windows machine into Linux, and use dd and ssh to transfer the
image to OpenSolaris. Verify the partition sizes (remember that the installer may have
created 2 partitions):
Copy the range of disk sectors that will include the MBR and these 2 partitions, that is the first 206848 + 61233152 = 61440000 sectors, or 61440000 * 512 = 31457280000 bytes. This number of bytes is exactly 30000*1024*1024 because I chose "30000MB" during installation. However always verify the sizes with sfdisk because sometimes I have noticed the installer adds 1 extra MB. I use dd and ssh to stream the image over the network to my OpenSolaris server:$ sfdisk -d /dev/sda # partition table of /dev/sda unit: sectors /dev/sda1 : start= 2048, size= 204800, Id= 7, bootable /dev/sda2 : start= 206848, size= 61233152, Id= 7 /dev/sda3 : start= 0, size= 0, Id= 0 /dev/sda4 : start= 0, size= 0, Id= 0
$ dd if=/dev/sda bs=512 count=61440000 | ssh opensolaris "cat >/tank/win7/hda"
- On OpenSolaris, create the iSCSI target.
First, snapshot the image (it will be useful):
Then create the iSCSI target from it:$ zfs snapshot tank/win7@orig
Immediately after iscsitadm create, OpenSolaris will start rewriting the entire image file over itself in order to force the allocation of all data blocks (thick image). This will take multiple minutes during which the iSCSI target is not really available (if you try to boot from it using gPXE, it will throw Input/output errors —it took me a while to find the cause of these errors). IMHO there should be an option to disable thick allocation. Anyway, monitor the progress of the rewrites with zfs list:$ iscsitadm create target --type disk --backing-store /tank/win7/hda win7 $ iscsitadm list target Target: win7 iSCSI Name: iqn.1986-03.com.sun:...win7 Connections: 0
You will know they are finished when the "USED" space will have doubled (because thanks to the snapshot, the non-rewritten blocks have been preserved —I told you it would be useful!):$ zfs list tank/win7 NAME USED AVAIL REFER MOUNTPOINT tank/win7 29.2G 2.83T 29.2G /tank/win7
When the rewrites are done, roll back to the snapshot, if only to reduce the used space back to normal:$ zfs list tank/win7 NAME USED AVAIL REFER MOUNTPOINT tank/win7 58.4G 2.80T 29.2G /tank/win7
$ zfs rollback tank/win7@orig $ zfs list tank/win7 NAME USED AVAIL REFER MOUNTPOINT tank/win7 29.2G 2.83T 29.2G /tank/win7
- Configure gPXE to offer booting Windows 7 from SAN.
I will assume that you have a pre-existing DHCP setup
serving gPXE configured to read a menu file that simply needs to be
updated with the Windows 7 option. If not, follow one of the
numerous gPXE HowTo guides.
The gPXE menu file should be edited to add (replace x.x.x.x with the
IP address of the OpenSolaris server, and the IQN with the one output
earlier by iscsitadm list):
Where cmd.c32 should be extracted from the syslinux 3.86 tarball and placed in the TFTP directory. I have not tried the newer 4.x versions but they should work.label win7 kernel cmd.c32 append sanboot iscsi:x.x.x.x::::iqn.1986-03.com.sun:...win7
- This is it, test it! Remove the physical disk from the Windows machine, boot via PXE, select the win7 menu option, and enjoy your new Windows 7 environment.
Diskless machines booted from an iSCSI SAN implemented with an OpenSolaris ZFS server allow you to do powerful things. You can:
- "zfs rollback" to revert a machine to snapshot.
- "zfs clone && iscsitadm create target" to quickly provision a new machine (modulo the forced thick allocation).
- "zfs destroy" to get rid of it.
Essentially, many of the features that are typically only available to virtualized environments are made available to physical machines. I have multiple diskless Linux machines that I use for my own GPGPU development projects. This setup gives me the option to run some tests under Windows 7 as well. Given that I frequently move GPUs from one machine to another, swap hardware components, upgrade or revert the OS/drivers, diskless booting and snapshotting certainly make my life much easier. If the above instructions to boot Windows 7 from iSCSI are useful to you, let me know!