Alarms – Moving them around
You should know by now that alarms are a powerful tool to help you manage and monitor your vSphere environment. But in my opinion there is a basic operation missing.
There is no easy way to move an alarms from one entity to another entity. No drag-and-drop in the vSphere Client, no Move-Alarm cmdlet in PowerCLI.
A practical example, you have developed this fantastic new alarm and for testing purposes you had defined it on a single virtual machine. Now the tests are done and your alarm is ready for production. But there is apparently no easy way to move your new alarm to the root of your vSphere environment.
Luckily we have PowerCLI and we can easily create a function to fill this gap.
The script
The function is called Move-Alarm and has the following syntax:
Move-Alarm -Alarm <Alarm> -From <ViContainer> -To <ViContainer[]> -DeleteOriginal
-Alarm: the MoRef of the Alarm object you want to move
-From: the ViContainer from where the alarm should be moved
-To: one or more ViContainer objects to which the alarm should be moved
-DeleteOriginal: a switch that determines what happens with the original alarm. Default is $false
Update 23/02/10
While using the script I discovered that the length of the name of an alarm can not exceed 80 characters. This seems to be an undocumented “feature”.
A second problem in the original script was that when you “move” to more than one destination, there would be an error message on the second “move”. That was because you can not have two alarms with the same name in your vCenter. The solution I used was to add the name of the destination entity as a suffix to the name of the new alarm.
The third problem was the Status property in each EventAlarmExpression object. Since the script copies the AlarmInfo object from the “from” alarm to the AlarmSpec object for the “to” alarm, the Status property has to blanked out explicitly.
Set-Variable -Name alarmLength -Value 80 -Option "constant"
$from = Get-Folder -Name "Datacenters" | Get-View
$to1 = Get-Folder -Name "Folder1" | Get-View
$to2 = Get-Folder -Name "Folder2" | Get-View
function Move-Alarm{
param($Alarm, $From, $To, [switch]$DeleteOriginal = $false)
$alarmObj = Get-View $Alarm
$alarmMgr = Get-View AlarmManager
if($deleteOriginal){
$alarmObj.RemoveAlarm()
}
else{
$updateAlarm = New-Object VMware.Vim.AlarmSpec
$updateAlarm = $alarmObj.Info
$oldName = $alarmObj.Info.Name
$oldState = $alarmObj.Info.Enabled
$oldDescription = $alarmObj.Info.Description
$suffix = " (moved to " + ([string]($to | %{$_.Name + ","})).TrimEnd(",") + ")"
if(($oldName.Length + $suffix.Length) -gt $alarmLength){
$newName = $oldName.Substring(0, $alarmLength - $suffix.Length) + $suffix
}
else{
$newName = $oldName + $suffix
}
$updateAlarm.Name = $newName
$updateAlarm.Enabled = $false
$updateAlarm.Description += ("`rOriginal name: " + $oldName)
$updateAlarm.Expression.Expression | %{
if($_.GetType().Name -eq "EventAlarmExpression"){
$_.Status = $null
$needsChange = $true
}
}
$alarmObj.ReconfigureAlarm($updateAlarm)
$alarmObj.Info.Name = $oldName
$alarmObj.Info.Enabled = $oldState
$alarmObj.Info.Description = $oldDescription
}
$newAlarm = New-Object VMware.Vim.AlarmSpec
$newAlarm = $alarmObj.Info
$oldName = $alarmObj.Info.Name
$oldDescription = $alarmObj.Info.Description
foreach($destination in $To){
if($To.Count -gt 1){
$suffix = " (" + $destination.Name + ")"
if(($oldName.Length + $suffix.Length) -gt $alarmLength){
$newName = $oldName.Substring(0, $alarmLength - $suffix.Length) + $suffix
}
else{
$newName = $oldName + $suffix
}
$newAlarm.Name = $newName
$newAlarm.Description += ("`rOriginal name: " + $oldName)
}
$newAlarm.Expression.Expression | %{
if($_.GetType().Name -eq "EventAlarmExpression"){
$_.Status = $null
$needsChange = $true
}
}
$alarmMgr.CreateAlarm($destination.MoRef,$newAlarm)
$newAlarm.Name = $oldName
$newAlarm.Description = $oldDescription
}
}
$alarmMgr = Get-View AlarmManager
$alarms = $alarmMgr.GetAlarm($from.MoRef)
$alarms | % {
Move-Alarm -Alarm $_ -From (Get-View $_) -To $to1,$to2 -DeleteOriginal:$false
}
Annotations
Line 1: The maximum length of the name of an Alarm defined as a constant.
Line 3-5: Variables that will be used later on in the script as parameters to the function. In the sample I’m moving all alarms from the vCenter root (hidden entity “Datacenters”) to two folders called “Folder1″ and “Folder2″
Line 8: Note that the function doesn’t use strongly types parameters for the -From and -To parameters. This is because the ViObjects on which alarms can be defined can be of several types (Datacenter, Folder, HostSystem…). This also allows to pass an array of ViObjects for the -To parameter.
Line 14: If the -DeleteOriginal switch is set to $true, the original alarm will be deleted.
Line 17-35: If the -DeleteOriginal switch is set to $false the original Alarm will be kept but it will be renamed since there can not be multiple alarms with the same name.
Line 24,48: If the length of name with the suffix exceeds 80 characters, the script will remove sufficient characters from the original alarmname to be able to add the suffix.
Line 29: If the original alarm is kept it will be renamed. The original will get a suffix “(moved to <dest>)”
Line 30: If the original alarm is kept it will be “disabled”.
Line 31,54: The script adds the original alarmname to the Description field.
Line 32-37,64-69: Since the script copies the AlarmSpec object from the original alarm, the Status field for all the EventAlarmExpression objects needs to blanked out.
Line 52: The -To parameter is handled in a foreach loop since the function allows more than one destination. The function can be used as a 1-to-n move in this case.
Line 80-81: A sample use case of the Move-Alarm function. All Alarms defined in the root of the vCenter will be “moved” to “Folder1″ and “Folder2″. The original Alarm will not be deleted but it will be renamed and disabled.
Samples
Before the run of the above sample use of the script, the alarms defined on the vCenter root look like this.
After the first call of the Move-Alarm function the first alarm has been changed and disabled.
And on both target folders the alarm has been created as this screenshot from the alarms on Folder1 shows.
This is a rather simple function but it can be quite useful at times. I hope it can be of use to some of you.




Luc
Thanks for this script. I hope you can help me understand how to move a single alarm from the root of the datacenter to a folder. I understand about changing the $from and $to lines at the top, but I’m uncertain how to select a single alarm. I tried modifying:
Move-Alarm -Alarm “Virtual machine total disk latency” -From $from -To $to1 -DeleteOriginal:$false
but that resulted in an error that the alarm wasn’t found. I don’t understand the syntax necessary to define the alarm properly for the get-view cmdlet.
@Mark, that function expects an Alarm object as a parameter. In other words a server-side, or SDK, object.
You can do
$alarm = (Get-AlarmDefinition -Name “Virtual machine total disk latency”).ExtensionData
Move-Alarm -Alarm $alarm -From $from -To $to1 -DeleteOriginal:$false
I hope this helps.
Luc,
I can’t thank you enough for your time & effort. Thanks for an awesome book & for all your work. It is making me a better scripter and helping me to understand script writing but more specifically PowerCLI better. I look forward to the day when I can write scripts with the speed & proficiency that you do.
Hi Luc,
I’m investigating migrating a set of defined alarms from one vCenter to another. I have a script that works if I have direct connection to both vCenters.
I’m trying to work out how to perform the migration if I don’t have direct access to both vCenter servers simultaneously.
Is there any way to export alarm(s) to output file(s) and then import them?
Cheers,
Jon
@Jon, in fact there is. I described the method in our book.
The functions are available ion the Sybex website.
You want the Get-AlarmScript function from chapter 16. This function will take an alarm and produce a .ps1 script that creates that same alarm. Once you have the .ps1 script, it’s a matter of executing that .ps1 script on the new vCenter.
I hope this helps to solve your problem.
Luc,
Did you see this KB http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1026429?
Per Vmware by disabling any alarm on object (VM, Host, etc.) you are disabling all alarms on the same objects on all VC; at least you should not count on them.
Thanks,
Oleg
Hi Oleg, thanks for the info.
Yes, I know that KB, but this was a bug that is fixed in 4.1 Update 1.
If you’re on 4.0 or 4.1, the described problem can indeed occur.
I’m afraid that I don’t understand the usage here — I have several alarms defined under the vCenter object and need them moved to a cluster level. Is that possible with this script? I’ve tried a couple things and all of my alarms end up getting renamed and disabled but not moved.
@Brad, the trick is in the setting of the To and From parameters.
To move from the vCenter root to a specific cluster, you will have to replace the 3 lines at the beginning with
$from = Get-Folder -Name "Datacenters" | Get-View
$to = Get-Cluster -Name "MyCluster" | Get-View
and the call to the actual function at the end will become
$alarms = $alarmMgr.GetAlarm($from.MoRef)
$alarms | % {
Move-Alarm -Alarm $_ -From (Get-View $_) -To $to -DeleteOriginal:$false
}
Is that understandable ?
Otherwise I’ll do a rewrite of that post and add some more examples.
Out of curiousity, how long does it take you to write a script like this?
@Conrad, the classic answer it depends
Seriously, most of the time my post ideas come from pieces of code that I already have.
That code was created for a practical problem in our environment or as an answer to a post in the PowerCLI Community.
For publication I have to generalise it, polish it up, test it and write the post.
This particular one started of from some existing code and it took me 2 evenings to make the post ready for publication.
Hey Luc,
In my case it would be nice to be able to copy the definitions from one vCenter to another. How should I tackle this? I’m not exactly sure how to use a script against two vCenter instances…
Hi Andrei,
With the latest PowerCLI build you can configure PowerCLI to run in multi-mode, which means you can open several vCenters and specify on the cmdlets against which vCenter they should run (that’s mostly through the -Server parameter).
Now this script use several SDK methods, where it is not so obvious to specify against which vCenter a SDK method should be executed.
I would start by investigating how the AcquireCloneTicket and CloneSession methods could be used.
But I’m not sure if that would solve the different sessions problems. It would require further investigation.
Luc.
Luc
As always I admire your dedication to solving real world admin problems using powercli. I do a lot of work with alarms and can see this coming in use at some point.
Can we take it this is your submission to the script-o-mania competition
Thanks Sham.
No, this is not my Script-O-Mania submission (yet)