Running the Microsoft ALM TFS 2013 (Hyper-V) Virtual Machine in VMWare without Persisting Changes

This blog describes how to run the Microsoft TFS/ALM Hyper-V virtual machine in one of the VMWare hypervisors (Player/Workstation/Fusion). You can use the same concepts for any other virtual machine/appliance.

The 2013 RTM ALM image comes with a set of TFS and Visual studio labs.  The virtual machine and the labs  have a couple expectations:
  1. It comes as a a Hyper-V VHD running an evaluation copy of Windows Server 2012.
  2. The work items and other information are "point in time" information.  This means sprint, iteration or other information can only be used in the labs if the VMs time is set to a specific date(s). 
  3. The machine resets the time to the same specific date and time on every reboot. This lets you re-run the exercises.  Pay attention to the places the way the time is set if you wish to use this process for Virtual Machines anchored at dates and times other than the ones used for the TFS 2013 RTM ALM image used in this post.
  4. The labs work best if the machine is restored back to its initial state after each lab.
We're going to run this virtual disk as a VMWare guest in a machine that automatically sets the Guest RTC to the correct time for the labs.  We will also restore the VM to its original state every time VMWare is re-launched.

VMWare Configuration

You can create a new virtual machine that uses the ALM virtual disk.  VMWare can consume the disk directly without conversion.  Configure the virtual machine but do not start it until you have manually edited the VMWare vmx file to set up the clock and disks snapshots.

  1. Create a directory to hold the virtual machine with some reasonable name. We will have VMWare use that directory for all its files later.
  2. Move the vhd virtual disk into the previously created directory.
  3. Run VMWare
  4. Create a new virtual machine
  5. Select Install System Later
  6. Select Microsoft Windows on the Guest operating screen. 
  7. Select the Windows version of Hyper-V (unsupported)
  8. Pick a location for the virtual machine.  Select the directory we created above
  9. Pick Store virtual disk as a single file.  We're not really going to use this disk. We're going to reconfigure the disks later to use the ALM VHD.
  10. Select Finish.  This should take you back to the screen that lists all the VMs including the one we just defined.
  11. Select the virtual machine and select Edit virtual machine settings
    1. Add a new IDE disk.  
    2. Select Use existing...
    3. Select the VHD
    4. Delete the old virtual disk.  We only need one disk and it should be the ALM disk
  12. Do not install VMWare tools
  13. Do not boot the machine
  14. Quit VMWare
Manually edit the VM configuration, vmx, file before booting the machine.

Manual Changes

Disabling Disk Persistence 

We want  the machine to roll back all session changes so that the VM always starts in exactly the same state.  We need to add 3 settings to the VMX file.  
ide0:0.mode = "independent-nonpersistent"
snapshot.action = "autoRevert"
snapshot.disabled = "TRUE"
We can remove the settings if we want to do some  work that we want to work across restarts. Be careful though. You often cant push time backwards if you've already done work on the current time.

Time at Startup.

The TFS 2013 RTM ALM VM resets its clock to 7/9/2013 1:30PM ever time it starts via a Task. This puts the machine in a known state and makes time based labs work.  Ex: Think iteration dates here. We want to be inside an iteration when using the sprint planning dashboards. 

You can have problem with this approach though.  A virtual machine's RTC is set to NOW when it boots up. This means the machine boots with the current time before it is reset by the startup tasks.  System or SQL changes can occur in thevirtual machine before the clock reset occurs creating timestamps later than 7/9/2013 1:30 PM. We need to set the virtual hardware clock before the operating system boots and reads the time.

The virtual RTC is used by the VM every time it runs. VMWare lets you set the virtual machine RTC at startup with a vmx setting. This web entry describes how we can set the VM time using the VM's virtual bios and RTC.

VMWare sets the RTC on the Unix Epoch. There are web sites that let you calculate the epoch time from a date and time that you enter. We want to choose an RTC time to just before the time that is set by the ALM vm on startup.  This insures that time moves only forward between bios boot, OS startup, SQL startup and task execution.

For this TFS 2013 RTM ALM virtual machine I have chosen 7/9/2013 1:30 AM which is earlier than,7/9/2013 1:30 PM, the ALM machine's OS will be set to after boot. 7/9/2013 1:30 AM maps to 1373334621 in Epoch Time. We add the following vmx entry based on that calculation:
rtc.starttime = "1373334621"
The time here is a unix style epoch time. There are web pages out there that can convert time between human readable and the Unix time format. The TFS 2012  and TFS 2013 RC ALM virtual machines used other dates so their rtc.startime should be set accordingly.  You can use this same reset process for other lab oriented virtual machines. 

Time Synchronization

VMWare has a set of tools that strive to synchronize time between the guest and the host. The Microsoft ALM Virtual Machine operates as if it is still July 2013 so we need to disable most of the Host/Guest time synchronization 
tools.syncTime = "FALSE"
time.synchronize.continue = "FALSE"
time.synchronize.restore = "FALSE"
time.synchronize.resume.disk = "FALSE"
time.synchronize.shrink = "FALSE"
time.synchronize.tools.startup = "FALSE"
time.synchronize.tools.enable = "FALSE"
time.synchronize.resume.host = "FALSE"
This document describes how VMWare manages time.

Sample VMX File

Here is my vmx configuration file that works with this service This VM described by this file operates on its own concept of time without syncing to any official time server. It also restores the C: drive disk on every restarts.

You can create completely new VM based the vmx describe below.

  1. Create a directory
  2. Put the vhd in the directory.
  3. Create a new vmx file, put it in the created directory and paste the contents from below into the file
  4. You should be able to now just double click on the vmx file to launch the ALM virtual machine.


.encoding = "windows-1252"
config.version = "8"
virtualHW.version = "10"
vcpu.hotadd = "TRUE"
scsi0.present = "TRUE"
scsi0.virtualDev = "lsisas1068"
sata0.present = "TRUE"
memsize = "4096"
mem.hotadd = "TRUE"
sata0:1.present = "TRUE"
sata0:1.autodetect = "TRUE"
sata0:1.deviceType = "cdrom-raw"
ethernet0.present = "TRUE"
ethernet0.connectionType = "nat"
ethernet0.virtualDev = "e1000"
ethernet0.wakeOnPcktRcv = "FALSE"
ethernet0.addressType = "generated"
usb.present = "TRUE"
ehci.present = "TRUE"
ehci.pciSlotNumber = "35"
usb_xhci.present = "TRUE"
sound.present = "TRUE"
sound.virtualDev = "hdaudio"
sound.fileName = "-1"
sound.autodetect = "TRUE"
serial0.present = "TRUE"
serial0.fileType = "thinprint"
pciBridge0.present = "TRUE"
pciBridge4.present = "TRUE"
pciBridge4.virtualDev = "pcieRootPort"
pciBridge4.functions = "8"
pciBridge5.present = "TRUE"
pciBridge5.virtualDev = "pcieRootPort"
pciBridge5.functions = "8"
pciBridge6.present = "TRUE"
pciBridge6.virtualDev = "pcieRootPort"
pciBridge6.functions = "8"
pciBridge7.present = "TRUE"
pciBridge7.virtualDev = "pcieRootPort"
pciBridge7.functions = "8"
vmci0.present = "TRUE"
hpet0.present = "TRUE"
usb.vbluetooth.startConnected = "TRUE"
displayName = "2013 ALM Hyper-V (unsupported)"
guestOS = "winhyperv"
nvram = "2013 ALM Hyper-V (unsupported).nvram"
virtualHW.productCompatibility = "hosted"
gui.exitOnCLIHLT = "FALSE"
powerType.powerOff = "soft"
powerType.powerOn = "soft"
powerType.suspend = "soft"
powerType.reset = "soft"
extendedConfigFile = "2013 ALM Hyper-V (unsupported).vmxf"
ide0:0.present = "TRUE"
ide0:0.fileName = "TD02WS12SFx64.vhd"
scsi0:0.present = "FALSE"
floppy0.present = "FALSE"
uuid.bios = "56 4d 6b 23 25 1b 6f 2d-b7 ca e8 22 47 3b ad a3"
uuid.location = "56 4d 6b 23 25 1b 6f 2d-b7 ca e8 22 47 3b ad a3"
replay.supported = "FALSE"
replay.filename = ""
ide0:0.redo = ""
pciBridge0.pciSlotNumber = "17"
pciBridge4.pciSlotNumber = "21"
pciBridge5.pciSlotNumber = "22"
pciBridge6.pciSlotNumber = "23"
pciBridge7.pciSlotNumber = "24"
scsi0.pciSlotNumber = "160"
usb.pciSlotNumber = "32"
ethernet0.pciSlotNumber = "33"
sound.pciSlotNumber = "34"
usb_xhci.pciSlotNumber = "192"
vmci0.pciSlotNumber = "36"
sata0.pciSlotNumber = "37"
scsi0.sasWWID = "50 05 05 63 25 1b 6f 20"
ethernet0.generatedAddress = "00:0c:29:3b:ad:a3"
ethernet0.generatedAddressOffset = "0"
vmci0.id = "1195093411"
vmotion.checkpointFBSize = "33554432"
cleanShutdown = "TRUE"
softPowerOff = "TRUE"
usb_xhci:1.speed = "2"
usb_xhci:1.present = "TRUE"
usb_xhci:1.deviceType = "hub"
usb_xhci:1.port = "1"
usb_xhci:1.parent = "-1"
usb_xhci:3.speed = "4"
usb_xhci:3.present = "TRUE"
usb_xhci:3.deviceType = "hub"
usb_xhci:3.port = "3"
usb_xhci:3.parent = "-1"
toolsInstallManager.updateCounter = "8"
sata0:1.startConnected = "FALSE"
unity.wasCapable = "FALSE"
tools.remindInstall = "TRUE"

ide0:0.mode = "independent-nonpersistent"
snapshot.action = "autoRevert"
snapshot.disabled = "TRUE"

rtc.starttime = "1373362200"
tools.syncTime = "FALSE"
time.synchronize.continue = "FALSE"
time.synchronize.restore = "FALSE"
time.synchronize.resume.disk = "FALSE"
time.synchronize.shrink = "FALSE"
time.synchronize.tools.startup = "FALSE"
time.synchronize.tools.enable = "FALSE"
time.synchronize.resume.host = "FALSE"

usb_xhci:4.present = "TRUE"
usb_xhci:4.deviceType = "hid"
usb_xhci:4.port = "0"
usb_xhci:4.parent = "1"

Conclusion

You can use these techniques to create/manage Virtual Machines that need to restore back to the previous state on every restart.  You can configure these same machines to put the hardware back at that same or other times.

Last edited 12/29/2013

Comments

Popular posts from this blog

Understanding your WSL2 RAM and swap - Changing the default 50%-25%

Installing the RNDIS driver on Windows 11 to use USB Raspberry Pi as network attached

DNS for Azure Point to Site (P2S) VPN - getting the internal IPs