Sydney XenDesktop Projects: Fast PVS driver updates

At Peninsula IT, the team in our Citrix technology consulting practice in Sydney are often engaged in projects involving Citrix Provisioning Services (PVS).  We think its an excellent and differentiated technology that provides significant performance, simplicity and single image management benefits to our customers in their XenApp and XenDesktop sites.

Updating PVS Target Device Software

One aspect of Citrix Provisioning Services that can make customers blood run cold is the idea of updating the PVS target device software (drivers) within the virtual disk image.  The really good news is that many customers are moving to the Citrix Long Term Service Release (LTSR) of the software, which at the time of writing, is PVS 7.6 update 1 (see the Citrix website here).  On this version, its simply a case of updating the target device software while the disk is in private image mode – see the Citrix website here, there is nothing complicated .  However, versions before PVS 7.6 update 1 require a few more special steps – the idea being that streamed disks could not have the streaming drivers updated on-the-fly.  There are a few ways these drivers can be updated – including reverse imaging the disk back to a non-streamed VM, or mounting the vhd / vhdx file onto an existing VM (in the case of hyper-V).  At Peninsula IT, we find in practice that these approaches are a bit clunky, require more staff co-ordination, and generally require a longer maintenance window, hence our preferred method is to copy the disk to the file system on an existing VM, and make it bootable by tweaking the boot loader before updating the drivers.  It sounds a bit complex, but in reality its not.

Using BCDEDIT to update the Provisioning Services drivers

Below are the steps we use for updating the Citrix Provisioning Services target device software on versions before PVS 7.6 update 1.

  1. Find an existing virtual machine (VM) on your hypervisor that was created by the same template as your PVS target servers.  Create a new one if needed.
  2. From the hypervisor console, add an extra disk to this VM.  Ensure that the new disk is larger than the PVS image VHD that you want to update.  From the Windows console, initialise and do a quick format on the new disk.
  3. Ensure that the PVS disk is a “merged base” from within the PVS console.
  4. Copy the vhd or vhdx file to be updated from the PVS servers Store to the new disk on the existing VM.  For this example we’ve copied it to the location E:\pvs-Win2016-soe.vhd
  5. From this point you need to be connected the the VM console and not via RDP.  Backup the boot loader on the VM by executing the following command from cmd.exe
bcdedit /export c:\boot-bcdbackup
  1. Create a new boot option for the GUI by copying the default item to allow booting from the PVS image disk by using this command. After this command is issued, find the GUID value in the output and copy it into notepad for use later
bcdedit /copy {default} /d "PVS vhd boot (E:)"
  1. Now link the VHD to the boot option by specifying the correct GUID copied from Step 6 above as follows (ie, replace the word guid below with the actual GUID you copied)
bcdedit /set {guid} device vhd=[E:]\pvs-Win2016-soe.vhd
bcdedit /set {guid} osdevice vhd=[E:]\pvs-Win2016-soe.vhd
  1. Now reboot the VM and select “PVS vhd boot (E:)” on the boot menu
  1. Once Windows has booted successfully, update the Hyper-V integration, Vmware or Xen tools first, and then update the PVS target device software. Restart the VM, choose the “PVS vhd boot (E:)” option again and make sure everything is ok before shutting down the machine.
  1. Start the VM again but this time choosing the default boot option, then rename and copy the updated VHD from the E: drive to the PVS server Store and test. The disk can then be imported into the Provisioning Services console and assigned to target devices
  2. If needed, we can cleanup the extra boot loader option on the VM by issuing this command with the GUID you saved to notepad in step 6:
bcdedit /delete {GUID} /cleanup

Thats it!