Hyper-V On-The-Go – Reclaiming Drive Space

Continuing in our “Boldly Going” series I wanted to touch on a minor issue I’ve had when working with certain Hyper-V features. One of those endearing features/qualities is found when you want to delete a VM.

Try this out in your environment on an expendable VM. Open your Hyper-V console, select the VM and choose delete:

Notice that Hyper-V prompts you with an ‘Are you sure?’ window:

Machine generated alternative text:
Delete Selected Virtual Machines 
Are you sure you want to delete all of the 
selected virtual machines? 
x 
[3 Please don't ask me again 
Del 
Don't Delete

Now given that prompting, you’d think, Hey! This sounds downright permanent. I’d better think hard about this before I go off willy-nilly and delete this VM or I may never get it back!.

Not so my trusty red-shirted friend!

Microsoft loves you and wants to make sure that you know what the heck you’re doing, or put another way, they are just trying to protect you from you.

By default, Hyper-V will delete the machine from its inventory but it will not delete the disc image (vhd/vhdx) file(s). This is actually a good thing because you can recover your VM from the image but, as with all good things, sometimes they just get in the way of of trying to just get things done quickly.

This is where our handy functions come into play.
As always when managing Hyper-V infrastructure, be sure to open your PowerShell session in an elevated context.

Here is the code for our two functions:

function Remove-LabVMs ($txtMatch)
{
    # Remove Lab VMs
        if ($txtMatch -eq $null)
        {
            Write-host "No VM Name was supplied. Delete ALL VMs?" -foregroundcolor Yellow 
            [ValidateSet('y','n')]$Readhost = Read-Host " ( y / n ) " 
            if ($ReadHost -ne 'y') { Exit }
        }
        $labVMs = Get-VM | Where-Object { $_.Name -match $txtMatch }
        $trgDrives = $labVMs.HardDrives.Path
        $labVMs | Remove-VM -Force
        $trgDrives | Remove-Item -Force -Verbose
}

Useless Note: I was going to name it Kill-LabVMs but it would not have met the Verb-Noun naming requirements and apparently ‘Kill” comes with some heavily negative connotations of its own.

    function Set-LabVMState
    {
        # Power On/Off Lab
        Param
        (
            [ValidateSet('Start','Stop','Restart','Resume','Suspend')]
            $vmOption,
            $txtMatch
        )
        if ($txtMatch -eq $null)
        {
            Write-host "No VM Name was supplied. Stop ALL VMs?" -foregroundcolor Yellow 
            [ValidateSet('y','n')]$Readhost = Read-Host " ( y / n ) " 
            if ($ReadHost -ne 'y') { Exit }
        }
        $vmAction = $vmOption + '-VM'
        $labVMs = Get-VM | ?{ $_.Name -match $txtMatch }
        $labVMs | & $vmAction -Verbose
    }

These functions will allow for:

  1. The attempt to Power-Off the specified VMs in your lab.1
  2. The immediate removal of the specified VMs in your lab.
1:Important; the VM(s) must be in a powered-off state to be removed.

When executed, the Remove-LabVMs completes four actions:

  1. Loads the selected VMs into memory.
  2. Identifies the vhd(x) file for each VM.
  3. Removes each VM from the inventory (in Hyper-V).
  4. Deletes the vhd(x) file for each VM.

Need to delete the entire lab?
No problem! Just run the function without parameters:
Remove-LabVMs
You will be prompted to verify deleting all your VMs.

This image has an empty alt attribute; its file name is 3-2.png

Need to delete a specific VM? Easy Peazy! Just run the function like so:
Remove-LabVMs -txtMatch ‘^app.’

This will target any VM name starting with APP.. Remember the function is using the Match operator to find VMs so regex is allowed. The ^ symbol indicates to start matching at the beginning of the string, so this search will find (and delete) any VM name beginning with APP..

Need to shutdown AND delete the entire lab?
 Combine the functions like so:

Set-LabVMState -vmOption Stop; Remove-LabVMs

Note: If the Set-LabVMState function fails to shut a VM down successfully, the Remove-LabVMs function will not be able to delete it and errors will result. I have seen this failure on VMs running as domain controllers. Below is an example of the errors returned attempting to delete a running VM:

I spend a lot of time working in Hyper-V so it behooved me to add these functions to my $Profile. This way I don’t need to go digging for them when I need them.

That pretty much covers what I wanted to cover in this topic so I will wrap it up here.

I will cover Profile tricks in another blog, but until then “Lab long and prosper!“.

More Blogs in the ‘Boldly Going” Series

  1. Hardware Considerations for Portable Labs
  2. Enabling the Hyper-V Engine
  3. Reclaiming Drivespace
  4. Sending Files to Your VMs (Part 1)
  5. Sending Files to Your VMs (Part 2)
  6. Sending Files to Your VMs (Part 3)
  7. Changing the Lab VM State

Authors