Table of Content
- Basic information
- Shutdown virtual machine
- Wait until virtual machine is off
- Creating the snapshot
- Removing the old snapshots
- Starting the virtual machine
- The complete script
In this blogpost I will share a script to automate Hyper-V VM snapshots with PowerShell. My goal of this script is to properly shutdown the virtual machine and create a snapshot and maintain the configured amount of snapshots based on day’s. This way I can reduce storage and it is possible to revert to a specific snapshot if the machine has broken down.
Basic information
We need some basic information that is stored in three variables. These variables contains the Hyper-V host name, the virtual machine name listed on the host and the amount of snapshots you want to maintain based on day’s.
$VirtualMachine = "My-VM" $HyperVHost = "HVhost.lab.local" $SnapshotDays = 10
Note: The virtual machine name can be listed by running this Powershell command Get-VM -CompterName $HyperVHost or just check in the Hyper-V Manager.
Shutdown virtual machine
in the first section we want to make sure the virtual machine is off. This is done by the Stop-VM which initiates a proper shutdown. Before we provide the command we first check if the virtual machine is running.
# Get VM information $VM = Get-VM -ComputerName $HyperVHost -Name $VirtualMachine # Provide shutdown command IF ($VM.State -ne "Off") { Write-Host (Get-Date)": Shutdown $VirtualMachine" Stop-VM -ComputerName $HyperVHost -Name $VirtualMachine }
Wait until virtual machine is off
The next step is to wait until the virtual machine is off and that is done by the following loop.
# Wait until VM is off Write-Host (Get-Date)": Waiting for $VirtualMachine to be Off" While ((Get-VM -ComputerName $HyperVHost -Name $VirtualMachine).State -ne "Off") { Write-Host "." -NoNewLine Start-Sleep -Seconds 5 } Write-Host " " Write-Host (Get-Date)": $VirtualMachine is Off"
Creating the snapshot
When the virtual machine is off the snapshot is taken. The format I used is the name of the virtual machine with the date of the taken snapshot.
Write-Host (Get-Date)": Creating snapshot of $VirtualMachine" $DateFormat = Get-Date -Format yyyy.MM.dd $Snapshot = $VM.Name + "-" + $DateFormat CheckPoint-VM -ComputerName $HyperVHost -Name $VirtualMachine -Snapshotname $Snapshot Start-Sleep -Seconds 2
Removing the old snapshots
This is done by collecting the snapshots older then the configured day’s. After these are collected the snapshots are removed by the Remove-VMSnapshot command.
Write-Host (Get-Date)": Removing snapshots of $VirtualMachine older than $SnapshotDays" Remove-VMSnapshot (Get-VMSnapshot -ComputerName $HyperVHost -VMName $VirtualMachine | Where-Object {$_.CreationTime -lt (Get-Date).AddDays(-$SnapshotDays)})
Starting the virtual machine
The last action is to power on the virtual machine. This is done by the Start-VM command.
Write-Host (Get-Date)": Starting $VirtualMachine" Start-VM -ComputerName $HyperVHost -Name $VM.Name Write-Host (Get-Date)": Backup script done"
The complete script
$VirtualMachine = "My-VM" $HyperVHost = "HVhost.lab.local" $SnapshotDays = 10 # Get VM information $VM = Get-VM -ComputerName $HyperVHost -Name $VirtualMachine # Provide shutdown command IF ($VM.State -ne "Off") { Write-Host (Get-Date)": Shutdown $VirtualMachine" Stop-Computer -ComputerName $VirtualMachine -Force } # Wait until VM is off Write-Host (Get-Date)": Waiting for $VirtualMachine to be Off" While ((Get-VM -ComputerName $HyperVHost -Name $VirtualMachine).State -ne "Off") { Write-Host "." -NoNewLine Start-Sleep -Seconds 5 } Write-Host " " Write-Host (Get-Date)": $VirtualMachine is in Off state" Write-Host (Get-Date)": Creating snapshot of $VirtualMachine" $DateFormat = Get-Date -Format yyyy.MM.dd $Snapshot = $VM.Name + "-" + $DateFormat CheckPoint-VM -ComputerName $HyperVHost -Name $VirtualMachine -Snapshotname $Snapshot Start-Sleep -Seconds 2 Write-Host (Get-Date)": Removing snapshots of $VirtualMachine older than $SnapshotDays" Remove-VMSnapshot (Get-VMSnapshot -ComputerName $HyperVHost -VMName $VirtualMachine | Where-Object {$_.CreationTime -lt (Get-Date).AddDays(-$SnapshotDays)}) Write-Host (Get-Date)": Starting $VirtualMachine" Start-VM -ComputerName $HyperVHost -Name $VM.Name Write-Host (Get-Date)": Backup script done"
Create a scheduled task that will run the script at a time you want and the snapshots are going to be created. I have scheduled the task to run every night at 3.00 AM so there are no interruptions on the server during production time.
I hope this is helpful for you and if you have any questions please leave a comment below.