PowerCLI script to alert on snapshots in vSphere

By | July 12, 2011

Updates – See bottom of post!

After writing my last script, I was asked by a couple of friends about ways to monitor your vSphere infrastructure for snapshots. There are many ways to do this, but here are two ways that I’ve used.

Alarm created in vCenter

From your Datacenter or Cluster object, go to Alarms and create a New Alarm. The screenshots below will illustrate how to make an alarm that will trigger after a VM’s snapshot hits 2GB.

Set your alarm’s name and description. Make sure the alarm type is for Virtual Machines and we’re monitoring for specific conditions.
Make these conditions fit your needs. This is just an example of which trigger to set.

Set your alarm range and frequency.
Finally set your notification thresholds. In this example we get an alert when the condition is red, then the “all clear” when it goes all the way green.

This method will work, but the alerts are ugly and personally I don’t like seeing a warning symbol on a VM unless it’s a real problem. So I recommend you use the script I wrote below.

PowerCLI Script

The script below will do the following:

  • Load the VMware commands into PowerShell (must have PowerCLI installed)
  • Connect to vCenter (will use the credentials of the user running the script, make sure you have access!)
  • Get a list of all VMs
  • Filter out all VMs without a snapshot
  • Send an e-mail to specified e-mail account(s) listing the VM, snapshot name, and size in megabytes of the snapshot – it will also include an attachment in CSV form (the format in the e-mail itself can be bad depending on where you’re viewing it from, e.g. a mobile device)
  • This script will NOT send an e-mail if no snapshots exist

Please let me know what you think. I’d love to know if this helped anyone.

$vcenterserver = "vcenter.domain.local" #Enter the FQDN or IP of your vCenter server
$fromAddr = "SnapshotReport@domain.com" # Enter the FROM address for the e-mail alert
$toAddr = "User@domain.com" # Enter the TO address for the e-mail alert
$smtpsrv = "" # Enter the FQDN or IP of a SMTP relay
$attachmentPref = 0 # Enter 1 if you would also like an attachment of the report in CSV format

Add-PSSnapin VMware.VimAutomation.Core # Add PowerCLI commandlets.

Connect-VIServer -server $vcenterserver

$date = Get-Date

$VMsWithSnaps = @(Get-VM | Get-Snapshot | Select vm,name,sizemb)

# Make sure the body isn't empty. If it is, skip this part and exit the script.
if($VMsWithSnaps -ne $null){
    $body = @("
    <center><table border=1 width=50% cellspacing=0 cellpadding=8 bgcolor=Black cols=3>
    <tr bgcolor=White><td>Virtual Machine</td><td>Snapshot</td><td>Size in MB</td></tr>")

    $i = 0

    do {
    if($i % 2){$body += "<tr bgcolor=#D2CFCF><td>$($VMsWithSnaps[$i].VM)</td><td>$($VMsWithSnaps[$i].Name)</td><td>$($VMsWithSnaps[$i].Sizemb)</td></tr>";$i++}
    else {$body += "<tr bgcolor=#EFEFEF><td>$($VMsWithSnaps[$i].VM)</td><td>$($VMsWithSnaps[$i].Name)</td><td>$($VMsWithSnaps[$i].Sizemb)</td></tr>";$i++}
    while ($VMsWithSnaps[$i] -ne $null)

    $body += "</table></center>"
# Send email alerting recipients about snapshots.
$VMsWithSnaps | Export-CSV "SnapshotReport $($date.month)-$($date.day)-$($date.year).csv"
Send-MailMessage -To "$toAddr" -From "$fromAddr" -Subject "WARNING: VMware Snapshots found on $date" -Body "$body" -Attachments "SnapshotReport $($date.month)-$($date.day)-$($date.year).csv" -SmtpServer "$smtpsrv" -BodyAsHtml
Remove-Item "SnapshotReport $($date.month)-$($date.day)-$($date.year).csv"
Send-MailMessage -To "$toAddr" -From "$fromAddr" -Subject "WARNING: VMware Snapshots found on $date" -Body "$body" -SmtpServer "$smtpsrv" -BodyAsHtml

Disconnect-VIServer -Server $vcenterserver -Confirm:$false


A buddy suggested that I make the script more user friendly by adding user defined variables at the top of the script. The above code now reflects this. Thanks Joseph.

Update 2 – July 27, 2011:

  • Added option to include an attachment with the e-mail
  • Created a neater report for e-mail
  • Simplified the query (don’t know why I didn’t do it this way before)
  • Various other tweaks as I’ve learned more about PowerShell

Update 3:

Forced $VMsWithSnaps to be an array (caused a blank email if only 1 VM had a snapshot).

11 thoughts on “PowerCLI script to alert on snapshots in vSphere

  1. J

    I love it! Ever since we went to ESXi, we couldn’t run our old snapshot checking alerts anymore. This fits in quite well.

  2. Pingback: Update to Global Address List script and Snapshot report – also blog update schedule | vNucleus

  3. Phong Nguyen


    Your PowerCLI snapshot script work beautifully.
    I executed the script manually under PowerCLI and got an email sucessfully.


    It would be awesome if we can add another collumn called “Created” to generate the snapshot taken date besides (VM name, snapshot and size).
    is this simple can you show me how to modify the script to do this?

    Can you show me steps by steps on how to automate this with the windows Task Scheduler on server 2008 R2 if possible?

    Your further help is much appreciated!

    I am a VMware newbie.

    1. David Post author

      Should be a pretty easy addition. I haven’t tested this, but it’s simple enough that it should work.

      Find this line:
      $VMsWithSnaps = @(Get-VM | Get-Snapshot | Select vm,name,sizemb)

      And replace it with:
      $VMsWithSnaps = @(Get-VM | Get-Snapshot | Select vm,name,sizemb,created)

      Find this line:
      <tr bgcolor=White><td>Virtual Machine</td><td>Snapshot</td><td>Size in MB</td></tr>")

      And replace it with:
      <tr bgcolor=White><td>Virtual Machine</td><td>Snapshot</td><td>Size in MB</td><td>Creation Time</td></tr>")

      Find these two lines:

      if($i % 2){$body += "<tr bgcolor=#D2CFCF><td>$($VMsWithSnaps[$i].VM)</td><td>$($VMsWithSnaps[$i].Name)</td><td>$($VMsWithSnaps[$i].Sizemb)</td></tr>";$i++}
      else {$body += "<tr bgcolor=#EFEFEF><td>$($VMsWithSnaps[$i].VM)</td><td>$($VMsWithSnaps[$i].Name)</td><td>$($VMsWithSnaps[$i].Sizemb)</td></tr>";$i++}

      And replace them with:

      if($i % 2){$body += "<tr bgcolor=#D2CFCF><td>$($VMsWithSnaps[$i].VM)</td><td>$($VMsWithSnaps[$i].Name)</td><td>$($VMsWithSnaps[$i].Sizemb)</td><td>$($VMsWithSnaps[$i].Created)</td></tr>";$i++}
      else {$body += "<tr bgcolor=#EFEFEF><td>$($VMsWithSnaps[$i].VM)</td><td>$($VMsWithSnaps[$i].Name)</td><td>$($VMsWithSnaps[$i].Sizemb)</td><td>$($VMsWithSnaps[$i].Created)</td></tr>";$i++}

      That should give you what you want.

  4. Pingback: Echo! Echo! Echo! | vNucleus

  5. Raymond McDonald

    Hi there,

    I would like to know is can this be modified to send an email if there is no snapshots? Say if Task Scheduler breaks then I would find this when I dont get an email saying there is snapshots or no snapshots.


  6. John

    Liking the script a lot, do you know if there is a way to take the lsit of VM’s in the array and get the ManagedBy field from AD and place that in the table with all the other data.

  7. Thiyagarajan

    Could you help to add in the script, which user has created the snapshot?

  8. Ramin Asef

    Hi David ,I would appreciate if you help me with the issue .We nee to create script to create alarm like above and send us email if VMSNAPSHOT has been created more than 10 GB .Could you kindly let me what modification needs to be done in above script .

    many thanks

  9. Craig


    Really useful script and thanks for posting it.
    Did you know you can change:
    if($VMsWithSnaps -ne $null)
    if ($VMsWithSnaps)
    and it’s the same thing?


Leave a Reply

Your email address will not be published.