VMware Cloud Community
tonygent
Enthusiast
Enthusiast
Jump to solution

Using PowerCLI to get VM Disk Stats

Firstly - this is really a message to LucD (who I know from previous assistance tends to prowl this forumSmiley Happy )  , just figured I'd share it, as it's all usefull info and any insight LucD has will no doubt be usefull for all.

Hi LucD,
Firstly - thanks for a great selection of posts on Reporting vSphere from Powershell - Well worth the time and a worth read for anyone.
I'm certainly not any good at PowerShell - but I was able to understand and make some changes for my benefit - so I figured I'd share my results and ask a couple of questions.
With your script as a basis - I've been able to come up with the following that SHOULD allow me to review ALL VMs in VC one at a time collect virtual disk stats for the VMs various disks, (IOPS, Throuput & Latency) I'm using VC 4.1 and and the storage is NFS attached, I believe these stats are OK but would appreciate your insight on this.
I'm quite pleased with the script - but it needs more testing on a valid site, rather than my small test area, but I'm sure from a 'PS' perspective there is more efficiency to be gained.
Firstly - is there any way of getting all the stats at once - rather than doing 6 calls per VM? (I'm also sure the '+=' one stat the the next can not be ideal)
Also - is there a way can control the output to the CSV, it seems to put colums in any order it likes and layout does not seem to be related to the group object command? Can this be controlled so I can have the 'value' and 'unit' entries next to each other?
Any insight and assistance would be appreciated, and I hope others will give it a test and let me know if it works for them too.
Thanks again for the inspiration and insight that got me this far Smiley Happy
Tony.
ESX 4.1, VC 4,1, PShell 2.0, PowerCLI 4.1.1
# Main Variables
$sVCentre = "VC IP"
$sVCUser = "administrator@domain"
$sVCPwd = "password"
$strVMWildCard = "*"
$strCSVName = "Stats-AvgVMDiskWriteStatsWorkingday"
$strCSVLocation = "c:\"
# define the start and finish times for a working day.
$today9am = (Get-Date -Hour 9 -Minute 0 -Second 0)
$today5pm = (Get-Date -Hour 17 -Minute 0 -Second 0)
$intStartDay = -1
$intEndDay = -1
## Begin Script
#Connect to VC
Connect-VIServer $sVCentre -User $sVCUser -Password $sVCPwd -ea silentlycontinue
$arrVMs = Get-VM | where-object {$_.Name -like $strVMWildCard}
foreach ($strVM in $arrVMs)
{
Write-Host "Getting Stats for : " $strVM.Name
Write-Host " - collating Write latency Stats"
$stats += Get-Stat -Entity $strVM -Stat virtualDisk.totalWriteLatency.average -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
Write-Host " - collating Read latency Stats"
$stats += Get-Stat -Entity $strVM -Stat virtualDisk.totalReadLatency.average -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
Write-Host " - collating Read IOPS Stats"
$stats += Get-Stat -Entity $strVM -Stat virtualDisk.numberReadAveraged.average -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
Write-Host " - collating Write IOPS Stats"
$stats += Get-Stat -Entity $strVM -Stat virtualDisk.numberWriteAveraged.average -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
Write-Host " - collating Read Throughput Stats"
$stats += Get-Stat -Entity $strVM -Stat virtualDisk.read.average -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
Write-Host " - collating Write Throughput Stats"
$stats += Get-Stat -Entity $strVM -Stat virtualDisk.write.average -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
Write-Host $stats.length
# group the data and collate the stats into averages for the day.
}$groups = $stats | Group-Object -Property {$_.Entity, $_.MetricId, $_.Instance}
$report = $groups | % {
New-Object PSObject -Property @{
Description = $_.Group[0].Description
Entity = $_.Group[0].Entity
EntityId = $_.Group[0].EntityId
Instance = $_.Group[0].Instance
MetricId = $_.Group[0].MetricId
Timestamp = $_.Group[0].Timestamp.Date.AddHours($_.Group[0].Timestamp.Hour)
Unit = $_.Group[0].Unit
Value = [math]::Round(($_.Group | Measure-Object -Property Value -Average).Average, 2)
}
}
#Exporting the report to a CSV file.
$strCSVSuffix = (get-date).toString('yyyyMMddhhmm')
$strCSVFile = $strCSVLocation + $strCSVName + "_" + $strCSVSuffix + ".csv"
$report | Export-Csv $strCSVfile -NoTypeInformation -UseCulture
61 Replies
vsmorfa
Contributor
Contributor
Jump to solution

yep... obviously you're right...

The last thing... then I'll stop to bother you Smiley Happy

How can I cange the time format of the report?

I would like to have the timestamp in the format of h24 instead of h12...

I mean:

now: 23/04/2012 01:00

to be: 23/04/2012 13:00

Thanks

V.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Change this line

Timestamp = ($oentry.Timestamp).toString('dd/MM/yyyy hh:mm')

into this

Timestamp = ($oentry.Timestamp).toString('dd/MM/yyyy HH:mm')


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

0 Kudos
vsmorfa
Contributor
Contributor
Jump to solution

PERFECT!!!!

Thank you very much LucD.

you're awesome :smileygrin:

0 Kudos
ImFlying
Contributor
Contributor
Jump to solution

Great script indeed !

One thing I'm struggling with, is the output.

This script has an output looking like:

EntityInstanceMetricIdValue
MyVMxyz.12345e8069872a000000963d00008015disk.numberwrite.summation7
MyVMxyz.12345e8069872a000000963d00008012disk.numberwrite.summation0

Is there a way to get an output with instances and values per line:

EntityInstance 1Instance 2disk.numberwrite.summation 1disk.numberwrite.summation 2
MyVMxyz.12345e8069872a000000963d00008015xyz.12345e8069872a000000963d0000801270

I saw in other scripts from LucD, for example for the Network Statistics per VM, http://www.lucd.info/2012/04/21/vnic-transmit-and-receive-rates/ that he succeeds to output with values in line (not in columns) but I'm not so gifted with scripting...

Any hint would be greatly appreciated.

0 Kudos
Locutus007
Contributor
Contributor
Jump to solution

This info is great. I used the above script from LucD and tonygent. I'm just starting with PS and PowerCLI, and trying to figure out how to get some things out of my environment. Wanted to note a couple things that I had trouble with:

  • Get-Stat kept erroring out until about 20 hours after I enabled the additional statistics level per device (Control vCenter performance counter collection and get back VM IOPS statistics | alpacapowered)
  • Once Get-Stat finally started working, it kept giving me only one sample time no matter what range I specified. I added "-IntervalSecs 1800" to that line
  • I wanted stats for NFS datastores, so I changed the $arrmetrics line to include all Datastore.%whateverstats%
  • Obviously, no matter what range you specify, it can only get stats for which you have enabled retention
  • I put the script into a text file with a ps1 extension, and am running it from the PowerCLI interface (run as admin). Is that the correct process? Any recommendations on scheduling this?

I'm going to be taking the CSV data from the script and using it to generate usage graphs of VM IOPS to use to evaluate storage expansion options.

Thanks everyone! Any suggestions or thoughts would be helpful. I hope my notes will help some other PowerCLI noobs!

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You need to understand how vSphere handles performance data.

Have a look at my PowerCLI & vSphere statistics – Part 1 – The basics, there I try to explain the different intervals that exist and how the aggregation takes places.

You can use the Windows Task Scheduler to run your scripts.

See Alan's Running a PowerCLI Scheduled task post.


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

0 Kudos
vihar1
Enthusiast
Enthusiast
Jump to solution

Hi,

although this is a very old topic, I hope someone can answer me here as well.


I want to extract the following statistics for a definite time in the past (like last November). Is this possible with PowerCLI?

Average CPU utilization
Peak CPU utilization
Average Memory utilization
Peak Memory utilization
allocated disc storage
used disc storage

Thanks in advance!

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, by manipulating the Start and Finish parameters on the Get-Stat cmdlet you can do this.

But it will depend on the statistics level you have defined for that time interval which metrics will be available.


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

0 Kudos
vihar1
Enthusiast
Enthusiast
Jump to solution

Great, I did some tests and get the average CPU usage for a VM.

However I want to have the disk statistics as well and it tells me the following:

Get-Stat  -entity vm -start 01/31/2014 -finish 02/01/2014 -disk -MaxSamples 1

Get-Stat : 2/10/2014 3:10:37 PM    Get-Stat        Object reference not set to an instance of an object.

At line:1 char:9

+ get-stat <<<<  -entity vm -start 01/31/2014 -finish 02/01/2014 -disk -MaxSamples 1

    + CategoryInfo          : NotSpecified: (:) [Get-Stat], VimException

    + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomatio   n.ViCore.Cmdlets.Commands.GetViStats

The VM is powered on for a while (for weeks at least).

I also want to know what kind of metrics are available and how can I query them (like the peak CPU utilization of a VM).

Thanks!

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That error is most of the time caused by a VM that was not powered on at the Start of the interval you specify on the Get-Stat cmdlet.

You can skip such VMs, by adding -ErrorAction SilentlyContinue on the Get-Stat cmdlet.

All available counters are described on the PerformanceManager page in the API Reference.


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

0 Kudos
vihar1
Enthusiast
Enthusiast
Jump to solution

Thanks, I'll have a look at it.

What is strange, that the VM was powered on Jan 15 this year and the query was about the time between 31 Jan and 02 Feb and it still gave me this error...

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Do you see metrics for that VM under the Performance tab for that period ?


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

0 Kudos
vihar1
Enthusiast
Enthusiast
Jump to solution

The same error received for productive VMs, but in the GUI it shows seemingly correctly (there are peaks but mostly 0 - not much load is there).

I had a look at the metrics but I do not know how to use them. The get-stat does not seem to accept them (I'm a PowerCLI beginner, API calls seem to stretch beyond my knowledge)

0 Kudos
vihar1
Enthusiast
Enthusiast
Jump to solution

We were able to gather CPU stats but not for disks. Is that true that it is not possible to gather disk metrics via this method?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You should also take into account the Statistics level for the counters for a specific time interval.

For example, cpu.usage.average requires statistics level 1

statslvl1.png

while virtualdisk.write.average requires level 2

statslvl2.png


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

0 Kudos
_axel_
Contributor
Contributor
Jump to solution

Hi!

I've been reading this thread over and over again, and I like it! This NFS-performance-metric-script would do exactly what i've been trying to do for some time now.

If I could get it to run ...

I've modified it a bit to check other metrics ( I changed entities of "$arrMetrics" to cpu.usage.average and so on), just to see if it's me doing something totally wrong, or if something is just ... not working as it should, and I've noticed that the only performance metrics I can get out of my ESXi hosts are the ones that I can see when i'm doing a "get-stat -Entity myesxihost". And that would be cpu.usage,average,cpu.usagemhz,average, mem.usage.average, disk.usage.average, net.usage.average, and sys.uptime.lastest.

When i'm asking for the metrics in the orginial script all I get is :

Get-Stat : 2014-02-27 13:17:22    Get-Stat        The metric counter "datastore.totalwritelatency.average" doesn't exist for entity "esxihost.fqdn".

At C:\tmp\powercli\nfs_disk_stats.ps1:37 char:18

+ $stats = Get-Stat <<<<  -Entity $arrHosts -Stat $arrMetrics -Start $today9am.AddDays($intStartDay) -Finish $today5pm.

AddDays($intEndDay)

    + CategoryInfo          : ResourceUnavailable: (datastore.totalwritelatency.average:String) [Get-Stat], VimExcepti

   on

    + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics_MetricDoesntExist,VMware.VimAutomation.

===

So am I doing something wrong here? Or is it my installation of vmware that is FUBAR? Or have I just been staring at this code to long to see what's wrong?

I'm using vmware 5.5, powershell 2.0 ... and as I have understood it, that should do it... but it doesn't.

Best regards

/_Axel_

0 Kudos
LucD
Leadership
Leadership
Jump to solution

From the name of the variable ($arrHosts) it looks as if you are passing ESXi servers to the Get-Stat cmdlet.

This metric is only available for VMs, so pass VMs on the Entity parameter.


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

0 Kudos
_axel_
Contributor
Contributor
Jump to solution

Thank you for the quick reply!

Yes, I did pass a esxi-host to the get-stat cmdlet, but I get the same errors when i'm running the script.

Best regards

/_Axel_

0 Kudos
LucD
Leadership
Leadership
Jump to solution

I didn't notice that you were looking for the datastore.totalwritelatency.average counter.

That is available for ESXi hosts and VMs.

Perhaps you could show how you populated the variables you use in the Get-Stat cmdlet.


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

0 Kudos
_axel_
Contributor
Contributor
Jump to solution

When using the script from this thread, and your post (no#5) i'm populating the variables like this:

# Main Variables

$sVCentre = "vcenter"      #the vcenter server...

$sVCUser = "appropriateusernameforthetask"

$sVCPwd = "andthecorrespondingpassword"

$strHostWildCard = "*" #all and everything would be fine

$strCSVName = "Stats-AvgHostDiskWriteStatsWorkingDay-nfs_disk_stats"

$strCSVLocation = "c:\tmp\powercli\stats\"

$arrMetrics = "datastore.numberReadAveraged.average","datastore.numberWriteAveraged.average",

"datastore.read.average","datastore.write.average","datastore.totalReadLatency.average",

"datastore.totalWriteLatency.average"   #this one i'm not doing anything with ...

And that's all i'm doing with the script.

When i'm using the get-stats cmdlet it looks like this:

get-stat -Entity 'esxihost.fq.dn' | get-stats -Stat "datastore.numberReadAveraged.average"

And I get the error as stated above. I've tried a few different metrics, and it doesn't matter what I try, besides the stats that are given when i'm doing just Get-stat -Entity 'esxihost.fq.dn'

Best regards

/_Axel_

0 Kudos