1 2 3 Previous Next 61 Replies Latest reply on Apr 12, 2016 10:15 AM by ggmattingly

    Using PowerCLI to get VM Disk Stats

    tonygent Enthusiast

      Firstly - this is really a message to LucD (who I know from previous assistance tends to prowl this forum )  , 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
      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
        • 1. Re: Using PowerCLI to get VM Disk Stats
          LucD Guru
          vExpertCommunity WarriorsUser Moderators

          Thanks Tony.

           

          1) Yes, you can call Get-Stat with multiple metrics, the downside is that the results will be mixed and you will have to extract the correct metric/value objects. What is even better, you can also pass all the VMs in one call to Get-Stat.

           

          2) The Export-Csv doesn't allow you to specify the order of the columns in the .csv file I'm afraid.

          The alternative is to write/construct the .csv file yourself.

          Capture each line as you like it in a string and then write this string to a file.

           

          This is the updated script

           

          # Main Variables 
          $sVCentre
          = "VC IP"
          $sVCUser = "administrator@domain"
          $sVCPwd
          = "password"
          $strVMWildCard
          = "*"
          $strCSVName = "Stats-AvgVMDiskWriteStatsWorkingday"
          $strCSVLocation = "c:\" $metrics = "virtualDisk.totalWriteLatency.average","virtualDisk.totalReadLatency.average",     "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average",     "virtualDisk.read.average","virtualDisk.write.average"
          # 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} $stats = Get-Stat -Entity $arrVMs -Stat $metrics -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
          #
          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
          • 2. Re: Using PowerCLI to get VM Disk Stats
            tonygent Enthusiast

            Hi LucD,

             

            Yep  - once again - spot on.

            Now runs a LOT faster , checked the stats and it all seems to work! So quite pleased, thanks once again for the assistance.

             

            TonyG

            • 3. Re: Using PowerCLI to get VM Disk Stats
              tonygent Enthusiast

              Hi LucD

               

              Pushing things a little further now and wondering if I can get Datastore stats in the same fashion? - We mainly use NFS these days and therefore - there are no real multipathing issues as a single VMK IP is assigned. Below is a revised piece of code that seems to do the job?? Can you see any pitfalls in this - is theresomething obvious I'm missing in this approach?

              I do get results and they seem valid with one exception - the NFS DataStore is refrenced by an InstanceID, and I'm unsure how to resolve this back to the actual DataStore name? - I've been through the Step-3 pages you wrote but this seems to be all SCSI Adapaters and the like, not sure they are valid for NFS Data?

               

              Any assistance to resolve the NFS Instance name to the DataStore name would be helpfull.

               

              THanks again

               

              TG

               

               

               

               

              # Main Variables
              $sVCentre = "VCIP"
              $sVCUser = "administrator@domain"
              $sVCPwd = "password"
              $strHostWildCard = "*"
              $strCSVName = "Stats-AvgHostDiskWriteStatsWorkingDay"
              $strCSVLocation = "c:\"
              $arrMetrics = "datastore.numberReadAveraged.average","datastore.numberWriteAveraged.average",
              "datastore.read.average","datastore.write.average","datastore.totalReadLatency.average",
              "datastore.totalWriteLatency.average"
              # 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
              $arrHosts = Get-VMHOST | where-object {$_.Name -like $strHostWildCard -and $_.ConnectionState -eq "Connected" }
              $stats = Get-Stat -Entity $arrHosts -Stat $arrMetrics -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay)
              $groups = $stats | Group-Object -Property {$_.Entity, $_.MetricId, $_.Instance}
              #$groups = $stats | Group-Object -Property {$_.Timestamp,  $_.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"
              Write-Host "Output file written to : $strCSVfile"
              $report | Export-Csv $strCSVfile -NoTypeInformation -UseCulture
              • 4. Re: Using PowerCLI to get VM Disk Stats
                tonygent Enthusiast

                A little more info.

                 

                I've managed to find a reference to the 'instance' GUID given to each datastore in the Web based Managed Object Reference on vCenter.

                It's in :

                 

                Content > Group D1 (DataCenters) > DataCenter >  DataStore-xxxxx > DataStoreHostMount (HostID) > HostMountInfo > Path : /vmfs/volumes/31cf10aa-6a110389"
                The "31cf10aa-6a110389" value is the same value as the 'Instance' reference in the output from the Get-Stats data.
                Not sure if it's any use - but may help you - help me
                TG
                • 5. Re: Using PowerCLI to get VM Disk Stats
                  LucD Guru
                  User ModeratorsvExpertCommunity Warriors

                  Hi TG,

                  That is indeed the unique identifier for a datastore.

                  In the following script I first create a hash table with all these identifiers and the corresponding datastorename.

                  When you interprete the statistics, you use the Instance as a key into the hash table  and it will return the datastorename.

                   

                  # Main Variables 
                  $sVCentre
                  = "VCIP"
                  $sVCUser
                  = "administrator@domain"
                  $sVCPwd = "password"
                  $strHostWildCard = "name*"
                  $strCSVName
                  = "Stats-AvgHostDiskWriteStatsWorkingDay"
                  $strCSVLocation
                  = "c:\"
                  $arrMetrics = "datastore.numberReadAveraged.average","datastore.numberWriteAveraged.average", "datastore.read.average","datastore.write.average","datastore.totalReadLatency.average", "datastore.totalWriteLatency.average"

                  #
                  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
                  $arrHosts
                  = Get-VMHOST | where-object {$_.Name -like $strHostWildCard -and $_.ConnectionState -eq "Connected" }
                  #
                  Create hash table Instance-DSname
                  $hashTab = @{} $arrHosts | %{     $_.Extensiondata.Config.FileSystemVolume.MountInfo | %{         $key = $_.MountInfo.Path.Split('/')[-1]         if(!$hashTab.ContainsKey($key)){             $hashTab[$key] = $_.Volume.Name         }     } }
                  #
                  Get the statistics
                  $stats
                  = Get-Stat -Entity $arrHosts -Stat $arrMetrics -Start $today9am.AddDays($intStartDay) -Finish $today5pm.AddDays($intEndDay) $groups = $stats | Group-Object -Property {$_.Entity, $_.MetricId, $_.Instance} #$groups = $stats | Group-Object -Property {$_.Timestamp,  $_.Instance}
                  $report = $groups | % {     New-Object PSObject -Property @{         Description = $_.Group[0].Description         Entity = $_.Group[0].Entity.Name         EntityId = $_.Group[0].EntityId         DSname = $hashTab[$_.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"
                  Write-Host "Output file written to : $strCSVfile"
                  $report
                  | Export-Csv $strCSVfile -NoTypeInformation -UseCulture
                  • 6. Re: Using PowerCLI to get VM Disk Stats
                    tonygent Enthusiast

                    Luc ,

                     

                    Once again – your a god!

                     

                    Great work and my sincere thanks

                     

                    Best regards

                    Tony Gent

                    VCP, EMCTA - NAS Specialist

                    • 7. Re: Using PowerCLI to get VM Disk Stats
                      SuperSpike Enthusiast
                      $metrics = "virtualDisk.totalWriteLatency.average","virtualDisk.totalReadLatency.average",     "virtualDisk.numberReadAveraged.average","virtualDisk.numberWriteAveraged.average",     "virtualDisk.read.average","virtualDisk.write.average"

                      What statistics level do I need to enable in order to retrieve these metrics?

                       

                      Using the default statistic levels, I only have these metrics available for my VMs:

                       

                      PS C:\> get-vm MyVM | Get-StatType
                      cpu.usage.average
                      cpu.usagemhz.average
                      cpu.ready.summation
                      mem.usage.average
                      mem.swapinRate.average
                      mem.swapoutRate.average
                      mem.vmmemctl.average
                      mem.consumed.average
                      mem.overhead.average
                      disk.usage.average
                      net.usage.average
                      sys.uptime.latest
                      sys.heartbeat.summation
                      disk.used.latest
                      disk.used.latest
                      disk.used.latest
                      disk.used.latest
                      disk.used.latest
                      disk.provisioned.latest
                      disk.unshared.latest

                       

                      As you can see, I have no virtualDisk.* counters at all.

                       

                      PowerCLI Version
                      ----------------
                         VMware vSphere PowerCLI 4.1 U1 build 332441
                      ---------------

                       

                      Any advice?

                      • 8. Re: Using PowerCLI to get VM Disk Stats
                        LucD Guru
                        User ModeratorsCommunity WarriorsvExpert

                        You can check which statistics level you need in the SDK Reference guide.

                        Go to the PerformanceManager page and select the group of metrics you are interested in.

                        In this case that is the virtual disk group.

                        As you can see, these metrics need statistics level 2.

                        • 9. Re: Using PowerCLI to get VM Disk Stats
                          vsmorfa Novice

                          Hi LucD.

                          First of all thank you for your job. I'm not a big fan of scripting, but with your guides I start to appriciate it

                          I was looking for a script that let me take information about disk usage of VMs, and I've tried you script.

                          When I run it I recieve this error:

                           

                          Get-Stat : 19/04/2012 13:33:00    Get-Stat        The metric counter "virtualdi
                          sk.totalreadlatency.average" doesn't exist for entity "dns_cl".
                          At C:\Scripts\Disk_Perf.ps1:23 char:18
                          + $stats = Get-Stat <<<<  -Entity $arrVMs -Stat $metrics -Start $todayMidnight.
                          AddDays(-1) -Finish $todayMidnight
                              + CategoryInfo          : ResourceUnavailable: (virtualdisk.totalreadlaten
                             cy.average:String) [Get-Stat], VimException
                              + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics
                             _MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

                           

                          Get-Stat : 19/04/2012 13:33:00    Get-Stat        The metric counter "virtualdi
                          sk.numberreadaveraged.average" doesn't exist for entity "dns_cl".
                          At C:\Scripts\Disk_Perf.ps1:23 char:18
                          + $stats = Get-Stat <<<<  -Entity $arrVMs -Stat $metrics -Start $todayMidnight.
                          AddDays(-1) -Finish $todayMidnight
                              + CategoryInfo          : ResourceUnavailable: (virtualdisk.numberreadaver
                             aged.average:String) [Get-Stat], VimException
                              + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics
                             _MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

                           

                          Get-Stat : 19/04/2012 13:33:00    Get-Stat        The metric counter "virtualdi
                          sk.numberwriteaveraged.average" doesn't exist for entity "dns_cl".
                          At C:\Scripts\Disk_Perf.ps1:23 char:18
                          + $stats = Get-Stat <<<<  -Entity $arrVMs -Stat $metrics -Start $todayMidnight.
                          AddDays(-1) -Finish $todayMidnight
                              + CategoryInfo          : ResourceUnavailable: (virtualdisk.numberwriteave
                             raged.average:String) [Get-Stat], VimException
                              + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics
                             _MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

                           

                          Get-Stat : 19/04/2012 13:33:00    Get-Stat        The metric counter "virtualdi
                          sk.read.average" doesn't exist for entity "dns_cl".
                          At C:\Scripts\Disk_Perf.ps1:23 char:18
                          + $stats = Get-Stat <<<<  -Entity $arrVMs -Stat $metrics -Start $todayMidnight.
                          AddDays(-1) -Finish $todayMidnight
                              + CategoryInfo          : ResourceUnavailable: (virtualdisk.read.average:S
                             tring) [Get-Stat], VimException
                              + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics
                             _MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

                           

                          Get-Stat : 19/04/2012 13:33:00    Get-Stat        The metric counter "virtualdi
                          sk.write.average" doesn't exist for entity "dns_cl".
                          At C:\Scripts\Disk_Perf.ps1:23 char:18
                          + $stats = Get-Stat <<<<  -Entity $arrVMs -Stat $metrics -Start $todayMidnight.
                          AddDays(-1) -Finish $todayMidnight
                              + CategoryInfo          : ResourceUnavailable: (virtualdisk.write.average:
                             String) [Get-Stat], VimException
                              + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics
                             _MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

                           

                          And this is true for all the virtual machines in my vsphere 4.1 cluster...

                          How come?

                          What am I missing?

                          Thank you

                          • 10. Re: Using PowerCLI to get VM Disk Stats
                            LucD Guru
                            vExpertCommunity WarriorsUser Moderators

                            It looks as if your Statistics Level for the Historical Interval is not at level 2.

                            That level is required to have this specific metric.

                            You can check from the vSphere Client.

                            • 11. Re: Using PowerCLI to get VM Disk Stats
                              vsmorfa Novice

                              You were right...

                              I have changed the level to 2.

                              Now, when I run the script I get this error:

                               

                              At C:\Scripts\Disk_Perf.ps1:23 char:18
                              + $stats = Get-Stat <<<<  -Entity $arrVMs -Stat $metrics -Start $todayMidnight.
                              AddDays(-1) -Finish $todayMidnight
                                  + CategoryInfo          : NotSpecified: (:) [Get-Stat], VimException
                                  + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomatio
                                 n.ViCore.Cmdlets.Commands.GetViStats

                               

                              Cannot index into a null array.
                              At C:\Scripts\Disk_Perf.ps1:29 char:32
                              +         Description = $_.Group[ <<<< 0].Description
                                  + CategoryInfo          : InvalidOperation: (0:Int32) [], RuntimeException
                                  + FullyQualifiedErrorId : NullArray

                               

                              Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null
                              .
                              At C:\Scripts\Disk_Perf.ps1:42 char:21
                              + $report | Export-Csv <<<<  $strCSVfile -NoTypeInformation -UseCulture
                                  + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingV
                                 alidationException
                                  + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
                                 icrosoft.PowerShell.Commands.ExportCsvCommand

                               

                              For reference I attach the script I'm running

                              Thank you LucD

                              • 12. Re: Using PowerCLI to get VM Disk Stats
                                LucD Guru
                                Community WarriorsUser ModeratorsvExpert

                                You'll have to wait at least 1 day till the aggregation jobs have collected the data for that interval.

                                A good way to check if the values are there, is by going to the Performance tab in the vSphere Client and selecting for example The Past Day.

                                • 13. Re: Using PowerCLI to get VM Disk Stats
                                  vsmorfa Novice

                                  I did it and I can see the data in the performance tab of vsphere client.

                                  Actually, looking at the errors, it looks to me like the script can't resolve some variables.

                                  Am I wrong?

                                  • 14. Re: Using PowerCLI to get VM Disk Stats
                                    LucD Guru
                                    vExpertUser ModeratorsCommunity Warriors

                                    Are you sure

                                    Get-VM | where-object {$_.Name -like $strVMWildCard}

                                    this returns any VMs ?

                                    1 2 3 Previous Next