Manage Hyper-V Snapshots
Show me all your snapshots
We have a cluster with a bunch of VMs. Let’s say around 300 .
Some actions require us to take a snapshot of certain VMs and then remove them after we’re sure everything is ok.
We are using VeeamOne to track this, but it’s goot do have good old PowerShell take care of the task itself.
There are 3 snippets here I’m using very often:
- create new snapshot with a certain name for selected VMs
- find all VMs with snapshots of certain name (i.e. ‘SystemUpdate’)
- remove all snapshots of certain name from selected VMs
This code also can be used to target single Hyper-V instances and use different Credentials. Also some Hyper-V nodes may be in maintenance mode so first let’s check which of those are available.
$HyperVHost = 'ClusterName' #clustername 'ClusterName' or hostname 'HyperVHost'
$Cluster = $true #true if cluster is targeted
#$Credential = Get-Credential #Optional
$connProperties = @{
ComputerName = $HyperVHost
}
if ($Credential) {
$connProperties.Credential = $Credential
}
if ($Cluster) {
$Nodes = Invoke-Command @connProperties -ScriptBlock {
Get-ClusterNode | where-object { $_.State -eq 'Up' } | select-object -ExpandProperty Name
}
$connProperties.ComputerName = $Nodes
}
Create Snapshots
Once I have all active
nodes I can query them for VMs and process only specific ones to create snapshot SystemUpdate
:
$SnapshotName = 'SystemUpdate'
$VMsToProcess = @(
'VMName1',
'VMName2'
)
Invoke-Command @connProperties -ScriptBlock {
$VMs = Get-VM
foreach ($VM in $VMs) {
if($VM.VMName -in $USING:VMsToProcess) {
Write-Host "Processing VM {$($VM.Name)} on Host {$($ENV:COMPUTERNAME)}"
Checkpoint-VM -VM $VM -SnapshotName $USING:SnapshotName
}
}
}
Find Snapshots
If I need to find all VMs with a snapshot of a name ‘SystemUpdate’ here’s the code:
$SnapshotName = 'SystemUpdate'
$VMs = Invoke-Command @connProperties -ScriptBlock {
Get-VM | Get-VMSnapshot -Name $USING:SnapshotName -ErrorAction SilentlyContinue
}
$VMsToProcess = $VMs | Out-GridView -passThru
I’ll get a window where I can select specific VMs to process. Also I’ll see whether there is a parent snapshot present:
Remove Snapshots
Now let’s merge those snapshots:
foreach ($process in $VMsToProcess) {
$connProperties.ComputerName = $process.PSComputerName
Invoke-Command @connProperties -ScriptBlock {
Write-Host "Processing $($USING:process.VMName) on host $($env:COMPUTERNAME)"
Get-VM $USING:process.VMName | Get-VMSnapshot -Name $USING:SnapshotName | Remove-VMSnapshot -Verbose
}
}
Full Code
Here are full snippets for given tasks
Create Snapshots - Full Code
$HyperVHost = 'ClusterName' #clustername 'ClusterName' or hostname 'HyperVHost'
$Cluster = $true #true if cluster is targeted
#$Credential = Get-Credential #Optional
$connProperties = @{
ComputerName = $HyperVHost
}
if ($Credential) {
$connProperties.Credential = $Credential
}
if ($Cluster) {
$Nodes = Invoke-Command @connProperties -ScriptBlock {
Get-ClusterNode | where-object { $_.State -eq 'Up' } | select-object -ExpandProperty Name
}
$connProperties.ComputerName = $Nodes
}
$SnapshotName = 'SystemUpdate'
$VMsToProcess = @(
'VMName1',
'VMName2'
)
Invoke-Command @connProperties -ScriptBlock {
$VMs = Get-VM
foreach ($VM in $VMs) {
if($VM.VMName -in $USING:VMsToProcess) {
Write-Host "Processing VM {$($VM.Name)} on Host {$($ENV:COMPUTERNAME)}"
Checkpoint-VM -VM $vM -SnapshotName $USING:SnapshotName
}
}
}
Find Snapshots - Full Code
$HyperVHost = 'ClusterName' #clustername 'ClusterName' or hostname 'HyperVHost'
$Cluster = $true #true if cluster is targeted
#$Credential = Get-Credential #Optional
$connProperties = @{
ComputerName = $HyperVHost
}
if ($Credential) {
$connProperties.Credential = $Credential
}
if ($Cluster) {
$Nodes = Invoke-Command @connProperties -ScriptBlock {
Get-ClusterNode | where-object { $_.State -eq 'Up' } | select-object -ExpandProperty Name
}
$connProperties.ComputerName = $Nodes
}
$SnapshotName = 'SystemUpdate'
$VMs = Invoke-Command @connProperties -ScriptBlock {
Get-VM | Get-VMSnapshot -Name $USING:SnapshotName -ErrorAction SilentlyContinue
}
$VMsToProcess = $VMs | Out-GridView -passThru
Remove Snapshots - Full Code
$HyperVHost = 'ClusterName' #clustername 'ClusterName' or hostname 'HyperVHost'
$Cluster = $true #true if cluster is targeted
#$Credential = Get-Credential #Optional
$connProperties = @{
ComputerName = $HyperVHost
}
if ($Credential) {
$connProperties.Credential = $Credential
}
if ($Cluster) {
$Nodes = Invoke-Command @connProperties -ScriptBlock {
Get-ClusterNode | where-object { $_.State -eq 'Up' } | select-object -ExpandProperty Name
}
$connProperties.ComputerName = $Nodes
}
$SnapshotName = 'SystemUpdate'
$VMs = Invoke-Command @connProperties -ScriptBlock {
Get-VM | Get-VMSnapshot -Name $USING:SnapshotName -ErrorAction SilentlyContinue
}
$VMsToProcess = $VMs | Out-GridView -passThru
foreach ($process in $VMsToProcess) {
$connProperties.ComputerName = $process.PSComputerName
Invoke-Command @connProperties -ScriptBlock {
Write-Host "Processing $($USING:process.VMName) on host $($env:COMPUTERNAME)"
Get-VM $USING:process.VMName | Get-VMSnapshot -Name $USING:SnapshotName | Remove-VMSnapshot -Verbose
}
}
Summary
These three little snippets saves me time whether I’m running a demo lab on my private host, test hosts or production ones.
Leave a comment