Creating VMware Snapshots with PowerCLI

Without a doubt, one the best reasons to virtualize is the ability to easily roll back to a previous configuration. This is done with the use of snapshots, and VMware is no different. Even better, you can manage the entire process from PowerShell with the PowerCLI cmdlets.

(Editor’s note: Need to catch up? We have loads of PowerCLI articles, including “Getting Started with vSphere PowerCLI,” ” Managing VMware Tools with PowerCLI,” and “Modifying a VM with PowerCLI.”
Using the command line means that you can automate snapshots or manage multiple snapshots with a single command. Perhaps you like to take a daily snapshot of all your running virtual machines as an extra safety precaution. Or maybe you plan on installing a service pack on a number of virtual machines and want an easy roll-back option should problems arise. Today I’ll walk you through using PowerCLI cmdlets to create and manage snapshots.

Creating a Snapshot

To create a snapshot, the virtual machine can be on or off. The snapshot will be created using that state. This might be important because if you roll back a running virtual machine to a snapshot where the virtual machine was stopped, the virtual machine will be stopped. You will use the New-Snapshot cmdlet.
When you create the snapshot you will need to give it a name. Optionally, you can also provide a description. If the virtual machine is running, you can also elect to save the memory state as well with the –Memory parameter. Also, if the virtual machine is running and it has virtual tools installed, you can opt for a quiescent snapshot with –Quiesce. This has the effect of saving the virtual disk in a consistent state. That is, the snapshot occurs without the operating system in the middle of trying to write something to disk. Personally, I always have less problems restoring to a snapshot if I use –Quiesce, although there is a slight trade-off in the time it takes to create the snapshot. In fact, because a snapshot can take a few minutes to create, you may want to create it in the background on the VMware host using –RunAsycn.
I’m going to create a snapshot of one of my running virtual machines.

​ PS C:\> get-vm petri-1 | new-snapshot -Name "Demo" -Description "Sample snapshot" -Quiesce -Memory

This combination of parameters will probably take the longest to create, but it should put the virtual machine back in the exact state should I restore to it. You will have to take into account what applications are running that might be adversely affected if you capture and restore memory.
Naturally, if I can do it for one virtual machine, I can do it for many.

​ PS C:\> get-vm globo* | new-snapshot -name DailySafety -Description "Created $(Get-Date)" –RunAsync

With this one line command I got all of my Globomantics virtual machines and created a snapshot for each one called DailySafety. The virtual machines are off which is why I didn’t use –Memory or –Quiesce. But I did create them via a VMware task so I could get my PowerShell prompt back and keep working.

Listing Snapshots

To enumerate snapshots, use Get-Snapshot. The snapshots are associated with the virtual machine, so you’ll need to specify one.

​ PS C:\> get-snapshot -vm petri-1
Name                 Description                    PowerState
----                 -----------                    ----------
pre-tools                                           PoweredOff
Demo                 Sample snapshot                PoweredOn

Or you can get a single snapshot by name.

​ PS C:\> get-snapshot -vm petri-1 -name demo | select *

As you can see in Figure 1 below, there is some very valuable information with the snapshot object.
create Snapshots with PowerCLI get-snapshot
Once you know what to look for, it is relatively simple to create a snapshot report.

​ get-vm | get-snapshot | select VM,Name,Description,
PowerState,Quiesced,Created,Parent,
@{Name="Age";Expression={(Get-Date) - $_.Created }},
@{Name="SizeMB";Expression={[math]::Round($_.SizeMB,2)}} |
Sort VM,Created

As you see in Figure 2, I’m simply displaying results to the console, but you can do whatever you want with the results.
create Snapshots with PowerCLI display results
Or perhaps you want to know how much space each virtual machine is using for snapshots.

​ get-snapshot * | Group VM |
Add-Member -membertype ScriptProperty -Name TotalSnapshotSizeMB -value {
$stat = $this.group | Measure-Object -property SizeMB -sum
[math]::Round($stat.sum,2)
} -passthru |
Select Name,Count,TotalSnapshotSizeMB |
Sort TotalSnapshotSizeMB –Descending

You can see my result in Figure 3.
create Snapshots with PowerCLI
With PowerShell there’s almost no limit to how you can slice, dice, and display data.

Restoring from a Snapshot

To restore a snapshot, we will use the Set-VM cmdlet. While you can probably do this with a single command, it might get a little complicated. There’s no reason not break it down into simple parts. First, get the snapshot.

​ PS C:\> $snap = get-snapshot -vm petri-1 -name demo

Set-VM can get the virtual machine by name.

​ PS C:\> set-vm -VM Petri-1 -Snapshot $snap -whatif
What if: Reverting VM 'Petri-1' to snapshot 'Demo'.

Using –Whatif is a nice sanity check. This looks good, so I’ll do it for real.

​ PS C:\> set-vm -VM Petri-1 -Snapshot $snap

I am prompted for confirmation after which the virtual machine is restored to its previous state.

Removing Snapshots

Periodically you may want to clean up old snapshots using Remove-Snapshot. The easiest approach is to get the snapshot or snapshots and pipe them to Remove-Snapshot. Some snapshots may have child snapshots so use –RemoveChildren to clean those up as well. My demo snapshot doesn’t have any children so I can easily remove it like this:

​ PS C:\> get-snapshot -name Demo -VM petri-1 | remove-snapshot

If you don’t want to be prompted, include –confirm:$False. Removing a snapshot can be a long process so you might want to take advantage of the RunAsync parameter.
Or, let’s say I want to delete my safety snapshots so that I can take a new set.

​ PS C:\> get-snapshot -name DailySafety -vm * | remove-snapshot -RemoveChildren -RunAsync -confirm:$false

In this situation, I have snapshot on multiple virtual machines that use the same name. You have to provide a value for –VM but you can use wildcards. I knew this would take some time to complete so I’m running it asynchronously.
Finally, I might want to remove all snapshots to free up some disk space.

​ PS C:\> get-snapshot -vm * | remove-snapshot –whatif

 
As with all of the PowerCLI cmdlets, take the time to read the complete help and examples. Try my examples in a nonproduction environment. Experiment with quiescence and without. Practice restoring snapshots. The more time you spend at a PowerShell prompt with PowerCLI, the more I think you’ll find managing your VMware infrastructure to be a snap.