Relocating a Hyper-V VM Folder

In my Hyper-V setup, I had spaces in the VM names (what we see in the server manager), which by default, also added spaces in folder names where the VHD and the other VM files were stored. When I started using PowerShell to work with the VMs, I had to use quotes around VM names because of the spaces. After some time, I decided to rename the VMs to have the same name as the network names of the VM (the names that can be pinged), which had no spaces. This renaming appeared to be a simple task because there was a right-click > Rename option.

I renamed the VMs easily and got rid of the spaces in the names. However, the folder paths and the VHD names remained unchanged and continued to use the old names with spaces. While my original problem had been resolved, the discrepancy in the VM name and the file/folder names was a new annoyance to me even though I could have ignored it quite easily. If I rename a folder/file (portion of path), I essentially get a new path for the files/folders.

Now, there may be situations where I would actually want to move the VM files from one location to another. Suppose that the disk on which the VM files exist is getting filled up and I need to expand the disk for one of the VMs. In this case, I would like to relocate the files to another drive. In another situation, I might want to distribute my existing VMs to different physical disks to minimize the I/O contention as multiple VMs run concurrently. In both these cases, I need to move the files for an existing VM from one location to another.

There are probably other alternatives to the approach that I adopted. The steps described below just summarize what worked for me and may or may not work in other situations. The following steps accomplished this change for me:

  1. Shut down the VM
  2. Back up the VM folder.
  3. If there are any snapshots for the VM, delete the snapshots. This step may or may not be necessary, but I suspect that there must be references to the AVHD files which are likely to be broken by path changes.
    1. Wait for merge to complete (A merge is indicated by a “Cancel Merge in progress …” button in the Actions pane for the VM. A merge combines the VHD and AVHD files into one VHD file. After the merge is complete, the cancel button disappears and the AVHD files also disappear from the disk.
  4. Create the new VM folder, and move the VHD file to the new folder.
    1. Rename the VHD file now, if renaming the VHD is desired for any reason.
  5. In the Hyper-V manager, open settings for the VM.
    1. Under Hardware > IDE Controller x > Hard Drive, change the path of the VHD file by browsing to the new location/name of the VHD file.
    2. Under Management > Snapshot File Location, select the new path to the base VM folder. Carefully look at the path before changing it so as to keep it at the same level.
  6. Stop Hyper-V service in Windows Services.
  7. Move the remaining contents of the VM folder to the new location.
  8. Hyper-V internally tracks the location of the VM folder/files using symlinks stored in C:\ProgramData\Microsoft\Windows\Hyper-V. The link to the VM under consideration needs to be updated.
  9. Using Windows Explorer or Command line, do the following
    1. Find the symlink with its name matching the VM ID. It is a long ID with xml extension. It can be matched easily by looking at the file with identical name (as the symlink) in the VM folder.
    2. Move this link out of this folder as a backup.
    3. Remove the file with the same name from the cache folder – C:\ProgramData\Microsoft\Windows\Hyper-V\Virtual Machines Cache
  10. Start cmd (Run as Administrator), and run the following commands after inserting the correct VM ID and pathin the commands
    1. cd C:\ProgramData\Microsoft\Windows\Hyper-V\Virtual Machines
    2. mklink <VM_ID>.xml "<PATH_TO_VM_FOLDER>\Virtual Machines\<VM_ID>.xml"
      1. The output of this command looks like:
        symbolic link created for <VM_ID>.xml <<===>> <PATH_TO_VM_FOLDER>\Virtual Machines\<VM_ID>.xml
    3. Fix permissions on the symlink and the file using the following commands:
      1. icacls <VM_ID>.xml /grant "NT VIRTUAL MACHINE\<VM_ID>":F
      2. icacls <VM_ID>.xml /grant "NT VIRTUAL MACHINE\<VM_ID>":F /L
  11. Start the Hyper-V service
  12. If VM renaming is desired, rename the VM using right-click > Rename In Hyper-V Manager
  13. Start the VM
  14. Verify that everything is working normally.