VMware Cloud Community
waltereye
Contributor
Contributor
Jump to solution

PowerCLI script for NFS Datastores

Hi

I have the following powershell script and this is new to me. What do I need to add to it in order to retrive a weeks worth of IO stats and also have it exported to a csv file.

Thanks.

$metrics = "virtualdisk.numberwriteaveraged.average","virtualdisk.numberreadaveraged.average"
$start = (Get-Date).AddMinutes(-5)
$report = @()

$vms = Get-VM | where {$_.PowerState -eq "PoweredOn"}
# vCenter Login Variables
$sVCentre = ""    # holds the fqdn or ip of the vcenter server.
$sVCUser = ""# holds the login name used to login to vcenter, local or domain
$sVCPwd = ""    # the password for vcenter login in clear txt.
$strVMWildCard = "*"    # use * for all machine, or use wildcard to limit, eg : "Sol*" for machines begining Sol
$strOutputLocation = "C:\" # The default output location for for results, the file name is generated - just provide the path.

# add VMware PS snapin
if (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
    Add-PSSnapin VMware.VimAutomation.Core
}

## Begin Script

#Connect to VC
Connect-VIServer $sVCentre -User $sVCUser -Password $sVCPwd -ea silentlycontinue

$stats = Get-Stat -Realtime -Stat $metrics -Entity $vms -Start $start
$interval = $stats[0].IntervalSecs

$hdTab = @{}
foreach($hd in (Get-Harddisk -VM $vms)){
    $controllerKey = $hd.Extensiondata.ControllerKey
    $controller = $hd.Parent.Extensiondata.Config.Hardware.Device | where{$_.Key -eq $controllerKey}
    $hdTab[$hd.Parent.Name + "/scsi" + $controller.BusNumber + ":" + $hd.Extensiondata.UnitNumber] = $hd.FileName.Split(']')[0].TrimStart('[')
}

$report = $stats | Group-Object -Property {$_.Entity.Name},Instance | %{
    New-Object PSObject -Property @{
        VM = $_.Values[0]
        Disk = $_.Values[1]
        IOPSMax = ($_.Group | `
            Group-Object -Property Timestamp | `
            %{$_.Group[0].Value + $_.Group[1].Value} | `
            Measure-Object -Maximum).Maximum / $interval
        Datastore = $hdTab[$_.Values[0] + "/"+ $_.Values[1]]
    }
}

$report

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The selection of the VMs can be adjusted if required.

With

$vms = Get-VM | where {$_.PowerState -eq "PoweredOn"}

you will only get statistics for VMs that are currently powered on.

An alternative, if you don't want to see this error messages for VMs where there is no performance data for the selected interval, is to use the ErrorAction parameter. Like this

Get-Stat -Entity $vms -Stat $metrics -Start $start -ErrorAction SilentlyContinue | 

Yes, you can adjust the interval by changing the Start parameter value.

And you can also use the Finish parameter to define the end of the interval.

See my PowerCLI & vSphere statistics – Part 1 – The basics post for some info on how to use the Get-Stat cmdlet.

To redirect the results to a CSV file use the Export-Csv cmdlet.

The last line would look someting like this

} | Export-Csv c:\report.csv -NoTypeInformation -UseCulture 


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

View solution in original post

Reply
0 Kudos
20 Replies
LucD
Leadership
Leadership
Jump to solution

Have you already seen this thread Re: Disk performance realtime, averrage on nas server


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

Yes,  do you mean I have to gather the NFS stats from the ESXi hosts. Is that the only way to gather NFS IO stats on vm's with NFS datastores? How about a 24 hour period?

Thanks

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Not with the Get-EsxTop cmdlet, that is intended for interactive performance measurements.

Those metrics are not stored nor aggregated in the vCenter DB


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

LucD

     What could I use for vm's IO performance on NFS datastores?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You could schedule a script that calls Get-Esxtop to run for example every hour for a couple of minutes, and store the resulting NFS metrics in a repository.

That will not give you the same reporting options as the metrics collected and stored by the PerformanceManager, but at least that is better than nothing (at least until vSphere collects NFS counters through the PerformanceManager).


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

LucD

Would the above script accomplish the same?

Thanks

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I don't think so, because these counters are not usable for NFS datastores.

Can you see these counters in the Performance tab of the vSphere client for the NFS datastores ?

And is there any performance data displayed ?


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

LucD

I was looking at the performance monitor and it collects data on average read and write requests per secound on the datastore for a vm wouldn' that give me which vm's have high disk activity? 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That would be an indication, but note that the size of the IO blocks also plays a role.

I would also include the throughput (throughput.usage.average) and the latency (totalReadLatency.average,totalWriteLatency.average).

That should give a more complete picture.

Ideally you could use Get-EsxTop and run it for a couple of minutes.

Do this several times during the day.

The esxtop counters are over smaller intervals and they show (mostly) the same metrics as you see in the esxtop utility.


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

LucD

     I'm not a powershell scripter and do you have any scripts that would help me out. This is what I want to accomplish is I have a NFS datastore that when I look on the Storage Array end it is heavily utilized so what I'd like to do is find the vm's with high disk activity and move some of them off to another datastore any help would be greatly appreciated.

Thanks

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this

$dsTab = @{}
Get-Datastore | where {$_.Type -eq "NFS"} | %{
  $dsName = $_.Name
  $_.ExtensionData.Host | %{     $NfsUuid = $_.MountInfo.Path.Split('/')[3]     if(!$dsTab.ContainsKey($NfsUuid)){       $dsTab.Add($NfsUuid,$dsName)     }   } }
$metrics
= "datastore.numberreadaveraged.average","datastore.numberwriteaveraged.average"
$start
= (Get-Date).AddHours(-1) $vms = Get-VM
Get-Stat
-Entity $vms -Stat $metrics -Start $start |
Group-Object -Property {$_.Entity.Name} | %{     New-Object PSObject -Property @{       VM = $_.Name
     
Datastore = $dsTab[$_.Group[0].Instance]       NumberReadAveraged = $_.Group | where {$_.MetricId -eq "datastore.numberreadaveraged.average"} |
       
Measure-Object -Property Value -Average |
       
select -ExpandProperty Average
     
NumberWriteAveraged = $_.Group | where {$_.MetricId -eq "datastore.numberwriteaveraged.average"} |
       
Measure-Object -Property Value -Average |
        select -ExpandProperty Average
    } }

In $dsTab we map the NFS datastore instancename, they do not have a real UUID, to the datastorename.

In the Get-Stat block we calculate for each VM the average read and write numbers over the last hour. Make sure you only take VMs that are located on NFS datastores, otherwise datastorename lookup with the instancename will fail.


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

LucD

     I'm getting the following error:

Unexpected token '_' in expression or statement.
At C:\Documents and Settings\iswbez\Desktop\wbNFSJan232013.ps1:25 char:24
+   $dsName = $_.Name  $_ <<<< .ExtensionData.Host | %{
    + CategoryInfo          : ParserError: (_:String) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The copy-paste dropped a CR-LF it seems, those were 2 seperate lines.

I corrected the code above, please try again.


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

LucD

I corrected that and now have another one:

The term 'Get-VM' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that
the path is correct and try again.
At C:\Documents and Settings\iswbez\Desktop\wbNFSJan232013.ps1:5 char:14
+ $vms = Get-VM <<<<  | where {$_.PowerState -eq "PoweredOn"}
    + CategoryInfo          : ObjectNotFound: (Get-VM:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

From where are you running this ? The PowerCLI prompt or a GUI like PowerGUI ?

Looks like the PowerCLI pssnapin is not loaded.


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

from the GUI like PowerGUI I have Added the following:

# add VMware PS snapin
if (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
    Add-PSSnapin VMware.VimAutomation.Core
}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

And does it run now ?


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

Reply
0 Kudos
waltereye
Contributor
Contributor
Jump to solution

Yes it runs. it looks like it is also queying vm's powered off:

Get-Stat : 1/23/2013 3:43:37 PM    Get-Stat        The metric counter "datastore.numberwriteaveraged.average" doesn't exist for entity "prod_ghmf5".   
At C:\Documents and Settings\iswbez\Desktop\wbNFSJan232013.ps1:38 char:9
+ Get-Stat <<<<  -Entity $vms -Stat $metrics -Start $start |
    + CategoryInfo          : ResourceUnavailable: (datastore.numberwriteaveraged.average:String) [Get-Stat], VimException
    + FullyQualifiedErrorId : Client20_RuntimeDataServiceImpl_CheckUserMetrics_MetricDoesntExist,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetViStats

Also can I run it for a day?  ie $start = (Get-Date).AddHours(-24) will this work?

and what do I need to adde to $report export it to a csv file?

Thanks

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The selection of the VMs can be adjusted if required.

With

$vms = Get-VM | where {$_.PowerState -eq "PoweredOn"}

you will only get statistics for VMs that are currently powered on.

An alternative, if you don't want to see this error messages for VMs where there is no performance data for the selected interval, is to use the ErrorAction parameter. Like this

Get-Stat -Entity $vms -Stat $metrics -Start $start -ErrorAction SilentlyContinue | 

Yes, you can adjust the interval by changing the Start parameter value.

And you can also use the Finish parameter to define the end of the interval.

See my PowerCLI & vSphere statistics – Part 1 – The basics post for some info on how to use the Get-Stat cmdlet.

To redirect the results to a CSV file use the Export-Csv cmdlet.

The last line would look someting like this

} | Export-Csv c:\report.csv -NoTypeInformation -UseCulture 


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

Reply
0 Kudos