If you are managing Virtualized infrastructure by using Hyper-V, this small script may come in handy (and save you from getting a headache).

Few clients have a procedure to create VM Snapshot before making some big changes to the VM (I know, that’s not a backup solution but I can’t win all the battles). The problem occurs if they forget to merge it after all was successful and you end up with a growing snapshot and low disk space o.O

So, here is how I ended that game.

Import-Module CredentialManager.psm1

Function Email {
$From = "Monitoring@Tech-Trainer.info"
$To = "support@Tech-Trainer.info"
#$Cc = ""
$Attachment = "C:\Temp\snapshots.html"
$Subject = "Active snapshots"
$Body = Get-Content C:\Temp\snapshots.html -Raw -ErrorAction SilentlyContinue
$SMTPServer = "smtp.sendgrid.net"
$SMTPPort = "587"
$Cred = Get-StoredCredential -Name EmailNotification
# Test if the file was created during snapshot check. If not email send will not be engaged.
if(Test-Path -Path C:\Temp\snapshots.html) {
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -BodyAsHtml -SmtpServer $SMTPServer -port $SMTPPort -Usessl -Credential $cred -Attachments $Attachment –DeliveryNotificationOption OnSuccess
    }
}

# Period for testing if older checkpoint exists
$Days = 3
# Clearing old data
Remove-Item -Path C:\Temp\snapshots.html -ErrorAction SilentlyContinue
# CSS for email style
$Header = @"
<style #close this style with >
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse; width: 100%;}
th {
  background-color: #4CAF50;
  color: white;
  text-align: left;
  height: 50px;
}
td {
  border-width: 1px; 
  padding: 3px; 
  border-style: solid; 
  border-color: black;}
</style #close this style with >
"@

$VMs = Get-VM | Where-Object {$_.State -eq 'Running'}
foreach($VM in $VMs){
$Snapshots = Get-VMSnapshot $VM
if ($snapshots.CreationTime.AddDays($Days) -lt (get-date)) {Get-VMSnapshot $VM | ConvertTo-Html -Property VMName, Name, CreationTime, ParentSnapshotName -Head $Header | Out-File -Append C:\Temp\snapshots.html}
}

email

The first thing that you may notice is that I’m using a module called CredentialManager.psm1. The Author of this great module is Dave Garnar and you can find it here. After reading about it you will see how I used it to create a stored credential in EmailNotification object.

Note: To be able to use this module you will have to put it in your local module directory ($env:PSModulePath).

The second one that may be strange is SMTP I used – This is a part of Azure subscription and it is free for up to 25000 of sent emails per month! Awesome!

You will notice that I have CSS included, some header style…?!? Well, I decided to shape the email that we get, to be nicer to the eye 🙂 And here it is:

Note: Pay attention to comment about closing the style in the header – inserting code inside the code was messing up my code 😀 And feel free to change colors as you prefer.

In the end, we are checking all the running VMs and if they have snapshot older than 3 days (I believe that’s enough time for the client to confirm that all’s god and that the snapshot won’t become that big).

The email will be triggered only if there are any snapshots.

For the brave ones – you may try this part of the code (I prefer merging manually at this moment):

#foreach($Snapshot in $Snapshots){
#
#    if ($snapshot.CreationTime.AddDays($Days) -lt (get-date)) {
#        Remove-VMSnapshot $Snapshot -WhatIf
#   } 
#}

 

Now that you have your script in place you should automate it – create a scheduled job that will trigger it at any time you like.

Have another great day in Admins life 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.