Using PowerShell for VM Snapshot Creation & Cleanup

Using PowerShell for VM Snapshot Creation & Cleanup

There is often a use case for creating snapshots of a list of VMs in a VMware virtual environment. For example, when upgrading vRealize Operations Manager, the documentation recommends taking a snapshot of the VMs in the cluster before upgrading. With a growing number of nodes in our vROps cluster, I finally wrote some PowerShell to automate the snapshot creation and removal process. When shared with my peers in another IT group, they had another use case where they wished to skip any VMs larger than a given size (1 TB in this instance).


<# .SYNOPSIS Read a list of VMs from a text file; check disk usage and take snapshot if less than 1 TB .DESCRIPTION @vMiklm - miklm.com 2017-08-08 #>

# vCenter Server name (comma separate for multiple)
Connect-VIServer VCENTER_SERVER_1, VCENTER_SERVER_2

# Input :: Change this to the local path to your text list of VMs to check & snapshot
$serverList = Get-Content "e:\temp\vmInputList.txt"

# Output :: Filename for output list of successful snapshot VMs
$outputFile = 'e:\temp\vmOutputList-20170808.txt'

# snapshotName = Descriptive name of Snapshot (includes system date)
$snapshotDate=Get-date
$snapshotName = "VM Snapshot - " + $snapshotDate

# snapshotDesc = Description of snapshot including responsible user & delete by date (using system date + 7 days)
$snapshotDate=(Get-date).AddDays(7)
$snapshotDesc = "USERNAME - Delete after " + $snapshotDate

# Threshold Size is the maximum size, in GB, of the VMs to snapshot. 1024 GB = 1 TB
$thresholdSize = 1024

$snapshotServerList = @()

foreach ($server in $serverList)
{
# initialize the sum variable to zero
$diskSizeTotal = 0

$Disks = Get-HardDisk -VM $server

foreach($disk in $Disks)
{
$DiskName = $Disk.Name
$DisksizeinGB = ($Disk.CapacityKB * 1024)/1GB

# use this sum variable to keep the running total of disk size in GB
$diskSizeTotal=$diskSizeTotal+$DisksizeinGB
}

if ($diskSizeTotal -gt $thresholdSize)
{
echo $server" : "$diskSizeTotal" GB is greater than 1 TB. Snapshot skipped"
}
else
{
echo $server" : "$diskSizeTotal" GB is less than 1 TB."
# Take Snapshot
New-Snapshot -VM $server -Name $snapshotName -Description $snapshotDesc
# Add server to list array of servers with Snapshot taken; this list will be output to file to allow cleanup of snapshots
$snapshotServerList+=$server
}
}

# Output list of servers that had Snapshot taken; this file should then be used as input for the snapshot cleanup script
foreach ($serverinList in $snapshotServerList)
{
echo $serverinList | Out-File -Append $outputFile
}

And here’s the accompanying script to remove snapshots when no longer required. Assumption is that the $outputFile from the above “take snapshot” script will be used as input ($serverList) for the “remove snapshot” script below.


<# .SYNOPSIS Read a list of VMs from a text file and remove ALL snapshots for listed VMs .DESCRIPTION @vMiklm - miklm.com - 2017-08-08 #>

Connect-VIServer VCENTER_SERVER_1, VCENTER_SERVER_2

# Change this to the local path to your list of VMs to remove snapshots
# If used with the above snapshots script, this is same file as $outputFile
$serverList = Get-Content "e:\temp\vmOutputList-20170808.txt"

foreach ($server in $serverList)
{
$snapsList = Get-VM $server | Get-Snapshot
foreach ($snapshot in $snapsList)
{
# If the number of snapshots is large, consider removing -RunAsync to avoid too much load on the storage backend
Remove-Snapshot $snapshot -Confirm:$false -RunAsync
}
}

Code is presented for example, reference, and training. You may have to modify extensively to make any of it work in your environment. I make no claims of being a developer. I have learned what little I know by seeing how others have solved problems in PowerShell (and PHP, C#, etc.), so this is a small effort to contribute back to the community. There are certainly other ways to do this, and likely BETTER ways, but this is what I have made. Feedback & suggestions are welcome in the comments. No support, warranty, guarantee, or anything else is given with any code found on this site. Use at your own risk.

Comments are closed.