Another post triggered by a question in the VMTN PowerCLI community. The user wanted to know how he could create a report that showed for which vSphere entities the alarm actions were disabled.
To set the stage, a short overview of what this is all about. In vSphere you can, since vSphere 4, disable and enable alarm actions for all the managed entities. This option is available from the vSphere client
and from the vSphere Web client.
But how to automate these actions, and more importantly in this case, how to report on the active settings ? Like always PowerCLI to the rescue.
The script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
function Set-AlarmActionState { <# .SYNOPSIS Enables or disables Alarm actions .DESCRIPTION The function will enable or disable alarm actions on a vSphere entity itself or recursively on the entity and all its children. .NOTES Author: Luc Dekens .PARAMETER Entity The vSphere entity. .PARAMETER Enabled Switch that indicates if the alarm actions should be enabled ($true) or disabled ($false) .PARAMETER Recurse Switch that indicates if the action shall be taken on the entity alone or on the entity and all its children. .EXAMPLE PS> Set-AlarmActionState -Entity $cluster -Enabled:$true #> param( [CmdletBinding()] [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Entity, [switch]$Enabled, [switch]$Recurse ) begin{ $alarmMgr = Get-View AlarmManager } process{ if($Recurse){ $objects = @($Entity) $objects += Get-Inventory -Location $Entity } else{ $objects = $Entity } $objects | %{ $alarmMgr.EnableAlarmActions($_.Extensiondata.MoRef,$Enabled) } } } function Get-AlarmActionState { <# .SYNOPSIS Returns the state of Alarm actions. .DESCRIPTION The function will return the state of the alarm actions on a vSphere entity or on the the entity and all its children .NOTES Author: Luc Dekens .PARAMETER Entity The vSphere entity. .PARAMETER Recurse Switch that indicates if the state shall be reported for the entity alone or for the entity and all its children. .EXAMPLE PS> Get-AlarmActionState -Entity $cluster -Recurse:$true #> param( [CmdletBinding()] [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Entity, [switch]$Recurse = $false ) process { $Entity = Get-Inventory -Id $Entity.Id if($Recurse){ $objects = @($Entity) $objects += Get-Inventory -Location $Entity } else{ $objects = $Entity } $objects | Select Name, @{N="Type";E={$_.GetType().Name.Replace("Impl","").Replace("Wrapper","")}}, @{N="Alarm actions enabled";E={$_.ExtensionData.alarmActionsEnabled}} } } |
Annotations
Line 23: We declare the Entity parameter as a base Inventory object. That way you can pass all types of vSphere entities to the function.
Line 33-39,71-77: In the $objects variable the function collects all the entities involved. In case Recurse is True, all the child entities are obtained through the Get-Inventory cmdlet.
Line 41: The function calls the EnableAlarmActions method to change the alarm actions state of each entity. The value of the Enabled switch determines if the alarm actions will be enabled or disabled.
Line 70: This line makes sure we have the latest situation for the entity. Remember that the objects PowerCLI produces are not updated automatically when something changes in the entity.
Line 81: To make the Type property a bit more readable, the Impl and Wrapper suffixes are removed.
Sample usage
The Get-AlarmActionState function is quite easy to use. In the first example we will ask for the state of the alarms on a cluster
1 2 |
$cluster = Get-Cluster Cluster1 Get-AlarmActionState -Entity $cluster -Recurse:$false |
The result is displayed on the console as follows.
The function can also be used in a pipeline construct. The following lines will do exactly the same as the previous example.
1 2 |
Get-Cluster Cluster1 | Get-AlarmActionState -Recurse:$false |
To change the state of the alarm actions, we can use the Set-AlarmActionState function. The following example will disable the alarm actions on Cluster1 and all its children. To confirm the change, the samepl calls the Get-AlarmActionState function to display the state.
1 2 3 |
$cluster = Get-Cluster Cluster1 $cluster | Set-AlarmActionState -Enabled:$false -Recurse:$true $cluster | Get-AlarmActionState -Recurse:$true |
In the console output we can see that the state of the alarm actions has effectively been changed. And this for the cluster and all its child entities.
Another vSphere feature we can now use in our automation scripts.
Enjoy !
RA
Hello Luc,
I need to disable alarms at the vCenter level, anyway of doing this (it can be PowerCLI, API, all is fine).
I normally use something like this (which is based on your original script), but vCenter does not have a MoRef (or I don’t know how to get it).
$esx_host = Get-VMHost -Name $esxi_hostname
$alarmMgr = Get-View AlarmManager
ForEach ($hosts in $esx_host) {$alarmMgr.EnableAlarmActions($hosts.Extensiondata.MoRef,$true)}
Any help is much appreciated, thank you!
LucD
You can find the vCenters root, and it’s MoRef, with
Get-Folder -Name Datacenters
Then you could do
$alarmMgr = Get-View AlarmManager
$root = Get-Folder -Name Datacenters
$alarmMgr.EnableAlarmActions($root.ExtensionData.MoRef, $true)
RA
Wow Luc…I’ve spent the best part of today trying to find how to do this, thank you so much!
I’m going to abuse your kindness and ask you if you have any clue on the URI required to do this through API (reason is that this is an Ansible project and I’m trying to limit using PowerCLI as much as possible due to time taken for login).
Thank you again!
LucD
Afaik, the methods available through the AlarmManager are not available through any REST API (yet).
You could call the method via the MOB using the Invoke-WebRequest cmdlet.
But that is definitely not done through a simple URI, it will be again a script.
You will have to authenticate and pass the correct parameters in the Body.
RA
Thanks for the tip Luc, I’ll def look into that since I can use Ansible URI module to do that.
AlChard
Hello Luc,
Good Day.
Newbie here on PowerShell/PowerCLI and in general in scrpting. I’ve tried to use this:
$cluster = Get-Cluster MyClusterName
Get-AlarmActionState -Entity $cluster -Recurse:$false
Apparently, it seemed when I tried to type in or look for Get-AlarmActionState there is none so that script doesn’t worked – it says is not recognized as the name of the cmdlet, function. 🙁
I hope this message will reach you and you can help me out.
Thank you in advance.
LucD
Hi,
You have to make the functions “known” to PowerShell.
You can do that by dot-sourcing the .ps1 file into which you copy the functions.
– copy the code to a .ps1 file, for example AlarmActionState.ps1
– dot-source that .ps1 file. Note that space between the 2 dots
. .\AlarmActionState.ps1
Now you can call Get-AlarmActionState and Set-AlarmActionState
AlChard
I’ve save that exact same parameter to a txt file then renamed to .ps1 file on my desktop and open powershell cmd then go to my desktop directory and key in this:
. .\AlarmActionState.ps1 (with a space on the middle of both dots)
But another error comes out that Get-Cluster is not recognize as the name of a cmdlet then another error on the Get-AlarmActionState same error as the first time it runs.
LucD
Did you save the code for both functions from the blog post to that .ps1 file?
I mean the code you find under The Script section in the blog post.
If Get-Cluster is not recognised that could mean that
– PowerCLI is not installed
– that the $env:PSModulePath doesn’t include the folder where you installed PowerCLI.
AlChard
It looks like I understood it already however it now’s throws the error:
Unable to find type Unable to find type [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]
ps1:65 char:5
LucD
It looks like your PowerCLI installation might have issues.
I would suggest removing and reinstalling PowerCLI
AlChard
Thanks Luc, I was able to execute the below parameter in PowerCLI with no issue:
$cluster = Get-Cluster Cluster1
Get-AlarmActionState -Entity $cluster -Recurse:$false
However, when I changed the recurse value to true it throws this error below, I got a result for Resource Pool, Cluster and VMHost but there where 2 VMs that are not included or missing (one is powered on and the other is powered off):
Get-Inventory exception has been thrown by the target of an invocation
ps1:73 char:19
Any idea what went wrong?
Srinivas
Hi LucD
we have the following challenge on the vCenter payload / snmp message:
VCenter is configured with an alert name, and separate from that, with a Description. However, when the SNMP message goes out, “the system” is combining the alert name together with the Description in a single string. For example:
The settings are:
• Alert Name: Infra_*
• Description: datastore at 85% utilization.
But the SNMP message has
* Infra_* datastore at 85% utilization.
The problem is that since the percentage is a variable, if the ticket is not yet close and another alerts goes out at 90%, then monitoring tool will think it is a different incident and create a new ticket.
Therefore, we want is for vCenter to keep the Alert name and the description separate from each other. Can this be achieved in script? if so can you please help on this.
LucD
I’m afraid that is a vCenter internal, and hence can’t be changed.
You could split the SNMP message on arrival at the SNMP Manager and only keep the Name part.
Srinivas
Thanks a lot for your response, much appreciated your service.
Is there anything we can do scripting to split if we opt for send alerts in mail.
LucD
You can use a number of variables in the Subject and Body of the emails.
Just use curly braces with the action name.
{alarmName} with event {eventDescription}
Note that the action list values are rather limited
Srinivas
Luc, can you help with some scripts if you already have or can you please share some reference links for scripts.
LucD
William has an example in Customizing vCenter Alarm Email Subject and Body
Srinivas
Thanks a lot Luc again.
Som
Is there a way to disable a single alarm for a specific object?
Ex: Disable only 1 specific alarm for a specific VM, where the alarm is defined at the vCenter Level and cannot be disabled on the VM itself?
LucD
Hi,
I’m afraid that is not possible.
Luc
Som
Thank you for the update brother.
I can finally stop searching for a way to get this done now.
David Griswold
Sorry to necro an old post, but 1) is this code still valid? and 2) has it been replaced by any newer PowerCLI cmdlets?
LucD
Hi David,
Yes, that code is still valid (just tried it in a vSphere7 environment).
Although there have been a number of Alarm related cmdlets since this post was published, afaik none of those offers to possibility to check if Alarm actions are enabled for a specific entity.
Jeff NOTEBAERT
Luc
I forgot to ask, do there is a way to track who disable the alarm of a device (owner) ?
Thanks
Jeff NOTEBAERT
Luc
Thanks for this nice function. I’m trying to use it in my environment to generate a report of all disable devices (cluster, VM host, VM, …)
Do you know why this filter doesn’t work ?
Get-AlarmActionState -Entity $cluster -Recurse:$true | where {$_.Alarm_actions_enabled -eq “False”} # | Select Name, type
Thanks
LucD
Hi Jeff,
The property you want to use in the Where-clause has some blanks in it, so you’ll have to place the propertyname between quotes. Like this
where {$_."Alarm actions enabled" -eq "False"}
You can do auditing of changes to an alarm definition by tracking the AlarmReconfiguredEvent entries in the events DB.
Let me know if you need some help with such a script ?
Satish
LucD,
I need to be notified whenever an VCenter alarm is enabled or disabled along with person’s name who performed the action.
Can you suggest if any script for this?
Regards,
Satish
LucD
Hi Satish,
I would look at the AlarmReconfiguredEvent events, if someone changes enabled/disabled, it should be in these events.
Dimple
Hi Lucd,
I do have the requirement to find who and when the alarm was disabled on an entity like cluster. Can you help me with it please.
Thanks
Dimple
Ravi
having issue, some one cleared the vcenter hardware alarm , how to collect host having hardware issue, is there any powercli script ?
LucD
Hi Ravi,
Sorry for not replying sooner.
With my Get-VIEventPlus function you can do something like this
function Get-VIEventPlus {
<# .SYNOPSIS Returns vSphere events .DESCRIPTION The function will return vSphere events. With the available parameters, the execution time can be improved, compered to the original Get-VIEvent cmdlet. .NOTES Author: Luc Dekens .PARAMETER Entity When specified the function returns events for the specific vSphere entity. By default events for all vSphere entities are returned. .PARAMETER EventType This parameter limits the returned events to those specified on this parameter. .PARAMETER Start The start date of the events to retrieve .PARAMETER Finish The end date of the events to retrieve. .PARAMETER Recurse A switch indicating if the events for the children of the Entity will also be returned .PARAMETER User The list of usernames for which events will be returned .PARAMETER System A switch that allows the selection of all system events. .PARAMETER ScheduledTask The name of a scheduled task for which the events will be returned .PARAMETER FullMessage A switch indicating if the full message shall be compiled. This switch can improve the execution speed if the full message is not needed. .EXAMPLE PS> Get-VIEventPlus -Entity $vm
.EXAMPLE
PS> Get-VIEventPlus -Entity $cluster -Recurse:$true
#>
param(
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]$Entity,
[string[]]$EventType,
[DateTime]$Start,
[DateTime]$Finish = (Get-Date),
[switch]$Recurse,
[string[]]$User,
[Switch]$System,
[string]$ScheduledTask,
[switch]$FullMessage = $false
)
process {
$eventnumber = 100
$events = @()
$eventMgr = Get-View EventManager
$eventFilter = New-Object VMware.Vim.EventFilterSpec
$eventFilter.disableFullMessage = ! $FullMessage
$eventFilter.entity = New-Object VMware.Vim.EventFilterSpecByEntity
$eventFilter.entity.recursion = &{if($Recurse){"all"}else{"self"}}
$eventFilter.eventTypeId = $EventType
if($Start -or $Finish){
$eventFilter.time = New-Object VMware.Vim.EventFilterSpecByTime
if($Start){
$eventFilter.time.beginTime = $Start
}
if($Finish){
$eventFilter.time.endTime = $Finish
}
}
if($User -or $System){
$eventFilter.UserName = New-Object VMware.Vim.EventFilterSpecByUsername
if($User){
$eventFilter.UserName.userList = $User
}
if($System){
$eventFilter.UserName.systemUser = $System
}
}
if($ScheduledTask){
$si = Get-View ServiceInstance
$schTskMgr = Get-View $si.Content.ScheduledTaskManager
$eventFilter.ScheduledTask = Get-View $schTskMgr.ScheduledTask |
where {$_.Info.Name -match $ScheduledTask} |
Select -First 1 |
Select -ExpandProperty MoRef
}
if(!$Entity){
$Entity = @(Get-Folder -Name Datacenters)
}
$entity | %{
$eventFilter.entity.entity = $_.ExtensionData.MoRef
$eventCollector = Get-View ($eventMgr.CreateCollectorForEvents($eventFilter))
$eventsBuffer = $eventCollector.ReadNextEvents($eventnumber)
while($eventsBuffer){
$events += $eventsBuffer
$eventsBuffer = $eventCollector.ReadNextEvents($eventnumber)
}
$eventCollector.DestroyCollector()
}
$events
}
}
$Start = (Get-Date).AddDays(-31)
Get-VIEventPlus -Start $start -EventType AlarmClearedEvent |
Select CreatedTime,UserName,FullFormattedMessage
Sam
hi LucD
my custom told me must be used the power cli to distable or enabel the alarm state ,i have used your script verygood haha thinks a lot 🙂
Rajan
Is this script working with PowerCli 5.1 Release 2. I am getting below error while running set-Alarmactionstate function
Exception calling “EnableAlarmActions” with “2” argument(s): “The object has already been deleted or has not been completely created”
At line:38 char:7
+ $alarmMgr.EnableAlarmActions($_.Extensiondata.MoRef,$Enabled)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : VimException
Michael
Hi Luc,
I´ve tried your code into PowerCLI 5.1 but I doesn´t work. I got te following error:
Get-AlarmActionState : Die Argumenttransformation für den Parameter "Entity" kann nicht verarbeitet werden. Der Wert "HAL-PROD_CL1" vom Typ "System.String" kann nicht in den Typ "VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl" konvertiert werden.
Bei Zeile:1 Zeichen:29
+ Get-AlarmActionState -Entity <<<< HAL-PROD_CL1
+ CategoryInfo : InvalidData: (:) [Get-AlarmActionState], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-AlarmActionState
Do you know the problem and how I could solve it? THis would be fine.
Thanks
Vman
Don’t know what I’m doing wrong. If I save this as a ps1 file and run it from powercli, I get nothing.
If try to run the Get-AlarmActionstate sample code, I get Errors running Get-alarmtionactionstate. (sigh)
What am I missing?
LucD
@Vman, when you download functions you have to save them in a .ps1 file. That .ps1 on itself will not do anything.
To make the 2 functions usable from the PS prompt or in your own scripts, you will have to dot-source the .ps1 file containing the functions.
PS C:\Scripts> . ./functions.ps1
There is a blank between the 2 dots, and it assumes the .ps1 file is saved in the folder C:\Scripts.
Once this is done, you can call any of the 2 functions as shown in the Sample Usage section.
Sam
@LucD,i have save the Script to the “C:\Sctriptis\” named functions.ps1.
i open the powercli and run “C:\Scripts> . ./functions.ps1” after this
PowerCLI C:\> c:\Scripts>../functions.ps1
无法将“c:\Scripts>../functions.ps1”项识别为 cmdlet、函数、脚本文件或可运行程
序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后重试。
所在位置 行:1 字符: 28
+ c:\Scripts>../functions.ps1 <<<../functions.ps1:Str
ing) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PowerCLI C:\>
Neil
Interesting article, it’s exactly what I’m looking for. However, when I run the function Get-AlarmActionState, I get the following error:
Unexpected token ‘State’ in expression or statement.
At line:25 char:33
+ $objects = @($Entity)State <<<<
+ CategoryInfo : ParserError: (State:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
I'll see if I can work it out, but just thought I'd give you a heads up.
Regards
admin
Thanks Neil, good catch.
That “State” shouldn’t be there. I updated the post.
Sorry about that