Home > Alarm, PowerCLI, PowerShell > Alarms – Moving them around

Alarms – Moving them around

February 20th, 2010 Leave a comment Go to comments

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.

  1. Mark
    December 13th, 2011 at 20:41 | #1

    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.

    • December 15th, 2011 at 07:48 | #2

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

  2. CJ
    October 4th, 2011 at 13:59 | #3

    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.

  3. Jon
    August 9th, 2011 at 12:30 | #4

    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

    • August 9th, 2011 at 13:19 | #5

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

  4. Oleg
    July 5th, 2011 at 20:18 | #6

    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

    • July 5th, 2011 at 20:25 | #7

      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.

  5. Brad
    June 28th, 2011 at 18:53 | #8

    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.

    • June 29th, 2011 at 22:59 | #9

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

  6. June 15th, 2011 at 21:43 | #10

    Out of curiousity, how long does it take you to write a script like this?

    • June 15th, 2011 at 21:53 | #11

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

  7. Andrei Neagoe
    June 24th, 2010 at 11:33 | #12

    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…

    • June 25th, 2010 at 03:37 | #13

      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.

  8. February 24th, 2010 at 18:14 | #14

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

  1. January 6th, 2012 at 07:10 | #1