Click an Ad

If you find this blog helpful, please support me by clicking an ad!

Tuesday, November 5, 2013

Checking for VMware Snapshots

So besides the standard way of simply looking at vCenter to see snapshots, there are a couple of other ways to accomplish this. The first way is manual, and uses RVTools, which is a GREAT tool for gathering lots of information about your VMware environment and its virtual machines. I run it every Monday just to make sure thing look healthy. Veeam's monitoring software, VeeamONE will also alert you when a snapshot is active for longer than a specified time, which can be altered by editing the alarm. VeeamONE is free, but if you want more features you have to go full version which is not free, of course.

I recommend both of these free tools to anyone who wants a health checkup or wants to create some quick documentation of their VMware Environment. These tools helped me immensely when I inherited mine, so that I could hit the ground with good information and a list of things to fix first.

I should not leave out vCheck, which a VERY full featured script offerend by Virtu-Al.net that can give you a LOT of good info. As a matter of fact, I created the script at the end of this entry from one of the subscripts of the vCheck project; the one that checks for snapshots.

I created this script to run at 6AM and let me know if there are any snapshots running before the start of the business day. Reasons for these snapshots can be a lot of things, but any of them bear looking into more closely. I could have a Veeam Backup that is stuck, like happened to me last week. I, or another admin, might have left a snapshot running (which merits a flogging!).

Also, you'll notice that the first thing it does is retrieve your credentials, which I created beforehand using the technique outlined in this post.

Without further ado, here's the script:

#Gets the credentials to facilitate connection to the Vcenter Server
$password = Get-Content c:\PSCred\mycred.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential "TaskSchedUser@Contoso.com",$password

#Gets some other miscellaneous variables for use in the email alert
$smtpServer = "mailServer.contoso.com"
$MailFrom = "helpdesk@contoso.com"
$MailTo = "IT@contoso.com"
$VISRV = "vCenterServer"

#Add the snapin for PowerCLI (The VMware Powershell module)
add-pssnapin Vmware.VimAutomation.Core

#Connect to your vCenter Server, using the credentials we created to authenticate
connect-viserver -server vCenterServer.contoso.com -credential $credential

#Function that finds the user that created the snapshot, so you can flog them
function Find-User ($username){
if ($username -ne $null)
{
$usr = (($username.split("\"))[1])
$root = [ADSI]""
$filter = ("(&(objectCategory=user)(samAccountName=$Usr))")
$ds = new-object system.DirectoryServices.DirectorySearcher($root,$filter)
$ds.PageSize = 1000
$ds.FindOne()
}
}

#Function that gets snapshot info
function Get-SnapshotTree{
param($tree, $target)

$found = $null
foreach($elem in $tree){
if($elem.Snapshot.Value -eq $target.Value){
$found = $elem
continue
}
}
if($found -eq $null -and $elem.ChildSnapshotList -ne $null){
$found = Get-SnapshotTree $elem.ChildSnapshotList $target
}

return $found
}

#Function that gets more detailed snapshot info
function Get-SnapshotExtra ($snap){
$guestName = $snap.VM # The name of the guest

$tasknumber = 999 # Windowsize of the Task collector

$taskMgr = Get-View TaskManager

# Create hash table. Each entry is a create snapshot task
$report = @{}

$filter = New-Object VMware.Vim.TaskFilterSpec
$filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
$filter.Time.beginTime = (($snap.Created).AddSeconds(-5))
$filter.Time.timeType = "startedTime"

$collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter))

$dummy = $collectionImpl.RewindCollector
$collection = $collectionImpl.ReadNextTasks($tasknumber)
while($collection -ne $null){
$collection | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $guestName} | %{
$row = New-Object PsObject
$row | Add-Member -MemberType NoteProperty -Name User -Value $_.Reason.UserName
$vm = Get-View $_.Entity
$snapshot = Get-SnapshotTree $vm.Snapshot.RootSnapshotList $_.Result
$key = $_.EntityName + "&" + ($snapshot.CreateTime.ToString())
$report[$key] = $row
}
$collection = $collectionImpl.ReadNextTasks($tasknumber)
}
$collectionImpl.DestroyCollector()

# Get the guest's snapshots and add the user
$snapshotsExtra = $snap | % {
$key = $_.vm.Name + "&" + ($_.Created.ToString())
if($report.ContainsKey($key)){
$_ | Add-Member -MemberType NoteProperty -Name Creator -Value $report[$key].User
}
$_
}
$snapshotsExtra
}

#Function to send mail. I normally just use a one-liner, but I'm reusing code, and this was here.
Function SnapMail ($Mailto, $snapshot)
{
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = $MailFrom
$msg.To.Add($Mailto)

$msg.Subject = "Snapshot Reminder"

$MailText = @"
There is a snapshot active on $($snapshot.VM) which was taken on $($snapshot.Created).

Name: $($snapshot.Name)

Description: $($snapshot.Description)
"@

$msg.Body = $MailText
$smtp.Send($msg)
}

#Cycles through any snapshots found, and send an email for each one
foreach ($snap in (Get-VM | Get-Snapshot)){
$SnapshotInfo = Get-SnapshotExtra $snap
SnapMail $mailto $SnapshotInfo
}

#Disconnect from the vCenter server
Disconnect-VIServer -Confirm:$false