PoshCode Logo PowerShell Code Repository

VMware Daily Report by alanrenouf 31 months ago (modification of post by alanrenouf view diff)
View followups from alanrenouf | diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/1212"></script>download | new post

For more information and sample out put please visit http://www.virtu-al.net/2009/07/14/powercli-daily-report/

  1. # vCheck - Daily Error Report
  2. #
  3. # Changes:
  4. # Version 1.11 - Simplified mail function.
  5. # Version 1.10 - Added How many days old the snapshots are
  6. # Version 1.9 - Added ability to change user account which makes the WMI calls
  7. # Version 1.8 - Added Real name resolution via AD and sorted disk space by PerfFree
  8. # Version 1.7 - Added Event Logs for VMware warnings and errors for past day
  9. # Version 1.6 - Add details to service state to see if it is expected or not
  10. # Version 1.5 - Check for objects to see if they exist before sending the email + add VMs with No VMTools
  11. param( [string] $VISRV)
  12.  
  13. # You can change the following defaults by altering the below settings:
  14. #
  15. #
  16. # Set the SMTP Server address
  17. #
  18. $SMTPSRV = "myexchangeserver.mydomain.comk"
  19. #
  20. # Set the Email address to recieve from
  21. #
  22. $EmailFrom = "reports@mydomain.com"
  23. #
  24. # Set the Email address to send the email to
  25. #
  26. $EmailTo = "myemail@mydomain.com"
  27.  
  28. #### Detail Settings ####
  29. # Set the username of the account with permissions to access the VI Server
  30. # for event logs and service details - you will be asked for the same username and password
  31. # only the first time this runs after setting the below username.
  32. # If it is left blank it will use the credentials of the user who runs the script
  33. $SetUsername = ""
  34. # Set the location to store the credentials in a secure manner
  35. $CredFile = ".\mycred.crd"
  36. # Set the warning threshold for Datastore % Free Space
  37. $DatastoreSpace = "5"
  38. # Set the warning threshold for snapshots in days old
  39. $SnapshotAge = 14
  40. # Set the number of days to show VMs created & removed for
  41. $VMsNewRemovedAge = 5
  42. # Set the number of days of VC Events to check for errors
  43. $VCEventAge = 1
  44. # Set tge bumber of days of VC Event Logs to check for warnings and errors
  45. $VCEvntlgAge = 1
  46.  
  47.  
  48. #######################################
  49. # Start of script
  50. if ($VISRV -eq ""){
  51.         Write-Host
  52.         Write-Host "Please specify a VI Server name eg...."
  53.         Write-Host "      powershell.exe DailyReport.ps1 MYVISERVER"
  54.         Write-Host
  55.         Write-Host
  56.         exit
  57. }
  58.  
  59. function Send-SMTPmail($to, $from, $subject, $smtpserver, $body) {
  60.         $mailer = new-object Net.Mail.SMTPclient($smtpserver)
  61.         $msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
  62.         $msg.IsBodyHTML = $true
  63.         $mailer.send($msg)
  64. }
  65.  
  66. Function Get-CustomHTML ($Header){
  67. $Report = @"
  68. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
  69. <html><head><title>$($Header)</title>
  70. <META http-equiv=Content-Type content='text/html; charset=windows-1252'>
  71.  
  72. <meta name="save" content="history">
  73.  
  74. <style type="text/css">
  75. DIV .expando {DISPLAY: block; FONT-WEIGHT: normal; FONT-SIZE: 10pt; RIGHT: 8px; COLOR: #ffffff; FONT-FAMILY: Tahoma; POSITION: absolute; TEXT-DECORATION: underline}
  76. TABLE {TABLE-LAYOUT: fixed; FONT-SIZE: 100%; WIDTH: 100%}
  77. *{margin:0}
  78. .dspcont { BORDER-RIGHT: #bbbbbb 1px solid; BORDER-TOP: #bbbbbb 1px solid; PADDING-LEFT: 16px; FONT-SIZE: 8pt;MARGIN-BOTTOM: -1px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 0px; BORDER-LEFT: #bbbbbb 1px solid; WIDTH: 95%; COLOR: #000000; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; BACKGROUND-COLOR: #f9f9f9}
  79. .filler {BORDER-RIGHT: medium none; BORDER-TOP: medium none; DISPLAY: block; BACKGROUND: none transparent scroll repeat 0% 0%; MARGIN-BOTTOM: -1px; FONT: 100%/8px Tahoma; MARGIN-LEFT: 43px; BORDER-LEFT: medium none; COLOR: #ffffff; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: medium none; POSITION: relative}
  80. .save{behavior:url(#default#savehistory);}
  81. .dspcont1{ display:none}
  82. a.dsphead0 {BORDER-RIGHT: #bbbbbb 1px solid; PADDING-RIGHT: 5em; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 5px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; MARGIN-BOTTOM: -1px; MARGIN-LEFT: 0px; BORDER-LEFT: #bbbbbb 1px solid; CURSOR: hand; COLOR: #FFFFFF; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; HEIGHT: 2.25em; WIDTH: 95%; BACKGROUND-COLOR: #cc0000}
  83. a.dsphead1 {BORDER-RIGHT: #bbbbbb 1px solid; PADDING-RIGHT: 5em; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 5px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; MARGIN-BOTTOM: -1px; MARGIN-LEFT: 0px; BORDER-LEFT: #bbbbbb 1px solid; CURSOR: hand; COLOR: #ffffff; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; HEIGHT: 2.25em; WIDTH: 95%; BACKGROUND-COLOR: #7BA7C7}
  84. a.dsphead2 {BORDER-RIGHT: #bbbbbb 1px solid; PADDING-RIGHT: 5em; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 5px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; MARGIN-BOTTOM: -1px; MARGIN-LEFT: 0px; BORDER-LEFT: #bbbbbb 1px solid; CURSOR: hand; COLOR: #ffffff; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; HEIGHT: 2.25em; WIDTH: 95%; BACKGROUND-COLOR: #A5A5A5}
  85. a.dsphead1 span.dspchar{font-family:monospace;font-weight:normal;}
  86. td {VERTICAL-ALIGN: TOP; FONT-FAMILY: Tahoma}
  87. th {VERTICAL-ALIGN: TOP; COLOR: #cc0000; TEXT-ALIGN: left}
  88. BODY {margin-left: 4pt}
  89. BODY {margin-right: 4pt}
  90. BODY {margin-top: 6pt}
  91. </style>
  92. </head>
  93. <body>
  94. <b><font face="Arial" size="5">$($Header)</font></b><hr size="8" color="#cc0000">
  95. <font face="Arial" size="1"><b>Generated on $($ENV:Computername)</b></font><br>
  96. <font face="Arial" size="1">Report created on $(Get-Date)</font>
  97. <div class="filler"></div>
  98. <div class="filler"></div>
  99. <div class="filler"></div>
  100. <div class="save">
  101. "@
  102. Return $Report
  103. }
  104.  
  105. Function Get-CustomHeader0 ($Title){
  106. $Report = @"
  107.                 <h1><a class="dsphead0">$($Title)</a></h1>
  108.         <div class="filler"></div>
  109. "@
  110. Return $Report
  111. }
  112.  
  113. Function Get-CustomHeader ($Num, $Title){
  114. $Report = @"
  115.         <h2><a class="dsphead$($Num)">
  116.         $($Title)</a></h2>
  117.         <div class="dspcont">
  118. "@
  119. Return $Report
  120. }
  121.  
  122. Function Get-CustomHeaderClose{
  123.  
  124.         $Report = @"
  125.                 </DIV>
  126.                 <div class="filler"></div>
  127. "@
  128. Return $Report
  129. }
  130.  
  131. Function Get-CustomHeader0Close{
  132.  
  133.         $Report = @"
  134. </DIV>
  135. "@
  136. Return $Report
  137. }
  138.  
  139. Function Get-CustomHTMLClose{
  140.  
  141.         $Report = @"
  142. </div>
  143.  
  144. </body>
  145. </html>
  146. "@
  147. Return $Report
  148. }
  149.  
  150. Function Get-HTMLTable {
  151.         param([array]$Content)
  152.         $HTMLTable = $Content | ConvertTo-Html
  153.         $HTMLTable = $HTMLTable -replace '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', ""
  154.         $HTMLTable = $HTMLTable -replace '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  "http://www.w3.org/TR/html4/strict.dtd">', ""
  155.         $HTMLTable = $HTMLTable -replace '<html xmlns="http://www.w3.org/1999/xhtml">', ""
  156.         $HTMLTable = $HTMLTable -replace '<html>', ""
  157.         $HTMLTable = $HTMLTable -replace '<head>', ""
  158.         $HTMLTable = $HTMLTable -replace '<title>HTML TABLE</title>', ""
  159.         $HTMLTable = $HTMLTable -replace '</head><body>', ""
  160.         $HTMLTable = $HTMLTable -replace '</body></html>', ""
  161.         Return $HTMLTable
  162. }
  163.  
  164. Function Get-HTMLDetail ($Heading, $Detail){
  165. $Report = @"
  166. <TABLE>
  167.         <tr>
  168.         <th width='25%'><b>$Heading</b></font></th>
  169.         <td width='75%'>$($Detail)</td>
  170.         </tr>
  171. </TABLE>
  172. "@
  173. Return $Report
  174. }
  175.  
  176. function Find-Username ($username){
  177.         if ($username -ne $null)
  178.         {
  179.                 $root = [ADSI]""
  180.                 $filter = ("(&(objectCategory=user)(samAccountName=$Username))")
  181.                 $ds = new-object  system.DirectoryServices.DirectorySearcher($root,$filter)
  182.                 $ds.PageSize = 1000
  183.                 $ds.FindOne()
  184.         }
  185. }
  186.  
  187. function Get-VIServices
  188. {
  189.         If ($SetUsername -ne ""){
  190.                 $Services = get-wmiobject win32_service -Credential $creds -ComputerName $VISRV | Where {$_.DisplayName -like "VMware*" }
  191.         } Else {
  192.                 $Services = get-wmiobject win32_service -ComputerName $VISRV | Where {$_.DisplayName -like "VMware*" }
  193.         }
  194.        
  195.         $myCol = @()
  196.  
  197.         Foreach ($service in $Services){
  198.                 $MyDetails = "" | select-Object Name, State, StartMode, Health
  199.                 If ($service.StartMode -eq "Auto")
  200.                 {
  201.                         if ($service.State -eq "Stopped")
  202.                         {
  203.                                 $MyDetails.Name = $service.Displayname
  204.                                 $MyDetails.State = $service.State
  205.                                 $MyDetails.StartMode = $service.StartMode
  206.                                 $MyDetails.Health = "Unexpected State"
  207.                         }
  208.                 }
  209.                 If ($service.StartMode -eq "Auto")
  210.                 {
  211.                         if ($service.State -eq "Running")
  212.                         {
  213.                                 $MyDetails.Name = $service.Displayname
  214.                                 $MyDetails.State = $service.State
  215.                                 $MyDetails.StartMode = $service.StartMode
  216.                                 $MyDetails.Health = "OK"
  217.                         }
  218.                 }
  219.                 If ($service.StartMode -eq "Disabled")
  220.                 {
  221.                         If ($service.State -eq "Running")
  222.                         {
  223.                                 $MyDetails.Name = $service.Displayname
  224.                                 $MyDetails.State = $service.State
  225.                                 $MyDetails.StartMode = $service.StartMode
  226.                                 $MyDetails.Health = "Unexpected State"
  227.                         }
  228.                 }
  229.                 If ($service.StartMode -eq "Disabled")
  230.                 {
  231.                         if ($service.State -eq "Stopped")
  232.                         {
  233.                                 $MyDetails.Name = $service.Displayname
  234.                                 $MyDetails.State = $service.State
  235.                                 $MyDetails.StartMode = $service.StartMode
  236.                                 $MyDetails.Health = "OK"
  237.                         }
  238.                 }
  239.                 $myCol += $MyDetails
  240.         }
  241.         Write-Output $myCol
  242. }
  243.  
  244. function Get-DatastoreSummary {
  245.         param(
  246.                 $InputObject = $null
  247.         )
  248.         begin {
  249.         }
  250.         process {
  251.                 if ($InputObject -and $_) {
  252.                         throw 'The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.'
  253.                         return
  254.                 }
  255.                 $processObject = $(if ($InputObject) {$InputObject} else {$_})
  256.                 if ($processObject) {
  257.                         $myCol = @()
  258.                         foreach ($ds in $_)
  259.                         {
  260.                                 $MyDetails = "" | select-Object Name, Type, CapacityMB, FreeSpaceMB, PercFreeSpace
  261.                                 $MyDetails.Name = $ds.Name
  262.                                 $MyDetails.Type = $ds.Type
  263.                                 $MyDetails.CapacityMB = $ds.CapacityMB
  264.                                 $MyDetails.FreeSpaceMB = $ds.FreeSpaceMB
  265.                                 $MyDetails.PercFreeSpace = [math]::Round(((100 * ($ds.FreeSpaceMB)) / ($ds.CapacityMB)),0)
  266.                                 $myCol += $MyDetails
  267.                         }
  268.                         $myCol | Where { $_.PercFreeSpace -lt $DatastoreSpace }
  269.                 }
  270.         }
  271.         end {
  272.         }
  273. }
  274.  
  275. function Get-SnapshotSummary {
  276.         param(
  277.                 $InputObject = $null
  278.         )
  279.  
  280.         BEGIN {
  281.         }
  282.  
  283.         PROCESS {
  284.                 if ($InputObject -and $_) {
  285.                         throw 'ParameterBinderStrings\AmbiguousParameterSet'
  286.                         break
  287.                 } elseif ($InputObject) {
  288.                         $InputObject
  289.                 } elseif ($_) {
  290.                        
  291.                         $mySnaps = @()
  292.                         foreach ($snap in $_){
  293.                                 $SnapshotInfo = Get-SnapshotExtra $snap
  294.                                 $mySnaps += $SnapshotInfo
  295.                         }
  296.  
  297.                         $mySnaps | Select VM, Name, @{N="DaysOld";E={((Get-Date) - $_.Created).Days}}, @{N="Creator";E={(Find-Username (($_.Creator.split("\"))[1])).Properties.displayname}}, Created, Description | Sort DaysOld
  298.  
  299.                 } else {
  300.                         throw 'ParameterBinderStrings\InputObjectNotBound'
  301.                 }
  302.         }
  303.  
  304.         END {
  305.         }
  306. }
  307.  
  308. function Get-SnapshotTree{
  309.         param($tree, $target)
  310.        
  311.         $found = $null
  312.         foreach($elem in $tree){
  313.                 if($elem.Snapshot.Value -eq $target.Value){
  314.                         $found = $elem
  315.                         continue
  316.                 }
  317.         }
  318.         if($found -eq $null -and $elem.ChildSnapshotList -ne $null){
  319.                 $found = Get-SnapshotTree $elem.ChildSnapshotList $target
  320.         }
  321.        
  322.         return $found
  323. }
  324.  
  325. function Get-SnapshotExtra ($snap){
  326.         $guestName = $snap.VM   # The name of the guest
  327.         $tasknumber = 999               # Windowsize of the Task collector
  328.         $taskMgr = Get-View TaskManager
  329.        
  330.         # Create hash table. Each entry is a create snapshot task
  331.         $report = @{}
  332.        
  333.         $filter = New-Object VMware.Vim.TaskFilterSpec
  334.         $filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
  335.         $filter.Time.beginTime = (($snap.Created).AddDays(-5))
  336.         $filter.Time.timeType = "startedTime"
  337.        
  338.         $collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter))
  339.        
  340.         $dummy = $collectionImpl.RewindCollector
  341.         $collection = $collectionImpl.ReadNextTasks($tasknumber)
  342.         while($collection -ne $null){
  343.                 $collection | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $guestName} | %{
  344.                         $row = New-Object PsObject
  345.                         $row | Add-Member -MemberType NoteProperty -Name User -Value $_.Reason.UserName
  346.                         $vm = Get-View $_.Entity
  347.                         if($vm -ne $null){
  348.                                 $snapshot = Get-SnapshotTree $vm.Snapshot.RootSnapshotList $_.Result
  349.                                 if($snapshot -ne $null){
  350.                                         $key = $_.EntityName + "&" + ($snapshot.CreateTime.ToString())
  351.                                         $report[$key] = $row
  352.                                 }
  353.                         }
  354.                 }
  355.                 $collection = $collectionImpl.ReadNextTasks($tasknumber)
  356.         }
  357.         $collectionImpl.DestroyCollector()
  358.        
  359.         # Get the guest's snapshots and add the user
  360.         $snapshotsExtra = $snap | % {
  361.                 $key = $_.vm.Name + "&" + ($_.Created.ToString())
  362.                 if($report.ContainsKey($key)){
  363.                         $_ | Add-Member -MemberType NoteProperty -Name Creator -Value $report[$key].User
  364.                 }
  365.                 $_
  366.         }
  367.         $snapshotsExtra
  368. }
  369.  
  370. Function Set-Cred ($File) {
  371.         $Credential = Get-Credential
  372.         $credential.Password | ConvertFrom-SecureString | Set-Content $File
  373. }
  374.  
  375. Function Get-Cred ($User,$File) {
  376.         $password = Get-Content $File | ConvertTo-SecureString
  377.         $credential = New-Object System.Management.Automation.PsCredential($user,$password)
  378.         $credential
  379. }
  380.  
  381. If ($SetUsername -ne ""){
  382.         if ((Test-Path -Path $CredFile) -eq $false) {
  383.                 Set-Cred $CredFile
  384.         }
  385.         $creds = Get-Cred $SetUsername $CredFile
  386. }
  387.  
  388. $VIServer = Connect-VIServer $VISRV
  389. If ($VIServer.IsConnected -ne $true){
  390.         # Fix for scheduled tasks not running.
  391.         $USER = $env:username
  392.         $APPPATH = "C:\Documents and Settings\" + $USER + "\Application Data"
  393.  
  394.         #SET THE APPDATA ENVIRONMENT WHEN NEEDED
  395.         if ($env:appdata -eq $null -or $env:appdata -eq 0)
  396.         {
  397.                 $env:appdata = $APPPATH
  398.         }
  399.         $VIServer = Connect-VIServer $VISRV
  400.         If ($VIServer.IsConnected -ne $true){
  401.                 send-SMTPmail -to $EmailTo -from $EmailFrom -subject "ERROR: $VISRV Daily Report" -smtpserver $SMTPSRV -body "The Connect-VISERVER Cmdlet did not work, please check you VI Server."
  402.                 exit
  403.         }
  404.        
  405. }
  406.  
  407.  
  408. $VM = Get-VM
  409. $VMH = Get-VMHost
  410. $Clusters = Get-Cluster
  411. $Datastores = Get-Datastore
  412. $FullVM = Get-View -ViewType VirtualMachine
  413.  
  414. $MyReport = Get-CustomHTML "$VIServer Daily Report"
  415.         $MyReport += Get-CustomHeader0 ($VIServer.Name)
  416.                
  417.                 # ---- General Summary Info ----
  418.                 $MyReport += Get-CustomHeader "1" "General Details"
  419.                         $MyReport += Get-HTMLDetail "Number of Hosts:" (($VMH).Count)
  420.                         $MyReport += Get-HTMLDetail "Number of VMs:" (($VM).Count)
  421.                         $MyReport += Get-HTMLDetail "Number of Clusters:" (($Clusters).Count)
  422.                         $MyReport += Get-HTMLDetail "Number of Datastores:" (($Datastores).Count)
  423.                 $MyReport += Get-CustomHeaderClose
  424.                
  425.                 # ---- Snapshot Information ----
  426.                 $Snapshots = $VM | Get-Snapshot | Where {$_.Created -lt ((Get-Date).AddDays(-$SnapshotAge))} | Get-SnapshotSummary
  427.                 If (($Snapshots | Measure-Object).count -gt 0) {
  428.                         $MyReport += Get-CustomHeader "1" "Snapshots (Over $SnapshotAge Days Old)"
  429.                                 $MyReport += Get-HTMLTable $Snapshots
  430.                         $MyReport += Get-CustomHeaderClose
  431.                 }
  432.                                
  433.                 # ---- Datastore Information ----
  434.                 $OutputDatastores = $Datastores | Get-DatastoreSummary | Sort PercFreeSpace
  435.                 If (($OutputDatastores | Measure-Object).count -gt 0) {
  436.                         $MyReport += Get-CustomHeader "1" "Datastores (Less than $DatastoreSpace% Free)"
  437.                                 $MyReport += Get-HTMLTable $OutputDatastores
  438.                         $MyReport += Get-CustomHeaderClose
  439.                 }
  440.                
  441.                 # ---- VMs created or Cloned ----
  442.                 $VIEvent = Get-VIEvent -maxsamples 10000 -Start (Get-Date).AddDays(-$VMsNewRemovedAge)
  443.                 $OutputCreatedVMs = $VIEvent | where {$_.Gettype().Name -eq "VmCreatedEvent" -or $_.Gettype().Name -eq "VmBeingClonedEvent" -or $_.Gettype().Name -eq "VmBeingDeployedEvent"} | Select createdTime, @{N="User";E={(Find-Username (($_.userName.split("\"))[1])).Properties.displayname}}, fullFormattedMessage
  444.                 If (($OutputCreatedVMs | Measure-Object).count -gt 0) {
  445.                         $MyReport += Get-CustomHeader "1" "VMs Created or Cloned (Last $VMsNewRemovedAge Day(s))"
  446.                                 $MyReport += Get-HTMLTable $OutputCreatedVMs
  447.                         $MyReport += Get-CustomHeaderClose
  448.                 }
  449.                
  450.                 # ---- VMs Removed ----
  451.                 $OutputRemovedVMs = $VIEvent | where {$_.Gettype().Name -eq "VmRemovedEvent"}| Select createdTime, @{N="User";E={(Find-Username (($_.userName.split("\"))[1])).Properties.displayname}}, fullFormattedMessage
  452.                 If (($OutputRemovedVMs | Measure-Object).count -gt 0) {
  453.                         $MyReport += Get-CustomHeader "1" "VMs Removed (Last $VMsNewRemovedAge Day(s))"
  454.                                 $MyReport += Get-HTMLTable $OutputRemovedVMs
  455.                         $MyReport += Get-CustomHeaderClose
  456.                 }
  457.                
  458.                 # ---- VC Errors ----
  459.                 $OutputErrors = Get-VIEvent -maxsamples 10000 -Start (Get-Date).AddDays(-$VCEventAge ) -Type Error | Select createdTime, @{N="User";E={(Find-Username (($_.userName.split("\"))[1])).Properties.displayname}}, fullFormattedMessage
  460.                 If (($OutputErrors | Measure-Object).count -gt 0) {
  461.                         $MyReport += Get-CustomHeader "1" "Error Events (Last $VCEventAge Day(s))"
  462.                                 $MyReport += Get-HTMLTable $OutputErrors
  463.                         $MyReport += Get-CustomHeaderClose     
  464.                 }
  465.                
  466.                 # ---- No VM Tools ----
  467.                 $NoTools = $FullVM | Where { $_.Runtime.PowerState -eq "poweredOn" } | Select Name, @{N="ToolsVersion"; E={$_.Config.tools.toolsVersion}} | Where { $_.ToolsVersion -eq 0} | Select Name
  468.                 If (($NoTools | Measure-Object).count -gt 0) {
  469.                         $MyReport += Get-CustomHeader "1" "No VMTools"
  470.                                 $MyReport += Get-HTMLTable $NoTools
  471.                         $MyReport += Get-CustomHeaderClose
  472.                 }
  473.                
  474.                 # ---- CD-Roms Connected ----
  475.                 $CDConn = $VM | Where { $_ | Get-CDDrive | Where { $_.ConnectionState.Connected -eq "true" } } | Select Name, Host
  476.                 If (($CDConn | Measure-Object).count -gt 0) {
  477.                         $MyReport += Get-CustomHeader "1" "VM: CD-ROM Connected - VMotion Violation"
  478.                                 $MyReport += Get-HTMLTable $CDConn
  479.                         $MyReport += Get-CustomHeaderClose
  480.                 }
  481.                
  482.                 # ---- Floppys Connected ----
  483.                 $Floppy = $VM | Where { $_ |  Get-FloppyDrive | Where { $_.ConnectionState.Connected -eq "true" } } | Select Name, Host
  484.                 If (($Floppy | Measure-Object).count -gt 0) {
  485.                         $MyReport += Get-CustomHeader "1" "VM:Floppy Drive Connected - VMotion Violation"
  486.                                 $MyReport += Get-HTMLTable $Floppy
  487.                         $MyReport += Get-CustomHeaderClose
  488.                 }
  489.                
  490.                 # ---- Virtual Center Details ----
  491.                 $MyReport += Get-CustomHeader "1" "$VIServer Service Details"
  492.                         $MyReport += Get-HTMLTable (Get-VIServices)
  493.                 $MyReport += Get-CustomHeaderClose
  494.                
  495.                 # ---- Virtual Center Event Logs - Error ----
  496.                 $ConvDate = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::Now.AddDays(-$VCEvntlgAge))
  497.                 If ($SetUsername -ne ""){
  498.                         $ErrLogs = Get-WmiObject -Credential $creds -computer $VIServer -query ("Select * from Win32_NTLogEvent Where Type='Error' and TimeWritten >='" + $ConvDate + "'") | Where {$_.Message -like "*VMware*"} | Select @{N="TimeGenerated";E={$_.ConvertToDateTime($_.TimeGenerated)}}, Message
  499.                 } Else {
  500.                         $ErrLogs = Get-WmiObject -computer $VIServer -query ("Select * from Win32_NTLogEvent Where Type='Error' and TimeWritten >='" + $ConvDate + "'") | Where {$_.Message -like "*VMware*"} | Select @{N="TimeGenerated";E={$_.ConvertToDateTime($_.TimeGenerated)}}, Message
  501.                 }
  502.                
  503.                 If (($ErrLogs | Measure-Object).count -gt 0) {
  504.                         $MyReport += Get-CustomHeader "1" "$VIServer Event Logs: Error"
  505.                                 $MyReport += Get-HTMLTable ($ErrLogs)
  506.                         $MyReport += Get-CustomHeaderClose
  507.                 }
  508.                
  509.                 # ---- Virtual Center Event Logs - Warning ----
  510.                 $ConvDate = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::Now.AddDays(-1))
  511.                 If ($SetUsername -ne ""){
  512.                         $WarnLogs = Get-WmiObject -Credential $creds -computer $VIServer -query ("Select * from Win32_NTLogEvent Where Type='Warning' and TimeWritten >='" + $ConvDate + "'") | Where {$_.Message -like "*VMware*"} | Select @{N="TimeGenerated";E={$_.ConvertToDateTime($_.TimeGenerated)}}, Message
  513.                 } Else {
  514.                         $WarnLogs = Get-WmiObject -computer $VIServer -query ("Select * from Win32_NTLogEvent Where Type='Warning' and TimeWritten >='" + $ConvDate + "'") | Where {$_.Message -like "*VMware*"} | Select @{N="TimeGenerated";E={$_.ConvertToDateTime($_.TimeGenerated)}}, Message
  515.                 }
  516.                 If (($WarnLogs | Measure-Object).count -gt 0) {
  517.                         $MyReport += Get-CustomHeader "1" "$VIServer Event Logs: Warning"
  518.                                 $MyReport += Get-HTMLTable ($WarnLogs)
  519.                         $MyReport += Get-CustomHeaderClose
  520.                 }
  521.                        
  522.         $MyReport += Get-CustomHeader0Close
  523. $MyReport += Get-CustomHTMLClose
  524.  
  525. #Uncomment the following lines to save the htm file in a central location
  526. #$Date = Get-Date
  527. #$Filename = "C:\Temp\" + $VIServer + "DailyReport" + "_" + $Date.Day + "-" + $Date.Month + "-" + $Date.Year + ".htm"
  528. #$MyReport | out-file -encoding ASCII -filepath $Filename
  529. #Invoke-Item $Filename
  530.  
  531. send-SMTPmail $EmailTo $EmailFrom "$VISRV Daily Report" $SMTPSRV $MyReport
  532.  
  533. $VIServer | Disconnect-VIServer -Confirm:$false

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me