In Windows Hyper-V 2012, Move-VMStorage leaves folders behind

I have tested a bit with the WinServ first in the early version 8 and then RC and now RTM, and what I thought was a bug that MS would fix before RTM seems to be still there.

What am I talking about then, well when you do a live or cold storage migration of a VM from for example your local storage to a SMB share either with the gui or preferebly with PowerShell, the built-in function leaves folders behind. And you can see where this is leading when moving a lot of VM´s, several VM´s folders retain with nothing inside and causing confusion!

As you can see on the screendump, the VM 2012 has been moved to another place but the folder still resides with no data in it, the subfolders are there but no disk files. And of course if I use the parameter -RetainVhdCopiesOnSource the folders should stay and also the configuration, vhd files 🙂

So I have done a modified Move-VMStorage function that actually removes the source folder also after moving the VM.

Here is the powershell function and a screendump how it actually deletes the folder also, And as you can see, I check if the VM resides on a share or locally on a hyper-v host and then I use Invoke-Command to delete the folder on the host´s local volume. The script can run on any machine that has RSAT-Hyper-V Powershell tools installed and with an account that has rights to delete folders on the shares/hosts.

<#
.Synopsis
   An updated Move-VMStorage function
.DESCRIPTION
   To also remove the folder where the VM was residing this function also deletes the folder after moving the VM
.EXAMPLE
   Move-VMStorage2 -VM test -ComputerName HV02 -Path \\SMB-srv01\VMs\test
.NOTES
Author: Niklas Akerlund 20120926
#>
function Move-VMStorage2
{
    [CmdletBinding()]
    [OutputType([int])]
    Param
    (
        # A name of a VM or a VM object
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $VM,
        # The name of the Hyper-V host
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $ComputerName,
        # The path where the VM is going to be relocated to.
        [string]
        $Path
    )

        # Lets move and tidy the source folder
        $VM = Get-VM $VM -ComputerName $ComputerName
        Move-VMStorage -VM $VM -DestinationStoragePath $Path
        $VMOldPath = $VM.Path
        if ($VMOldPath.StartsWith("\\")) {
           Remove-Item -Path $VMOldPath -Recurse -Force
        }else{
            Invoke-Command -ComputerName $VM.ComputerName -ScriptBlock {Remove-Item -Path $Using:VMOldPath -Recurse -Force}
        }
        
}

Make sure that you always add the VM´s name to the path otherwise you will put the VM´s folders and files in the SMB folder directly and that will cause a mess and when you run my function it will try to clean that folder and all subfolders wich means all VM´s not running in that folder. Maybe I will add the control that It checks that the path to delete includes the VM name in a future update 😛

Comments

Flo
Reply

Hey!

Nice work – but I’m too noob to get it running, I’v downloaded your script from http://gallery.technet.microsoft.com/scriptcenter/modified-Move-VMStorage-6d4e0da5#content and executed it. PS always tells me:

PS C:\> Move-VMStorage2
Move-VMStorage2 : The term ‘Move-VMStorage2’ is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
again.
At line:1 char:1
+ Move-VMStorage2
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Move-VMStorage2:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Any idea? Thx!

Niklas
Reply

Hi, You will have to load the function first so if you download the script and then run “. .\move-vmstorage.ps1” and then you will be able to run the Move-VMStorage2 @Flo