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-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