Testing and Validating Hyper-V VHD/VHDX Files

It is probably a safe bet that the VHD and VHDX files in a Hyper-V environment are incredibly important. If the file isn’t where you expect it to be or if there is a problem with it, Hyper-V won’t be very happy. Typically when a virtual machine is running if there is a problem with a disk file you’ll know right away. But perhaps you have a library of virtual machines that aren’t always online. It would be better to know ahead of time if there is a problem by testing your VHD and VHDX files.

Here are some techniques using the PowerShell cmdlets in the Hyper-V 3.0 module.

Getting VHD Paths

Finding the associated file paths with virtual machine is pretty simple. The virtual machine has a hard drives property which is a collection of hard drive objects.

PS C:> get-vm chi-win8 | select -expand harddrives

Or, you can use the Get-VMHardDiskDrive cmdlet.

PS C:> Get-VMHardDiskDrive chi-win8

This works even better when used in a pipelined expression.

PS C:> get-vm chi* | Get-VMHardDiskDrive

I could have gotten all virtual machines. You can see the path, but that is only the configuration. There is no way of knowing if the file even exists unless you start the virtual machine or test.

Testing Path

One test we can do is to use the Test-Path cmdlet. This is an easy way to verify a file or folder exists.

PS C:> test-path c:windows
True

To use with the Hyper-V cmdlets takes a little more because we need to get the Path property.

PS C:> Get-VMHardDiskDrive chi-fp01 | foreach { Test-path $_.path}
True
True
True

Or here’s a neat trick we can do in PowerShell 3.0.

PS C:> Test-Path (Get-VMHardDiskDrive chi-fp01).Path
True
True
True

The downside here is that if a file couldn’t be found PowerShell would return False, but I wouldn’t know which file failed. One solution is to simply add the test as a custom property.

PS C:> Get-VMHardDiskDrive chi-win8 | Select VMName,Controller*,DiskNumber,Path,@{Name="TestPath";Expression={$_ | Test-Path}}

This should work as well on multiple virtual machines and those with multiple drives.

PS C:> Get-VMHardDiskDrive chi-fp01,chi-dc01 | Select VMName,Controller*,DiskNumber,Path,@{Name="TestPath";Expression={$_ | Test-Path}}

Let’s check all of my virtual machines and see if there are any problems:

PS C:> Get-VMHardDiskDrive * | Select VMName,Controller*,DiskNumber,Path, @{Name="TestPath";Expression={$_ | Test-Path}} | where {-Not $_.TestPath}

Because of PowerShell’s object-based nature, this is a one-line command and now I can see where I have a problem.

Testing the VHD

But verifying the path is only half the battle. The file might exist but it might be corrupted or in the case of a differencing disk there may be an issue with the chain of disks. We can accomplish this with Test-VHD from the Hyper-V PowerShell module. It is as simple to use as this.

PS C:> Get-VMHardDiskDrive chi-win8 | test-vhd
True
PS C:> Get-VMHardDiskDrive chi-fp01 | test-vhd
True
True
True

If there is a failure PowerShell will tell you and display the error.

Like Test-Path it is hard to tell what file goes with the result unless there is a problem. So we can expand our earlier pipelined expression.

PS C:> Get-VMHardDiskDrive "SystemCenter Demo",chi-win8,"demo rig" | Select VMName,Controller*,DiskNumber,Path, @{Name="TestPath";Expression={$_ | Test-Path}},@{Name="TestVHD";Expression={$_ | Test-VHD }}

Or I can filter for test failures as I did before. If this is something I wanted to use often, I’d turn it into a PowerShell function.

#requires -version 3.0

Function Test-VHDIntegrity {

<#
.Synopsis
Test VHD files for integrity
.Description
Test the drive files for a Hyper-V virtual machine and verify the specified
file exists and that there are no problems with it.
.Example
PS C:> Get-VM | Test-VHDIntegrity | Out-Gridview
.Example
PS C:> Get-VM | Test-VHDIntegrity | where {(-NOT $_.TestPath) -OR (-NOT $_.TestVHD)}
.Link
Test-Path
Test-VHD
#>

[CmdletBinding()]

Param (
 [Parameter(Position=0,Mandatory,
 ValueFromPipelineByPropertyName,
 ValueFromPipeline)]
 [alias("vmname","name")]
 [ValidateNotNullorEmpty()]
 [object[]]$VM
)
Process {
#write-verbose ($vm | out-string)
    foreach ($item in $VM) {
      Write-Verbose "Analyzing disks for $item"
      <#
      I intentionally omitted parameter names for
      Get-VMHardDiskDrive so that it can detect if it
      is processing a string or a virtual machine
      #>
      Get-VMHardDiskDrive $item | 
      Select VMName,Controller*,DiskNumber,Path, 
      @{Name="TestPath";Expression={$_ | Test-Path}},
      @{Name="TestVHD";Expression={$_ | Test-VHD }} 
    } #foreach
}

} #end function

With this function loaded into my PowerShell session I can now run commands like this to identify problems:

PS C:> get-vm | Test-VHDIntegrity | where {(! $_.TestPath) -or (! $_.TestVHD)}

I retrieved all the virtual machines, and tested the drives with my function for each one, then I filtered out all the results except those where one of the tests failed. Now I can see which virtual machines I need to look at in more detail. As with all the PowerShell samples I post here, please review and test thoroughly in a non-production environment.

Summary

The health and integrity of your VHD and VHDX files are paramount in Hyper-V. With a little PowerShell it is easy to discover problems before they become major headaches. Of course, this is another scenario where having decent backups is critical so that if a file is found missing you can easily restore it.

 

Altaro Hyper-V Backup
Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!

3 thoughts on "Testing and Validating Hyper-V VHD/VHDX Files"

Leave a comment or ask a question

Your email address will not be published. Required fields are marked *

Your email address will not be published.

Notify me of follow-up replies via email

Yes, I would like to receive new blog posts by email

What is the color of grass?

Please note: If you’re not already a member on the Dojo Forums you will create a new account and receive an activation email.