Hyper-V Script to move everything off of a physical disk

Hyper-V storage migration makes it very easy to move virtual machines wherever you need them, while they are running.  And in the past I have showed you how easy it is to use PowerShell to storage migrate all the virtual machines on your computer to a new location.

However, over the winter break I had a specific challenge.  I needed to services some of the storage arrays in my home configuration – and to do this I needed to empty specific physical disks of virtual machines.  I did not want to move all the virtual machines on the system – just the ones that were on the storage array that I was about to take offline.

To do this – I wrote the following script:

$sourcePath = "F:\"
$destinationPath = "D:\"
(Get-ChildItem $sourcePath -Recurse | ?{$_.Attributes -ne "Directory"}).count
Get-VM | %{
   $VM = $_
   # Check the configuration path
   $currentVMPath = $_.ConfigurationLocation
   if ($currentVMPath.StartsWith($sourcePath)) {
      $newVMPath = ($destinationPath) + ($currentVMPath.TrimStart($sourcePath))
      Move-VMStorage -VM $VM -VirtualMachinePath $newVMPath}
   # Check the snapshot path
   $currentSnapshotFilePath = $_.SnapshotFileLocation 
   if ($currentSnapshotFilePath.StartsWith($sourcePath)) {
      $newSnapshotFilePath = ($destinationPath) + ($currentSnapshotFilePath.TrimStart($sourcePath))
      Move-VMStorage -VM $VM -SnapshotFilePath $newSnapshotFilePath}
   # Check the smart paging file path
   $currentSmartPagingFilePath = $_.SmartPagingFilePath
   if ($currentSmartPagingFilePath.StartsWith($sourcePath)) {
      $newSmartPagingFilePath = ($destinationPath) + ($currentSmartPagingFilePath.TrimStart($sourcePath))
      Move-VMStorage -VM $VM -SmartPagingFilePath $newSmartPagingFilePath}
   # Go over each hard drive
   $_.HardDrives | %{
      # Check the hard drive
      $currentHardDrivePath = $_.Path
      if ($currentHardDrivePath.StartsWith($sourcePath)) {
         $newHardDrivePath = ($destinationPath) + ($currentHardDrivePath.TrimStart($sourcePath))
         Move-VMStorage -VM $VM -VHDs @(@{"SourceFilePath" = $currentHardDrivePath; "DestinationFilePath" = $newHardDrivePath})}
 (Get-ChildItem $sourcePath -Recurse | ?{$_.Attributes -ne "Directory"}).count

This goes through each virtual machine and checks the configuration path, checkpoint path, paging file path and virtual hard disks.  If it finds any component of the virtual machine on the disk that is about to be removed – it moves it to the new location.

Also, to help ensure that everything is going according to plan, it shows you how many files are present on the source disk before and after the script runs.  Assuming that you only have virtual machines on your source disk – it should report zero files remaining at the end of the script.