VMware Cloud Community
qwert1235
Enthusiast
Enthusiast

Script to find overutilized virtual machines

Hello:

Is there a way to find all overutilized virtual machines on the VC via script? for example, I want to find all Vms that are using more than 80% memory and/or CPU 10 minutes in a row or longer.

The same question I have for underutilized virtual machines, but it will be easy once I get the first part working.

Thanks a lot,

qwert

30 Replies
LucD
Leadership
Leadership

That should be

$limit = 80
$vms = Get-VM
$metric = "cpu.usage.average","mem.usage.average"
$start = (Get-Date).AddHours(-24)
$stats = Get-Stat -Entity $vms -Stat $metric -Start $start -ErrorAction SilentlyContinue
$stats |
Group-Object -Property {$_.Entity.Name},{[int](($_.Timestamp.Hour * 60 + $_.Timestamp.Minute)/10)} | %{
    $cpuAvg = ($_.Group | where {$_.MetricId -eq "cpu.usage.average"} | Measure-Object -Property Value -Average).Average
    $memAvg = ($_.Group | where {$_.MetricId -eq "mem.usage.average"} | Measure-Object -Property Value -Average).Average
    if($cpuAvg -gt $limit -and $memAvg -gt $limit){
            Select -InputObject $_ @{N="VM";E={$_.Values[0]}},@{N="Time";E={$_.Group[0].Timestamp}}
}}


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

Reply
0 Kudos
vkaranam
Enthusiast
Enthusiast

Thanks a lot LucD,

It worked. In the Next steps the screen got hang up at this >> mark and it gives me no output.

PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $limit = 80
PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $vms = Get-VM
PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $metric = "cpu.usage.average","mem.usage.average"
PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $start = (Get-Date).AddHours(-24)
PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $stats = Get-Stat -Entity $vms -Stat $metric -Start $start -ErrorAction SilentlyContinue
PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $stats |
>> Group-Object -Property {$_.Entity.Name},{[int](($_.Timestamp.Hour * 60 + $_.Timestamp.Minute)/10)} | %{
>>     $cpuAvg = ($_.Group | where {$_.MetricId -eq "cpu.usage.average"} | Measure-Object -Property Value -Average).Average
>>     $memAvg = ($_.Group | where {$_.MetricId -eq "mem.usage.average"} | Measure-Object -Property Value -Average).Average
>>     if($cpuAvg -gt $limit -and $memAvg -gt $limit){
>>             Select -InputObject $_ @{N="VM";E={$_.Values[0]}},@{N="Time";E={$_.Group[0].Timestamp}}
>>
>>
>>

if i keep on pressing enter it loads >> but there is no ouptut.

Thanks

VK

Reply
0 Kudos
LucD
Leadership
Leadership

The last line was missing.

There should be 2 closing curly braces.

Btw, isn't a lot easier when you save the code in a .ps1 file and then execute the script from the file ?

PowerCLI C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> ./script.ps1


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

Reply
0 Kudos
vkaranam
Enthusiast
Enthusiast

Hey LucD,

I ran the script in the powershell editor and also in power cli on two different vcenters. I did not get any errors and also no output. I guess i have to chage the limit. so I changed  the limit to 40.The limit you are reffering is to print the machine names which reached the average use of CPU and Memory to 40%. am i right??

Also the output prints the same vm multiple times with the time stamp??

here is the output

VM                                                                               Time

--                                                                               ----

28                                                       2/4/2013 12:00:00 PM

48                                                        2/4/2013 10:30:00 AM

48                                                       2/4/2013 10:00:00 AM

48                                                        2/4/2013 9:30:00 AM

48                                                      2/4/2013 9:00:00 AM

48                                                      2/4/2013 8:00:00 AM

48                                                    2/4/2013 7:30:00 AM

45                                   2/4/2013 9:30:00 AM

45                                      2/4/2013 9:00:00 AM

45                                      2/4/2013 8:00:00 AM

45                                   2/4/2013 7:30:00 AM

45                                       2/4/2013 3:00:00 AM

56                                                  2/4/2013 12:30:00 PM

56                                                 2/4/2013 12:00:00 PM

56                                             2/4/2013 11:30:00 AM

lab-vm                                                             2/4/2013 1:30:00 AM

lab-vm                                                             2/4/2013 1:00:00 AM

After the braces i added this export command and it started asking for Input object. I think powershell recognized export command as a new command line rather than part of that code?? How can i add the export command as the part of the code??

>> export-csv C:\report.csv -UseCulture -NoTypeInformation
>>
cmdlet Export-Csv at command pipeline position 1
Supply values for the following parameters:
InputObject:

Thanks

VK

Reply
0 Kudos
LucD
Leadership
Leadership

You have to 'pipe' the objects to the Export-Csv cmdlet. Did you place the pipe symbol (vertical bar) after the last closing curly brace ?

You will get instances if both CPU and memory are above the limit.

And you see a line for each interval for each VM where this condition evaluated to $true.

That explains why the multiple lines for the same VM, but each with a different timestamp.


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

Reply
0 Kudos
vkaranam
Enthusiast
Enthusiast

Hey LucD,

That is working is fine. I have added the Pipe. If  i want to find out the overutilized vm's only w.r.t to memory not cpu for about 10 days is it possible?? Shall i increase the (Get-Date).AddHours(-24) to 240 (10days) and for memory what i have to do??

Thanks

VK

Reply
0 Kudos
LucD
Leadership
Leadership

That would be possible, but a DateTime object in PowerShell has other methods.

You could do

$start = (Get-Date).AddDays(-10)

The test against the limit for the CPU and memory is done in this line

if($cpuAvg -gt $limit -and $memAvg -gt $limit){

If you only want to test the memory against the limit, you change that line like this

if($memAvg -gt $limit){


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

esxi1979
Expert
Expert

Well if u looking for VM which are using 80% CPU then u would call them undersize , don't u .. ie u need to add more memory .. the headline of the thread is otherwise tho ..

Reply
0 Kudos
esxi1979
Expert
Expert

Hi

   LucD Guru  User Moderators vExpert  

 

Reply
0 Kudos
LucD
Leadership
Leadership

In my PowerCLI & vSphere statistics – Part 2 – Come together post I have an example on how to produce reports for specific time frames.

Have a look.


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

AlbertWT
Virtuoso
Virtuoso

This is awesome.

Thanks Luc !

/* Please feel free to provide any comments or input you may have. */
Reply
0 Kudos