Recently, at a client site, I came across a less than ideal configuration for a Hyper-V environment. There were a few virtual servers configured with a 2TB virtual hard disk for the primary hard disk. This doesn’t sound like an issue because you could just split the disk up into a few volumes. I like to do a small volume for the OS and updates, another one for any applications and one for data. If I’m spinning up a VM, I like to do these as separate VHDs, but that’s another post.
In this case, the VMs were set up with Dynamically Expanding virtual hard disks in the VHD format. The VMs on the host had a total of 7TB of disk space provisioned on a host that only has 1.2TB of disk space. As those VHDs fill up, the host will run out of space, which will cause virtual machines to enter a paused state. To avoid this, I always do a fixed size VHD for a production virtual server. Working for a Managed Services Provider, you tend to see things that aren’t ideally configured. A lot of times we inherit environments from other providers who employed less qualified techs or one that was built by the owner’s friend or relative who “knows a lot about computers”. So, how do we go about fixing this?
Defragment the VHD
First thing we want to do is to defragment the VHD. Defragmenting it will move all the data to the beginning of the disk, allowing us to fully compact the disk. Some people say to run the defragment on the VM with the disk you’re trying to compact, but I like to mount the VHD on the host and defragment it there. Besides the next step will require the VHD to be mounted on the host.
As you can see in the image above, the VHD is mounted. Now we can defragment it using our favorite defragmenting utility. Be sure to optimize the drive as well since this will move all of the data to the beginning of the drive.
Shrink the Volume
Now that we defragmented the disk, we want to shrink the volume. Since we mounted the VHD, we can simply right click on the volume and select Shrink Volume. We don’t have to shrink it to the final size, but we want there to be enough unallocated space in order to shrink the disk itself. I like use the maximum amount of space to shrink in MB, minus 1000 MB.
In the above picture, the maximum amount of shrink space is already entered. In this case, I would change it to 2068539. This helps to prevent issues with free space being available and the shrink process failing.
Shrink the Disk
We are going to use PowerShell to shrink the disk. The cmdlet we are going to use is Resize-VHD. This cmdlet has two conditions that need to be met in order for it to work.
- The virtual hard disk you are shrinking needs to be in the VHDX format. You can use this cmdlet to expand a VHD.
- It’s only available on Windows 8 and Server 2012 or newer.
If you’ve been paying attention, you’ll remember that the virtual hard disk in this case is a VHD. We can’t use this cmdlet to shrink a VHD. Luckily, there is another cmdlet which will accomplish this for us. Convert-VHD will allow us to convert the VHD to a VHDX. For this to be successful, the disk needs to be offline.
I changed my working path in PowerShell to the location where the virtual hard disks are stored and ran the following cmdlet:
Convert-VHD –Path sourceDisk.vhd –DestinationPath convertedDisk.vhdx –VHDType Dynamic
Once that completes, I run the following cmdlet:
Resize-VHD –path convertedDisk.vhdx –SizeBytes 120GB
Keep in mind that it is best to run the Resize-VHD cmdlet from an elevated PowerShell session. After we resize the disk, we want to convert it to a fixed size. We can use the following cmdlet:
Convert-VHD –path convertedDisk.vhdx –DestinationPath –fixedDisk.vhdx –VHDType Fixed -DeleteSource
Add Disk to VM
It’s time to edit the settings of the VM to have it boot from the new VHDX. In Hyper-V manager, I simply change the hard disk to the new VHDX and start the system up.
Now, we can see that the drive for our virtual server is smaller. The final step here is to extend the volume to use that unallocated space. We can safely delete the original VHD file for the disk drive as it is not needed.
As you can see, it’s reasonably easy to correct this type of issue. If you have any questions or comments, please leave them below.