VMware Cloud Community
nikpetrov95
Contributor
Contributor
Jump to solution

Create a custom CPU alarm for VM using PowerCli

Hello! I need to create an alarm on the CPU for each virtual machine, after the alarm has worked, I need to send a message to the user's mail, mail information should be taken from the user attribute of VM (I did it myself). Please help me with this matter.

Tags (1)
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

It looked like that from the previous screenshot.

But if you want to do this for multiple VMs, the script need some changes.

Something like this

Get-VM -Name 'Test1', 'Test2' -PipelineVariable vm |

ForEach-Object -Process {

    $userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').value

    $sAlarmTrigger = @{

        Metric              = Get-Metric -MetricGroup 'CPU' -Name 'usage' | Select-Object -First 1

        MetricAlarmOperator = 'Above'

        Yellow              = 50

        Red                 = 75

        EntityType          = 'VirtualMachine'

    }

    $trigger = New-AlarmTrigger @sAlarmTrigger


    $sAlarmAction = @{

        Email   = $true

        Subject = 'CPU Usage high'

        To      = $userEmail

    }

    $action = New-AlarmAction @sAlarmAction


    $sAlarmDef = @{

        Name         = 'CPU High'

        Description  = 'Trigger alarm when CPU utilisation is too high'

        Entity       = $vm

        AlarmTrigger = $trigger

        AlarmAction  = $action

    }


    New-AlarmDefinition @sAlarmDef

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

43 Replies
LucD
Leadership
Leadership
Jump to solution

Can you provide some more details about the requirement?

What do you mean by "... alarm on the CPU"?
Is that when CPU utilisation goes over a specific watermark?

Also, what do you mean by "... mail information should be taken from the user attribute"?

Is that the email To address?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

What do you mean by "... alarm on the CPU"?-  for example standart vcenter alarm "Virtual machine CPU usage"

Is that when CPU utilisation goes over a specific watermark? - Yes, it is

I need to create an alarm action on each virtual machine (by the name of the machine) this is the main requirement

Also, what do you mean by "... mail information should be taken from the user attribute"?

Is that the email To address?

foreach($vmName in $vmNames){

$entity = Get-VM -Name $vmName

$mail=(Get-Annotation -Entity (get-vm $vmName) -CustomAttribute Contact).value

$action = New-AlarmAction -Email -Subject 'Test' -To "$mail" -AlarmDefinition $def

I need something like this:

pastedImage_11.png

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is in fact the solution.
What is missing from that code?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

I can't found this part for cpu

$stat = 'disk.used.latest'

$statSplit = $stat.Split('.')

$si = Get-View ServiceInstance

$perfMgr = Get-View -Id $si.Content.PerfManager

$metric = $perfMgr.PerfCounter | where{$_.GroupInfo.Key -eq $statSplit[0] -and $_.NameInfo.Key -eq $statSplit[1] -and $_.RollupType -eq $statSplit[2]}

$alarmMgr = Get-View AlarmManager

$entity = Get-View -ViewType VirtualMachine -Filter @{'Name'=$vmName}

$spec = New-Object VMware.Vim.AlarmSpec

$spec.Name = $alarmName

$spec.Enabled = $true

$spec.Description = $alarmDescription

$metricId = New-Object VMware.Vim.PerfMetricId

$metricId.CounterId = $metric.Key

$metricId.Instance = ''

$expression = New-Object VMware.Vim.MetricAlarmExpression

$expression.Metric += $metricId

$expression.Type = 'VirtualMachine'

$expression.Operator = [VMware.Vim.MetricAlarmOperator]::isAbove

$expression.Yellow = $yellowGB * 1MB

$expression.Red = $redGB * 1MB

$spec.Expression = $expression

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

In the recent PowerCLI release there are new cmdlets to create metric based alarms.

Something like this

$vm = Get-VM -Name MyVM

$userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').value

$sAlarmTrigger = @{

    Metric = Get-Metric -MetricGroup 'CPU' -Name 'usage' | select -First 1

    MetricAlarmOperator = 'Above'

    Yellow = 50

    Red = 75

    EntityType = 'VirtualMachine'

}

$trigger = New-AlarmTrigger @sAlarmTrigger


$sAlarmAction = @{

    Email = $true

    Subject = 'CPU Usage high'

    To = $userEmail

}

$action = New-AlarmAction @sAlarmAction


$sAlarmDef = @{

    Name = 'CPU High'

    Description = 'Trigger alarm when CPU utilisation is too high'

    Entity = $vm

    AlarmTrigger = $trigger

    AlarmAction = $action

}

New-AlarmDefinition @sAlarmDef


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

Thank you, but I had error if I use 2 or more vms.

Get-Annotation: Cannot convert "System.Object []" to type "VMware.VimAutomation.ViCore.Types.V1.Inventory.Inven
toryItem "required for the Entity parameter. The specified method is not supported.
line: 1 character: 38
+ $ userEmail = (Get-Annotation -Entity $ vm -CustomAttribute 'Contact').

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You seem to have a blank between $ and vm on the Entity parameter


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

I haven't blunk between $ and vm

$vm = Get-VM -Name "test1","test2"

$userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').value

Get-Annotation : Не удается преобразовать "System.Object[]" в тип "VMware.VimAutomation.ViCore.Types.V1.Inventory.InventoryItem", необходимый для п

араметра "Entity". Указанный метод не поддерживается.

строка:1 знак:38

+ $userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

It looked like that from the previous screenshot.

But if you want to do this for multiple VMs, the script need some changes.

Something like this

Get-VM -Name 'Test1', 'Test2' -PipelineVariable vm |

ForEach-Object -Process {

    $userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').value

    $sAlarmTrigger = @{

        Metric              = Get-Metric -MetricGroup 'CPU' -Name 'usage' | Select-Object -First 1

        MetricAlarmOperator = 'Above'

        Yellow              = 50

        Red                 = 75

        EntityType          = 'VirtualMachine'

    }

    $trigger = New-AlarmTrigger @sAlarmTrigger


    $sAlarmAction = @{

        Email   = $true

        Subject = 'CPU Usage high'

        To      = $userEmail

    }

    $action = New-AlarmAction @sAlarmAction


    $sAlarmDef = @{

        Name         = 'CPU High'

        Description  = 'Trigger alarm when CPU utilisation is too high'

        Entity       = $vm

        AlarmTrigger = $trigger

        AlarmAction  = $action

    }


    New-AlarmDefinition @sAlarmDef

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

nikpetrov95
Contributor
Contributor
Jump to solution

Excellent! It works.

How can I use the miltipale mail address?

New-AlarmAction: Unable to bind the "To" parameter to the target. Exception when setting "To": "Invalid email address: 1@test.com; 2@test.om "

pastedImage_1.png

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Multiple mail addresses should be separated with a comma afaik.

Try replacing the ; with a ,


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

The comma did n't help

New-AlarmAction :Cannot bind “To” parameter to target. An exception "To" : "Invalid email address: 1@test.com,2@test.com"

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Seems to work for me with an array of strings

To      = 'user1@local.lab','user2@local.lab'

In your case you could try

To      = $userEmail.Split(';')


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

It's work! Thank you so much!

Get-VM -Name 'Test1','Test2' -PipelineVariable vm |

ForEach-Object -Process {

    $userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').value

    $sAlarmTrigger = @{

        Metric              = Get-Metric -MetricGroup 'CPU' -Name 'usage' | Select-Object -First 1

        MetricAlarmOperator = 'Above'

        Yellow              = 50

        Red                 = 75

        EntityType          = 'VirtualMachine'

    }

    $trigger = New-AlarmTrigger @sAlarmTrigger

    $sAlarmAction = @{

        Email   = $true

        Subject = 'CPU Usage high'

        To      = $userEmail.Split(';')

    }

    $action = New-AlarmAction @sAlarmAction

    $sAlarmDef = @{

        Name         = "CPU High_$vm"

        Description  = 'Trigger alarm when CPU utilisation is too high'

        Entity       = $vm

        AlarmTrigger = $trigger

        AlarmAction  = $action

    }

    New-AlarmDefinition @sAlarmDef

}

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

LucD​ Hello, how  I can create $sAlarmTrigger like this?

pastedImage_1.png

or set time option for this

  $sAlarmTrigger = @{

        Metric              = Get-Metric -MetricGroup 'CPU' -Name 'usage' | Select-Object -First 1

        MetricAlarmOperator = 'Above'

        Yellow              = 50

        Red                 = 75

        EntityType          = 'VirtualMachine'

    }

    $trigger = New-AlarmTrigger @sAlarmTrigger

and I had incorrect alarms

Target: Test1

Previous Status: Gray

New Status: Red

Alarm Definition:

([Yellow metric Is above 0%; Red metric Is above 0%] OR [Yellow metric Is above 0%; Red metric Is above 0%])

Current values for metric/state:

Metric CPU Usage = 30% OR Metric CPU Usage = 30%

Description:

Alarm 'CPU High_test1' on MSK-DPRO-APL555 changed from Gray to Red

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There were a few issues with my previous solution.

The Get-Metric cmdlet doesn't really one to select the correct metric.

The values for the thresholds need to be multiplied by 100.

And the duration can be defined.

My new version which should fix the issues.

$vmNames = 'test01','test02'

$metricName = 'cpu.usage.average'


$mGroup,$mName,$mRollup = $metricName.Split('.')

$si = Get-View ServiceInstance

$perfMgr = Get-View -Id $si.Content.PerfManager

$metric = $perfMgr.PerfCounter |

    where{$_.GroupInfo.Key -eq $mGroup -and

          $_.NameInfo.Key -eq $mName -and

          $_.RollupType -eq $mRollup}


Get-VM -Name $vmNames-PipelineVariable vm |

ForEach-Object -Process {

    $userEmail = (Get-Annotation -Entity $vm -CustomAttribute 'Contact').value

    $sAlarmTrigger = @{

        Metric              = Get-Metric -MetricGroup 'CPU' -Name 'usage' | where{$_.Key -eq $metric.Key}

        MetricAlarmOperator = 'Above'

        Red                 = 7500

        RedIntervalSeconds  = 300

        EntityType          = 'VirtualMachine'

    }

    $trigger = New-AlarmTrigger @sAlarmTrigger


    $sAlarmAction = @{

        Email   = $true

        Subject = 'CPU Usage high'

        To      = $userEmail.Split(';')

    }

    $action = New-AlarmAction @sAlarmAction


    $sAlarmDef = @{

        Name         = 'CPU High'

        Description  = 'Trigger alarm when CPU utilisation is too high'

        Entity       = $vm

        AlarmTrigger = $trigger

        AlarmAction  = $action

    }


    New-AlarmDefinition @sAlarmDef

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

Thank you!

Reply
0 Kudos
nikpetrov95
Contributor
Contributor
Jump to solution

Hi LucD, I need your help again .... I can't set up a mail resend(after 5 minutes) notification for this alarm. can you help me?

I can only do this after creating an alarm and can't change the source of the alarm, and therefore additional steps must be taken.

Get-AlarmDefinition -Name "CPU High DBA340"| Get-AlarmAction | New-AlarmActionTrigger -StartStatus Red -EndStatus Yellow -Repeat

Get-AlarmDefinition -Name "CPU High DBA340"| Get-AlarmAction|Get-AlarmActionTrigger |select -First 1 | Remove-AlarmActionTrigger -Confirm:$false

Get-AlarmDefinition -Name "CPU High DBA340"| Get-AlarmAction | set-AlarmActionTrigger -StartStatus Yellow -EndStatus Red -Repeat

Get-AlarmDefinition -Name "CPU High DBA340"| Get-AlarmAction|Get-AlarmActionTrigger |select -First 1 | Remove-AlarmActionTrigger -Confirm:$false

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You mean something like this?

$alarm = Get-AlarmDefinition -Name 'CPU High'

$action = Get-AlarmAction -AlarmDefinition $alarm -ActionType SendEmail

Remove-AlarmAction -AlarmAction $action -Confirm:$false

$trigger = New-AlarmActionTrigger -StartStatus $action.Trigger[0].StartStatus -EndStatus $action.Trigger[0].EndStatus -Repeat

New-AlarmAction -AlarmDefinition $alarm -Email -Subject $action.Subject -To $action.To -AlarmActionTrigger $trigger


Set-AlarmDefinition -AlarmDefinition $alarm -ActionRepeatMinutes 5 -Confirm:$false


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos