Boot from VHD – the joy of BCDedit and a nice hyper-v gotcha or two.

I’ve been updating two of my machines from the Beta to the RC of Server 2008 R2. It’s been quite a learning experience, and I’ve put together a video to show some of the things that Windows 7 and Server 2008 R2 can do with VHDs which should be posted soon. Along the way I’ve found some of the pitfalls and climbed out of them so let me share what happened.

The idea was simple enough. Install the new OS into a VHD, at the first reboot copy the VHD and use it to bring a second machine up at the same “mostly installed” point.  That is quite simple 3 commands using BCD edit. In Windows NT from 3.1 all the way through to server 2003 the bootstap loader used a file named boot.ini to tell it what to do. Boot.ini made way for the boot configuration database, very clever it  is too, unfortunately you can’t work on it in a text editor – instead of being an XML file or similar it it’s edited with BCD edit. The database contains a number of sections. One named “Windows Boot Manager” describes the menu which appears at boot time, another “Windows Boot Loader” describes the settings for the OS to boot and other sections can describe things like the RAMdisk windows Hyper-V boots from. If you run BCDEDIT /enum all from an elevated command prompt you can see what’s in it.

Windows 7 and Server R2 have some new bits in their boot loader to allow them to boot from a VHD file instead of a hard disk, and to the OSes themselves have some logic to cope with this. If you update the boot sector on a Windows Server 2008 or Vista machine (using BootSect in the boot folder of the Windows 7 / Server 2008 R2 install disk) you can make a machine which boots into Server 2008 (say) from the hard disk and Server 2008 from a VHD. No repartitioning disks or dealing with two sets of Windows on 1 partition. And that’s what I was running before.

It seemed like a good idea to re-create the entry in the BCD for my copied hard disk, so I deleted it and recreated a boot loader section.

BCDEDIT /copy {current} /D “Windows Server 2008 R2 RC on VHD”

This returns a GUID which you need to copy and use in two further commands: I got these wrong… not that I realized it.

While I was copying 10 gigs of VHD file to the second machine I finished the setup on the first enabling Hyper-V, Audio, the Windows Desktop experience, the PowerShell interactive environment and so on. Then it was time to boot machine 2. It failed. I tried fixing the BCD. No joy. It wasn’t clear to me if the problem was the BCD or VHD file so I copied the one I’d just finished configuring… which didn’t work either. I briefly made that machine totally unbootable by exporting the BCD from the working machine and importing it. BCDs aren’t portable, and it makes me think there is more information in there than you can see – so that it hooks the information up with the right disk. Fortunately I’d also exported the BCD I overwrote so I got back to where I had been. Over on the Virtualization blog my friend Mike Kolitz has a recent post about boot from VHD and wondering if I might something out of date or just wrong I checked the syntax he was using and it was completely different from mine. His went

bcdedit /set {GUID} osdevice  vhd=[locate]\folder\filename.vhd
bcdedit /set {GUID} device  vhd=[locate]\folder\filename.vhd

This worked. The Set command in BCD edit takes 3 parts, the identifier of the section, the name of the Value being set in that section, and what that value should be set to . So VHD=[locate] isn’t telling the command about a VHD parameter the = sign is literal text.
So I now I had a duplicate machine and to avoid problems with the domain I syspreped it, gave it a new name, set its IP address and joined it to the domain. All fine I tried to connect between the machines. No luck. I quickly eliminated the firewall as an issue, and both could talk to the domain controller, IP addresses were getting resolved. Time to check the arp cache. I can never remember the switches for arp.exe but it’s arp –a to dump out the cache (Oh yes a change from / to – for switches … I was already grinding my teeth missing the consistency and tab-expansion of switches the we have in Powershell). This led me to the discovery that I had duplicate MAC addresses on both machines – or strictly on both Virtual NICs which I had created in Hyper-V before duplicating the VHD. I’d ended up working at Machine 1 and deleting and recreating the network connection did no good at all. So, as if to prove that mistakes come in bunches, I set about re-installing machine 1. Had I thought about I would have reinstalled the copy, not the original. You see, when the MAC address is chosen for a virtual NIC it is based on the MAC address of the physical NIC (with the first few digits changed):  recreating the virtual network on Machine 2 fixed the problem.

This gave me a chance to test some other PowerShell I have been writing to configure the machine, and I thought I would try doing the whole configuration from the command line. This lead me into the new “Deployment Image Servicing and Management tool” DISM.EXE which deserves a week of blog posts by itself. Notice how command line uses a colon rather than a space to separate the name of a parameter from its value. 

DISM.exe /online /Enable-Feature /FeatureName:Microsoft-Hyper-V     
DISM.exe /online /Enable-Feature /FeatureName:Microsoft-Hyper-V-Management-Clients
installs Hyper-V itself, then the management tools and hey presto it doesn’t work …. what ? Installing these parts doesn’t tell the hypervisor to load at boot time, that needs an entry in BCDEdit.

bcdedit /set "{default}" hypervisorlaunchtype auto

OK I had hyper-v working. I had the components I wanted installed, I used some my PowerShell Library for Hyper-v  to set up the Virtual network and some other bits of Powershell that I’m getting ready to release to Set the IP address and patch the machine via windows update. PowerShell has a command to add a machine to a Domain so that was that taken care of – strangely there is no rename-machine, so that’s on my Powershell to-do list. The final step before creating my cluster was to hook up to ISCSI disks. I knew Dave Northey had posted about this so I copied the commands he used.

iscsicli QAddTargetPortal daven-2008
iscsicli QAddTarget iqn.1991-05.com.microsoft:daven-2008-daven-2008-target daven-2008
iscsicli QloginTarget iqn.1991-05.com.microsoft:daven-2008-daven-2008-target
iscsicli PersistentLoginTarget iqn.1991-05.com.microsoft:daven-2008-daven-2008-target T * * * * * * * * * * * * * * * 0
iscsicli BindPersistentVolumes
iscsicli ListPersistentTargets
iscsicli ReportTargetMappings

And the 4th one down really does have 17 parameters of which 15 are “*” Notice also how the commands don’t use / or – ; if nothing else I might wrap these up in PowerShell to make them easier to call.

I might drill a little deeper into the way these work for future posts, but right now I want to finish my PowerShell “Configurator” script which I referred to above. And I have a video in the works for uses of VHDs.