PowerCLI script to count paths to VMFS volumes
When implementing new storages or configure existing ones it is a good idea to check paths (state and amount) to volumes. When operating a few hosts using a few datastores this can be a very time-consuming task when using the GUI. Therefore I wrote the following function.
function Get-VMFSPathCount ($DatastorePattern='', $ClusterPattern='', $VMHostPattern='', [Switch]$TextOutput=$false, [int]$ShouldCount=-1) { # # .NOTES # =========================================================================== # Blog: vnote42.net # Twitter: @vnote42 # Version: 1.0 # =========================================================================== # .SYNOPSIS # Function counts paths of VMFS-LUNs. # .DESCRIPTION # Function can be used get current state of paths for reporting or further processing. # You can use a color-coded text-report or table/list-output. For selecting volumes, # pattern of VMFS datastore names can be used. Furthermore, you can list just volumes, # path count does not meet your expectation. # .PARAMETER DatastorePattern # With this parameter, you can select for which VMFS Volumes to count paths. # No input, means to take any Volume into account. # When using the exact name, just this Volume is analyzed. # All other inputs are takes as part of datastore name. # .PARAMETER ClusterPattern # Just hosts of selected clusters are analyzed. # No input, means to take all hosts (in any or no cluster) into account. # When using the exact name, just hosts of this cluster are analyzed. # All other inputs are takes as part of cluster name. # .PARAMETER VMHostPattern # Just selected hosts are analyzed. # No input, to not filter any hosts. # When using the exact name, just this host is analyzed. # All other inputs are takes as part of host name. # .PARAMETER TextOutput # When set to $false (default), output is an array # When set to $true, output is text-based and color-coded. Can be used, for reporting. # .PARAMETER ShouldCount # You can define the amount of paths that should exists (active+standby+dead). # No input means every volume is analyzed. # When there are dead paths to a volume, this volume is always in output. # .OUTPUTS # Depending on parameter TextOutput, output is an array or text. # .EXAMPLE # Get-VMFSPathCount # Count paths for all VMFS-volume for all hosts for connected VIserver (vCenter or single host) # .EXAMPLE # Get-VMFSPathCount -DatastorePattern 3par # Count paths for all VMFS-volume, containing string "3par" # .EXAMPLE # Get-VMFSPathCount -DatastorePattern 3par | Format-Table -AutoSize # To show table instead of list, use: # .EXAMPLE # Get-VMFSPathCount -DatastorePattern 3par -TextOutput:$true # Report output as text # .EXAMPLE # Get-VMFSPathCount -DatastorePattern 3par -ShouldCount 2 | Format-Table -AutoSize # Analyse all volumes, containing string "3par" and count of all paths is not 2 # $Result = @() $VmfsDatastores = @{} $QueryClusterList = Get-Cluster ("*"+$ClusterPattern+"*") ForEach ($DS in (Get-Datastore ("*"+$DatastorePattern+"*") | Where-Object {$_.Type -eq "vmfs"})){ $DS.Extensiondata.Info.Vmfs.Extent | ForEach-Object { $VmfsDatastores[$_.DiskName] = $DS.Name } } if ($VmfsDatastores.Count -eq 0) {break} ForEach ($VmHost in (Get-VMHost ("*"+$VMHostPattern+"*") | Where-Object {$_.ConnectionState -eq "Connected" -or $_.ConnectionState -eq "Maintenance"})) { $Cluster = Get-Cluster -VMHost $VmHost.Name if ($ClusterPattern -ne '' -and $Cluster.Name -notin $QueryClusterList.Name) {continue} $Luns = $VmHost | Get-ScsiLun | Where-Object {$_.IsLocal -ne "true" -and $_.CanonicalName -in $VmfsDatastores.Keys} if ($TextOutput) {Write-Host $VmHost.name} ForEach ($Lun in $Luns) { $CountTab = $Lun | Get-ScsiLunPath $CountAll = $CountTab.Count $CountActive = ($CountTab | Where-Object {$_.state -eq "Active"}).count $CountStandby = ($CountTab | Where-Object {$_.state -eq "Standby"}).count $CountDead = ($CountTab | Where-Object {$_.state -eq "Dead"}).count $VmfsName = $Lun.CanonicalName if($VmfsDatastores.ContainsKey($Lun.CanonicalName)){ $Vmfsname = $VmfsDatastores[$Lun.CanonicalName] } if ($ShouldCount -ne $CountActive -or $CountDead -gt 0) { if ($TextOutput) { Write-Host "`t" $VmfsName -NoNewline Write-Host -ForegroundColor Green "`t" "Active:" $CountActive -NoNewline if ($CountDead -ne 0) {Write-Host -ForegroundColor Red "`t" "Dead:" $CountDead} else {Write-Host} } else { $NewEntry = [PScustomObject] @{ Cluster = $Cluster.Name VMhost = $VmHost.Name Datastore = $Vmfsname AllPathCount = $CountAll ActivePathCount = $CountActive StandbyPathCount = $CountStandby DeadPathCount = $CountDead MultipathPolicy = $lun.MultipathPolicy } $Result += $NewEntry } } } } if (!$TextOutput) {$Result | Sort-Object Cluster, VMhost, Datastore} }
Input
Before running the function, a connection to a vCenter or single host has to be established. Depending on entered parameters the function uses hosts of this connection to count paths to VMFS volumes. You can restrict to analyze specific clusters, hosts or volumes. These parameters can be used to enter a exact name or a part of the name. For example ClusterPattern
“Cluster” would select “Cluster1” and “Cluster2”. Furthermore you can enter an expected path-count, when this is not met, volume will be in output. Selected Volumes with dead paths are always in output.
Output
You have the option to got output as table or text-based. Text-based can be used for reporting purpose. Table is useful for documentation and further processing. In Table you get counter for active, standby and dead paths. Because most often multipath policy is also a very interesting property, it is also in table.
[Update 1.4.2020]
- Selection of hosts line 81 includes now ConnectionState, so disconnected hosts will not cause delays when running the script.
- Thanks to @RFrankemolle who found a typo, correct output columne name is MultipathPolicy now.
Notes
- Needed module is VMware.VimAutomation.Core.
- If you want to get
Get-Help
functionality to work for this function, replace per-line comment to block-comment (<# … #>) from.NOTES
to last.EXAMPLE
. This notation did not work in wordpress-plugin. - Possible VIservers: vCenter and single ESXi host.
- Host and cluster selection takes single hosts, host in clusters and hosts not in clusters into account.
- When a datastore is within selection, it is always in output when any path is dead.
- In text-based output there are no cluster names.
- Because of cmdlet
Get-ScsiLun
function needs some time to complete. - If you see dead paths, you can check for Permanent Device Loss (PDL) state
Feel free, to post bugs or ideas for improvements.