Cleaning up old snapshots is one of the easiest ways that a virtualization administrator can reclaim storage capacity in their environment. Unlike reclaiming other resources such as CPU or Memory, deleting old snapshots doesn’t require downtime and therefore doesn’t usually require getting your change control board involved. Now, many of us are guilty of having snapshots that are months old, and sometimes for reasons we can’t even remember. But unless you have a tool like vRealize Operations Manager, finding and deleting old snapshots can be a lengthy manual process.
PowerCLI can help with this. The Remove-Snapshot cmdlet can be leveraged to delete a VM’s old snapshots. Simply running the following command will delete every snapshot in your environment.
Get-VM | Get-Snapshot | Remove Snapshot
However, what if you want to be more selective about what snapshots you’re removing? It’s likely you still need that snapshot you took today right before lunch. So how do we automate this so that we have control over which VM’s snapshots get deleted and which don’t?
The following script is something I quickly wrote for one of my customers. The user will create a CSV file with the VM’s he or she wants to clean up along with that VM’s respective vCenter Server. The script will then connect to the vCenter server(s) and go through one-by-one deleting the specified VM’s snapshots.
By leveraging a great tool by Rob de Veij called RV tools, we can easily create a list of VM’s with old snapshots. Sure, it will take some effort to convert the CSV output from RVTools into something that is formatted for this script; however, I wrote this for my customer to leverage their TAM Metrics report that I provide to them. If you’re not a TAM customer, then RV tools is another great way to get similar results.
For this example, we’ll pick two VM’s. Desktop1 and 2008r2 App Server. Both VM’s are managed by the same vCenter Server, so the CSV table would look like this in Excel.
vCenter | VM |
VC1 | Desktop1 |
VC1 | 2008r2 App Server |
It’s very important to include the vCenter and VM headers because these are called by the script. The reason I included the vCenter Server here is because my customer has multiple vCenters and instead of forcing them to log into each one, why not make it easy and connect to all of them.
When you first launch the script, it will import the CSV file and ask the user for their vCenter Credentials. This assumes that the credentials are the same for each vCenter you wish to connect to.
The script then looks at the vCenter column of the CSV and de-duplicates it, thus creating a list of what unique vCenters we need to connect to.
Once we’re connected to the vCenter Server(s), we start going down the list of VM’s and deleting their snapshots one by one. We could delete many snapshots at the same time, but here we’re just doing one at a time in an abundance of caution to avoid generating too many IOPs on our storage.
Once the script has finished, we can log into vCenter and see the Remove Snapshot tasks.
As an added benefit, this script generates a log file to show us when we kicked off a remove-snapshots task, how many snapshots are associated with that VM, and when the task finished. The log also includes any output from the Remove-Snapshot command in case of an error.
The log file for our two VM’s will look similar to this.
##################################################### 06/16/2017 16:59:22 New Session Started 06/16/2017 16:59:22 Connecting to VC1 06/16/2017 16:59:22 Removing 1 Snapshot(s) for VM Desktop1 06/16/2017 16:59:24 Snapshots removed for Desktop1 06/16/2017 16:59:24 Removing 3 Snapshot(s) for VM 2008r2 App Server 06/16/2017 16:59:27 Snapshots removed for 2008r2 App Server
As always, when copying this or any script off the internet for use in production, be sure to thoroughly test it in a lab environment to make sure it works for your particular scenario. This script was written in between conference calls and while I did my best to test it in my home lab, I can’t account for every circumstance. For example, what would happen if you had two VM’s under different vCenters with the same name? Would it cause headaches for you or your customer? That’s why it’s always good to test everything for your particular scenario in a lab first.
$csvfile = ".\Snapshots.csv" #CSV file of the VM's to have their snapshots removed $logfile = ".\log.txt" #Script's log file location $vms = Import-Csv $csvfile #Read the CSV File into a variable $creds = Get-Credential #Get the user's credentials for vCenter (assumes the user has the same user/pass for all vCenters) $timestamp = Get-Date #Get the current date/time and place entry into log that a new session has started Add-Content $logfile "#####################################################" Add-Content $logfile "$timestamp New Session Started" $vcenters = $vms | select -ExpandProperty vCenter -Unique #Read the vCenters contained in the CSV and dedupe them foreach ($vcenter in $vcenters) #Log into each vCenter included in the CSV file (assumes the user has the same user/pass for all vCenters) { $timestamp = Get-Date #Get the current date/time and place entry into log that the script is connecting to each vCenter $message = "$timestamp Connecting to $vcenter" Write-Host $message Add-Content $logfile $message Connect-VIServer $vcenter -Credential $creds #Connect to the vCenter using the credentials provided at first run Write-Host `n } foreach ($vm in $vms) #Remove snapshots for each VM in the CSV { $vm = get-VM $vm.VM #Load the virtual machine object $snapshotcount = $vm | Get-Snapshot | measure #Get the number of snapshots for the VM $snapshotcount = $snapshotcount.Count #This line makes it easier to insert the number of snapshots into the log file $timestamp = Get-Date #Get the current date/time and place entry into log that the script is going to remove x number of shapshots for the VM $message = "$timestamp Removing $snapshotcount Snapshot(s) for VM $vm" Write-Host $message Add-Content $logfile $message $vm | Get-Snapshot | Remove-Snapshot -confirm:$false | Out-File $logfile -Append #Removes the VM's snapshot(s) and writes any output to the log file $timestamp = Get-Date #Get the current date/time and place entry into log that the script has finished removing the VM's snapshot(s) Add-Content $logfile "$timestamp Snapshots removed for $vm" }
The Script is working fine ,thanks Matt 🙂
You may use start-transcript in the beginning and stop-tracnscript in the end to collect the logs and errors that may occur while running this script
Thanks Matt B, the script works perfectly. – Matt F