Hyper-V’s snapshot feature is a double-edged sword. It’s a convenient method to make a quick backups of a machine state prior to certain activities. However, the presence of check-points would sometimes interfere with the VM’s migration (under certain conditions) and restoration (via means other than using checkpoints). Therefore, it’s necessary for Admins to perform systems maintenance by removing Hyper-V snapshots from all guest VM’s on a regular basis, especially if there are enterprise backup systems already available to serve the purpose of business continuity.

# purgeVmSnapshots.ps1

$vmNames='testwindows'
$snapshotlabel='testsnapshot'

function purgeVmSnapshots([string[]]$vmName,[string]$snapshotLabel){
    # Usage:
    # a. purgeVmSnapshots $vmNames $snapShotLabel # This is to remove specific snapshot by a label
    # b. purgeVmSnapshots $vmNames # This will purse all snapshots matching VM names

    $vmClusterNodes=Get-ClusterGroup|?{$_.GroupType -eq 'VirtualMachine'}
    $results=[System.Collections.ArrayList]::new()
    foreach ($vm in $vmName){
        $ownerNode=($vmClusterNodes|?{$vm -eq $_.Name}).OwnerNode
        if($ownerNode.State -eq 'Up'){
            $removeSnapShotCommand={
                param($vm,$snapShotLabel)
                try{
                    if($snapShotLabel){
                        Remove-VMSnapshot -VMName $vm -Name $snapShotLabel -ea Stop
                    }else{
                        Remove-VMSnapshot -VMName $vm -ea Stop
                        }
                    return $true
                }catch{
                    Write-Error $_
                    return $false
                    }
                }
            $isSnapshotRemoved=invoke-command -ComputerName $ownerNode.Name -ScriptBlock $removeSnapShotCommand -Args $vm,$snapShotLabel
            $results+=[pscustomobject]@{'vmName'=$vm;'ownerNode'=$ownerNode.Name;'snapShotRemoved'=$isSnapshotRemoved}
        }elseif($ownerNode){
            write-warning "$vm is currently owned by DOWNED node $($ownerNode.Name). No snapshots can be taken for such guest VM."
            $results+=[pscustomobject]@{'vmName'=$vm;'ownerNode'=$ownerNode.Name;'snapShotRemoved'=$false}
        }else{
            write-warning "$vm is does not match any Hyper-V Host in this cluster $((get-cluster).Name)"
            $results+=[pscustomobject]@{'vmName'=$vm;'ownerNode'='None';'snapShotRemoved'=$false}
            }
    }
    return $results
}

#Checkpoint-VM -vmName $vmNames -SnapshotName $snapShotLabel
purgeVmSnapshots $vmNames $snapShotLabel