Tips & Tricks from Our CTO: Converting VHDX TO VHD


I recently had a need to use a vendor’s virtual appliance in my lab.  Unfortunately, the vendor only supported VMware vSphere and Microsoft Hyper-V, and I’m running Citrix XenServer.  For this activity, I thought I’d try pulling the Hyper-V appliance into XenServer.

After extracting the appliance archive, I found that the virtual disk format was VHDX.  XenServer doesn’t support VHDX at this point in time, so I needed to get it into a format that XenServer DID support; namely VHD.  Did some looking around and found various tools that didn’t quite fit.  There’s the Convert-VHD command in the Hyper-V management suite, but you have to have Hyper-V installed in order to use it.  VHDtool only supports VHD files, not VHDX.  VHDXtool only supports upgrading from VHD to VHDX, and not the other way around.  Disk2vhd only supports using physical source disks.

So after all that investigation, I came up with a rather simple way of accomplishing the task.  In recent versions of Windows, you can create and mount both VHD and VHDX files.  Past the container abstraction, the data presented within either should be identical.  So I mounted the VHDX file as read-only, created and connected a new dynamic VHD file and used dd to copy the CONTENTS from one container to the other.  It worked out really well and did allow the VM to boot.

Note: The booting process for operating systems can be a complicated thing.  I was successful in moving a virtual machine that used MBR, but unsuccessful with another that used GPT.  Newer versions of Hyper-V have the ability to use Secure Boot, which may have gotten in my way.  This process WILL copy the contents of a VHDX file to a VHD file, but it does not ensure that it will boot properly.  This article does not go into troubleshooting the boot process after the transfer is made.  If anyone has good, reliable information on troubleshooting or modifying the boot process (GPT, Secure Boot, etc.) please contact our team at and I’ll update with a list of resources.

Here are the steps:

  • Open Disk Management (in Computer Management)

    • Attach source VHDX file
      • Action (menu) > Attach VHD

          • Location: Location of the VHDX file
          • Read Only: checked
  • Determine if the disk uses MBR or GPT
    • Open CMD as Administrator
      • Type diskpart
        • Type list disk
          DISKPART> list disk
            Disk ###  Status         Size     Free     Dyn  Gpt
            --------  -------------  -------  -------  ---  ---
            Disk 0    Online           50 GB      0 B
            Disk 1    Online           50 GB      0 B        *

          The asterisk in the Gpt column denotes that GPT is used.  So for this example, Disk 0 uses MBR, while Disk 1 uses GPT.

  • Create and attach the target VHD file
    • Action (menu) > Create VHD
      • Location: location for the new VHD file
      • Size: the size of the virtual disk
      • VHD: selected
      • Dynamically expanding: selected
    • Initialize disk
      • In the lower-right Disk Management pane, you should see a disk with all Unallocated space. To the right, it should say Not Initialized. Right-click where it says, “Not Initialized” and select Initialize Disk.

        • Make sure the same partition style as the source disk uses is selected and click OK
    • Now, LEAVE THE DISK MANAGEMENT WINDOW ALONE. If the contents are refreshed during the following process, Windows will recognize that there are duplicate signatures on two of your disks and offline the target disk.
  • Next, you need to use the Linux dd and sha1sum commands within Windows. There are a few ways to accomplish this, but I find an easy one to be to use MobaXterm, and therefore the following instructions use that.  You could use Cygwin (which is what MobaXterm implements) or a Windows port of dd if you’d like.
  • Launch MobaXterm AS ADMINISTRATOR
    • Click the Start Local Terminal button
      Note: the following commands expect that you’ll have a single boot drive on the system, the second drive would be your source and the third drive would be your target. Change the commands to accommodate your actual environment.

      • First, find out what disks your system sees. sda is the boot drive, sdb is my source drive with 5 partitions, and sdc is my target drive.
        [host] ➤ ls /dev/sd*
        sda   sda1  sda2  sdb   sdb1  sdb2  sdb3  sdb4  sdb5  sdc
      • Next, use dd to copy the entire contents of the source disk to the target disk. This takes a long time, so be patient.
        [host] ➤ dd if=/dev/sdb of=/dev/sdc bs=4k
        7864320+0 records in
        7864320+0 records out
        32212254720 bytes (30.0GB) copied, 1987.146259 seconds, 15.5MB/s
      • Lastly, validate that the two disks are identical.
        [host] ➤ sha1sum /dev/sdb && sha1sum /dev/sdc
        3256bc67f1a4a5ab15166f1fe23b877609a5e1c4 /dev/sdb
        3256bc67f1a4a5ab15166f1fe23b877609a5e1c4  /dev/sdc
  • NOW, switch back to the Disk Management window:
    • Detach target and source virtual disks:
      • Right-click target disk -> Offline

        • Error: the media is write-protected -> OK
          When you selected Offline, Windows looked at the disk signatures, found the duplicate and set the disk to offline. So this error is somewhat expected.
    • Right-click target disk -> Detach VHD
    • Right-click source disk -> Offline
    • Right-click source disk -> Detach VHD
  • Attach target virtual disk just to validate that the partitioning looks correct:
    • Action (menu) > Attach VHD
      • Location: Location of the VHD file
      • Read Only: checked
    • Validate that you see partitions and that connects properly.
    • Detach target virtual disk:
      • Right-click target disk -> Offline
      • Right-click target disk -> Detach VHD
    • Copy the VHD to XenServer
      For this activity, you need to have an NFS storage repository for XenServer. If not using MobaXterm, you can use most any scp or sftp tools, as long as they support large file transfer (many old tools have file size limits).

      • In MobaXterm, select Open New Tab from the Terminal menu
      • ssh to the XenServer node: ssh root@<host>
        MobaXterm automatically creates an sftp session in the left pane when you connect via SSH in the terminal window.
      • In the left pane, navigate to the storage repository you want to copy the VHD to. In newer versions of XenServer you’ll find this in /run/sr-mount, while (if memory serves) you’ll find it in /var/run/sr-mount in older versions. The xe sr-list command will give you the relationship between the SR name and UUID.
        # xe sr-list params=uuid,name-label
        uuid ( RO)          : 8e059c11-487e-a3e4-27fd-6b9d351a215c
        name-label ( RW): ISO library
        uuid ( RO)          : f552634a-1fd8-324a-df0e-a099b869c14d
        name-label ( RW): DVD drives
        uuid ( RO)          : abd713d8-6141-eda8-d8bc-ebfc49b3d1a6
        name-label ( RW): XenServer Tools
        uuid ( RO)          : bbf2b544-d1c6-f743-50b7-49e792868efe
        name-label ( RW): Local storage
        uuid ( RO)          : c068494b-ff55-1181-397a-6118db0fc653
        name-label ( RW): RAIN NFS
        uuid ( RO)          : ccb26834-2c5a-b554-0715-e045eae685b4
        name-label ( RW): Local Storage - SSD
        uuid ( RO)          : 0e8947e6-6799-401b-edb6-0a39db8e7954
        name-label ( RW): Local storage
        uuid ( RO)          : 354d3c1d-c729-010a-0b26-a77d78d2f764
        name-label ( RW): QS_3PAR_SSD_NFS
    • In the left pane, just under the Quick Connect field, click the “Upload to current folder” toolbar button, select the VHD file and click the Open button.
    • Once the upload is completed (progress bar is at the bottom of the sftp pane) complete the following in the ssh session, changing parameters and uuids to suite your use case:
      [host pwd]# cd /run/sr-mount/<sr-uuid>
      [host pwd]# xe vdi-create sr-uuid=<sr-uuid> type=user name-label=<name> virtual-size=<size>GiB 80f2c4db-5437-4680-a8db-2d11c58d14ff
      [host pwd]# mv 80f2c4db-5437-4680-a8db-2d11c58d14ff.vhd 80f2c4db-5437-4680-a8db-2d11c58d14ff.vhd.bak
      [host pwd]# mv <filename>.vhd 80f2c4db-5437-4680-a8db-2d11c58d14ff.vhd

  • Create the VM
    • In XenCenter create a new VM with the “Other install media” template
      • Select “Boot from network”
    • Before booting the VM:
      • In the Boot Options section of the VM’s properties, change the boot order so Network is below Hard Disk
      • Add the virtual disk to the VM in the VM’s storage tab
    • Power on the VM

Hopefully, you’ll find this process to be painless.  With respect to the Disk Management signatures, Mark Russinovich wrote a fantastic blog about Fixing Disk Signature Collisions which explains why VHD conversions sometimes have booting problems.  Hopefully, you won’t need it, but you have it if you do!