Get Host Alarms and Error Messages

vCenter alarms are good, but after you finish configuring emails for all the important alarms you want to receive that is when someone creates an email rule to ignore all these alarms. This started me down the path of adding an environment reporting email to let me know if there are any actual issues I need to worry about when I get to work in the morning.

Since the report I have runs at the same time each day I created a variable called “yesterday”. This will be used to find error messages that happened since yesterday’s run.

$yesterday = (Get-Date).AddDays(-1)

Then we need to find host error events. I’m getting every host, then getting all the error events for each host that were generated after $yesterday.

$hostErrors = Get-VMHost | Get-VIEvent -Types Error -Start $yesterday

Previously, I was filtering the start time for a CreatedTime greater than yesterday because I didn’t realize -Start and -Finish were options. I measured the difference and I saved over 2 minutes by using the -Start switch I saved over 150 seconds.

The output events have a lot of info we aren’t interested in. The only thing you need to capture is the Full Formatted Message

We’ll display the output using $hostErrors.FullFormattedMessage

Full script:

$yesterday = (Get-Date).AddDays(-1)
$hostErrors = Get-VMHost | Get-VIEvent -Types Error -Start $yesterday
$hostErrors.FullFormattedMessage

Now that’s great for error messages, but what about alarms?

First we’ll get all the hosts that have an active alarm.

$triggeredhosts = get-vmhost | get-view | where {$_.TriggeredAlarmState.OverallStatus -ne $null}

In my environment you can see that I have 1 host with an alarm, but when we view the TriggeredAlarmState we don’t see what the alarm is for or even the name of the host that has an alarm:

Now we need to do some lookups on this data to give us useful information. Because we can have more than 1 alarm at a time, we need to build a hash array and state populating data.

First we create the hash array:

$alarmReport = @()

Now we create a ForEach loop for every triggered event. We use $triggeredHosts.TriggeredAlarmState instead of just $triggeredHosts because we can have multiple alarms per host and since we’ll resolve the host name on each alarm in this loop this is an easier way to do it.

ForEach ($trigger in $triggeredHosts.TriggeredAlarmState) {

Then we resolve the host system ID to name:

$hostName = Get-VMHost | Where {$_.Id -eq $trigger.Entity}

Now we need to get the type of alarm:

$getAlarm = (Get-View -Id $trigger.Alarm).Info.Name

Then we define the columns for our array. We’re capturing host name, cluster name, the state of the host (connected, maintenance, not responding), and then the name of the alarm:

$row = "" | Select Host, Cluster, State, Alarm

Now we can populate our columns:

$row.Host = $hostName.Name
$row.Cluster = $hostName.Parent
$row.State = $hostName.State
$row.Alarm = $getAlarm

Now we add this row to the hash array and close the ForEach loop:

$alarmReport += $row }

And when we view the output of $alarmReport we see the host name, the cluster, the state, and the current active alarm.

Here’s the whole script:

$triggeredhosts = get-vmhost | get-view | where {$_.TriggeredAlarmState.OverallStatus -ne $null}
$alarmReport = @()
ForEach ($trigger in $triggeredHosts.TriggeredAlarmState) {
$hostName = Get-VMHost | Where {$_.Id -eq $trigger.Entity}
$getAlarm = (Get-View -Id $trigger.Alarm).Info.Name
$row = "" | Select Host, Cluster, State, Alarm
$row.Host = $hostName.Name
$row.Cluster = $hostName.Parent
$row.State = $hostName.State
$row.Alarm = $getAlarm
$alarmReport += $row }

Leave a Reply

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