VMware Cloud Community
swamynaveen
Enthusiast
Enthusiast
Jump to solution

PowerCLi script to fetch Storage dead paths

Hi All,

I'm using below powerCLi script to fetch storage dead paths across the multiple vcenters to report the storage dead paths. However, hbaname & runtimename values are not matching. Kindly adivse any methods or changes for below script to get the right values to match storage HBA & associated RuntimeNames.

======Script start==========

 

 

$vmhosts = Get-VMHost -State Connected,Maintenance

$i=0

$result = ForEach ($vmhost in $vmhosts) {

$vc = Get-VMHost $vmhost


$i++

Write-Progress -Activity “Scanning hosts” -Status (“Host: {0}” -f $vmhost.Name) -PercentComplete ($i/$vmhosts.count*100) -Id 0

$hbas = $vmhost | Get-VMHostHba

$j=0

ForEach ($hba in $hbas) {

$j++

Write-Progress -Activity “Scanning HBAs” -Status (“HBA: {0}” -f $hba.Device) -PercentComplete ($j/$hbas.count*100) -Id 1

$luns = $hba | Get-ScsiLun

$k=0

ForEach ($lun in $luns) {

$k++

Write-Progress -Activity “Scanning Luns” -Status (“Lun: {0}” -f $lun.CanonicalName) -PercentComplete ($k/$luns.count*100) -Id 2

$paths = $lun | Get-Scsilunpath #| where{$_.State -eq "dead"}

$l=0

ForEach ($path in $paths | where{$_.State -eq "Dead"} ) {

$l++

Write-Progress -Activity “Scanning Paths” -Status (“Path: {0}” -f $path.Name) -PercentComplete ($l/$paths.count*100) -Id 3

New-Object PSObject -Property @{
vCenter = $vc.ExtensionData.CLient.ServiceUrl.Split('/')[2]
Host = $vmhost.name
Cluster = $vmhost.Parent
LUN_Can = $lun.CanonicalName
SizeGB = $lun.CapacityGB
HBA = $hba.Name
WWN = “{0}” -f (((“{0:x}” -f $hba.PortWorldWideName) -split ‘([a-f0-9]{2})’ | where {$_}) -Join “:”)
RuntimeName = $lun.RuntimeName
Vendor = $lun.Vendor

PathSelectionPolicy = $lun.MultiPathPolicy

PathStatus = $path.state


Target = $path.SanId
LUNID = (($lun.RunTimeName -Split “L”)[1] -as [Int])

#Path = $path.Name
}

}

}

}

}

$result

 

 

===========

Output report:

============

swamynaveen_0-1646071988428.png

 

Regards,

Naveen

0 Kudos
2 Solutions

Accepted Solutions
knikolov
VMware Employee
VMware Employee
Jump to solution

Try this:

$vmhosts = Get-VMHost -State Connected, Maintenance
$i = 0
$result = ForEach ($vmhost in $vmhosts) {
    $vc = Get-VMHost $vmhost
    $i++
    Write-Progress -Activity “Scanning hosts” -Status (“Host: {0}” -f $vmhost.Name) -PercentComplete ($i / $vmhosts.count * 100) -Id 0
    $luns = Get-ScsiLun -VmHost $vmhost
    $k = 0
    ForEach ($lun in $luns) {
        $k++
        Write-Progress -Activity “Scanning Luns” -Status (“Lun: {0}” -f $lun.CanonicalName) -PercentComplete ($k / $luns.count * 100) -Id 2
        $paths = $lun | Get-Scsilunpath #| where{$_.State -eq "dead"}
        $l = 0
        ForEach ($path in $paths | where { $_.State -eq "Dead" } ) {
            $l++
            Write-Progress -Activity “Scanning Paths” -Status (“Path: {0}” -f $path.Name) -PercentComplete ($l / $paths.count * 100) -Id 3
            New-Object PSObject -Property @{
                vCenter             = $vc.ExtensionData.CLient.ServiceUrl.Split('/')[2]
                Host                = $vmhost.name
                Cluster             = $vmhost.Parent
                LUN_Can             = $lun.CanonicalName
                SizeGB              = $lun.CapacityGB
                HBA                 = ($path.Name -split ":")[0]
                WWN                 = “{0}” -f (((“{0:x}” -f $hba.PortWorldWideName) -split ‘([a-f0-9]{2})’ | where { $_ }) -Join “:”)
                RuntimeName         = $path.Name
                Vendor              = $lun.Vendor
                PathSelectionPolicy = $lun.MultiPathPolicy
                PathStatus          = $path.state
                Target              = $path.SanId
                LUNID               = (($path.Name -Split “L”)[1] -as [Int])
                #Path = $path.Name
            }
        }
    }
}

$result

View solution in original post

swamynaveen
Enthusiast
Enthusiast
Jump to solution

@knikolov Thanks so much. have validated your script and noticed that WWN details are missing. I've managed to add few variables to capture WWN/DatastoreName/LUN Model details. Here is the working script for reference. Is there a way to show the output data in specific order? as its showing different order everytime.

$vmhosts = Get-Cluster| Get-VMHost -State Connected,Maintenance
$i = 0
$result = ForEach ($vmhost in $vmhosts) {
    $vc = Get-VMHost $vmhost
    $VMHostDatastores =  Get-VMHost $vmhost |Get-Datastore
    $i++
    Write-Progress -Activity “Scanning hosts” -Status (“Host: {0}” -f $vmhost.Name) -PercentComplete ($i / $vmhosts.count * 100) -Id 0
    $luns = Get-ScsiLun -VmHost $vmhost
    $k = 0
    ForEach ($lun in $luns) {
        $k++
        Write-Progress -Activity “Scanning Luns” -Status (“Lun: {0}” -f $lun.CanonicalName) -PercentComplete ($k / $luns.count * 100) -Id 2
        $paths = $lun | Get-Scsilunpath #| where{$_.State -eq "dead"}
        $l = 0 #| where { $_.State -eq "Dead" }
        ForEach ($path in $paths  ) {
            $Device = ($path.Name -split ":")[0]
            $hba = Get-VMHostHba -Type FibreChannel -Device $Device -VMHost $vmhost
            $Datastore = $VMHostDatastores | Where-Object -FilterScript {($_.extensiondata.info.vmfs.extent | ForEach-Object -Process {$_.diskname}) -contains $path.ScsiCanonicalName}| Select-Object -ExpandProperty name
            $l++
            Write-Progress -Activity “Scanning Paths” -Status (“Path: {0}” -f $path.Name) -PercentComplete ($l / $paths.count * 100) -Id 3
            New-Object PSObject -Property @{
                vCenter             = $vc.ExtensionData.CLient.ServiceUrl.Split('/')[2]
                Host                = $vmhost.name
                Cluster             = $vmhost.Parent
                LUN_Can             = $lun.CanonicalName
                DatastoreName       = $Datastore
                SizeGB              = $lun.CapacityGB
                HBA                 = ($path.Name -split ":")[0]
                WWN                 = “{0}” -f (((“{0:x}” -f $hba.PortWorldWideName) -split ‘([a-f0-9]{2})’ | where { $_ }) -Join “:”)
                RuntimeName         = $path.Name
                Vendor              = $lun.Vendor
                Model               = $lun.Model
                PathSelectionPolicy = $lun.MultiPathPolicy
                PathStatus          = $path.state
                Target              = $path.SanId
                LUNID               = (($path.Name -Split “L”)[1] -as [Int])
                #Path = $path.Name
            }
        }
    }
}

$result |Out-GridView

 

View solution in original post

0 Kudos
14 Replies
LucD
Leadership
Leadership
Jump to solution

Do you only see that for "Dead" paths?
I don't have Dead paths, and the script seems to be working fine for me.


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

0 Kudos
swamynaveen
Enthusiast
Enthusiast
Jump to solution

@LucD  Thanks for quick response. Hope you are doing good!!.

Actually, I'm seeing vmhba's to RunTimeName values mismatch for both dead paths as well active paths.

 

Regards,

Naveen

 

0 Kudos
knikolov
VMware Employee
VMware Employee
Jump to solution

I believe that the issue you're seeing is due to the fact that you have the same SCSI luns accessible through different HBAs. I would modify the script to start with the SCSI luns, then retrieve all SCSI lun paths and extract the HBA from the path name similar to how you extract the LunID

0 Kudos
swamynaveen
Enthusiast
Enthusiast
Jump to solution

@knikolov Thank you. Pls let me know once you the updated script. I'll run it and check the status.

Tags (1)
0 Kudos
knikolov
VMware Employee
VMware Employee
Jump to solution

Try this:

$vmhosts = Get-VMHost -State Connected, Maintenance
$i = 0
$result = ForEach ($vmhost in $vmhosts) {
    $vc = Get-VMHost $vmhost
    $i++
    Write-Progress -Activity “Scanning hosts” -Status (“Host: {0}” -f $vmhost.Name) -PercentComplete ($i / $vmhosts.count * 100) -Id 0
    $luns = Get-ScsiLun -VmHost $vmhost
    $k = 0
    ForEach ($lun in $luns) {
        $k++
        Write-Progress -Activity “Scanning Luns” -Status (“Lun: {0}” -f $lun.CanonicalName) -PercentComplete ($k / $luns.count * 100) -Id 2
        $paths = $lun | Get-Scsilunpath #| where{$_.State -eq "dead"}
        $l = 0
        ForEach ($path in $paths | where { $_.State -eq "Dead" } ) {
            $l++
            Write-Progress -Activity “Scanning Paths” -Status (“Path: {0}” -f $path.Name) -PercentComplete ($l / $paths.count * 100) -Id 3
            New-Object PSObject -Property @{
                vCenter             = $vc.ExtensionData.CLient.ServiceUrl.Split('/')[2]
                Host                = $vmhost.name
                Cluster             = $vmhost.Parent
                LUN_Can             = $lun.CanonicalName
                SizeGB              = $lun.CapacityGB
                HBA                 = ($path.Name -split ":")[0]
                WWN                 = “{0}” -f (((“{0:x}” -f $hba.PortWorldWideName) -split ‘([a-f0-9]{2})’ | where { $_ }) -Join “:”)
                RuntimeName         = $path.Name
                Vendor              = $lun.Vendor
                PathSelectionPolicy = $lun.MultiPathPolicy
                PathStatus          = $path.state
                Target              = $path.SanId
                LUNID               = (($path.Name -Split “L”)[1] -as [Int])
                #Path = $path.Name
            }
        }
    }
}

$result
swamynaveen
Enthusiast
Enthusiast
Jump to solution

@knikolov Thanks so much. have validated your script and noticed that WWN details are missing. I've managed to add few variables to capture WWN/DatastoreName/LUN Model details. Here is the working script for reference. Is there a way to show the output data in specific order? as its showing different order everytime.

$vmhosts = Get-Cluster| Get-VMHost -State Connected,Maintenance
$i = 0
$result = ForEach ($vmhost in $vmhosts) {
    $vc = Get-VMHost $vmhost
    $VMHostDatastores =  Get-VMHost $vmhost |Get-Datastore
    $i++
    Write-Progress -Activity “Scanning hosts” -Status (“Host: {0}” -f $vmhost.Name) -PercentComplete ($i / $vmhosts.count * 100) -Id 0
    $luns = Get-ScsiLun -VmHost $vmhost
    $k = 0
    ForEach ($lun in $luns) {
        $k++
        Write-Progress -Activity “Scanning Luns” -Status (“Lun: {0}” -f $lun.CanonicalName) -PercentComplete ($k / $luns.count * 100) -Id 2
        $paths = $lun | Get-Scsilunpath #| where{$_.State -eq "dead"}
        $l = 0 #| where { $_.State -eq "Dead" }
        ForEach ($path in $paths  ) {
            $Device = ($path.Name -split ":")[0]
            $hba = Get-VMHostHba -Type FibreChannel -Device $Device -VMHost $vmhost
            $Datastore = $VMHostDatastores | Where-Object -FilterScript {($_.extensiondata.info.vmfs.extent | ForEach-Object -Process {$_.diskname}) -contains $path.ScsiCanonicalName}| Select-Object -ExpandProperty name
            $l++
            Write-Progress -Activity “Scanning Paths” -Status (“Path: {0}” -f $path.Name) -PercentComplete ($l / $paths.count * 100) -Id 3
            New-Object PSObject -Property @{
                vCenter             = $vc.ExtensionData.CLient.ServiceUrl.Split('/')[2]
                Host                = $vmhost.name
                Cluster             = $vmhost.Parent
                LUN_Can             = $lun.CanonicalName
                DatastoreName       = $Datastore
                SizeGB              = $lun.CapacityGB
                HBA                 = ($path.Name -split ":")[0]
                WWN                 = “{0}” -f (((“{0:x}” -f $hba.PortWorldWideName) -split ‘([a-f0-9]{2})’ | where { $_ }) -Join “:”)
                RuntimeName         = $path.Name
                Vendor              = $lun.Vendor
                Model               = $lun.Model
                PathSelectionPolicy = $lun.MultiPathPolicy
                PathStatus          = $path.state
                Target              = $path.SanId
                LUNID               = (($path.Name -Split “L”)[1] -as [Int])
                #Path = $path.Name
            }
        }
    }
}

$result |Out-GridView

 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Use the [ordered] construct

New-Object PSObject -Property ([ordered]@{
    vCenter             = $vc.ExtensionData.CLient.ServiceUrl.Split('/')[2]
    Host                = $vmhost.name
    Cluster             = $vmhost.Parent
    LUN_Can             = $lun.CanonicalName
    SizeGB              = $lun.CapacityGB
    HBA                 = ($path.Name -split ":")[0]
    WWN                 = “{0}” -f (((“{0:x}” -f $hba.PortWorldWideName) -split ‘([a-f0-9]{2})’ | where { $_ }) -Join “:”)
    RuntimeName         = $path.Name
    Vendor              = $lun.Vendor
    PathSelectionPolicy = $lun.MultiPathPolicy
    PathStatus          = $path.state
    Target              = $path.SanId
    LUNID               = (($path.Name -Split “L”)[1] -as [Int])
    #Path = $path.Name
})


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

swamynaveen
Enthusiast
Enthusiast
Jump to solution

@LucD Thank you. After adding the [ordered] construct output data is showing as per order. 

0 Kudos
swamynaveen
Enthusiast
Enthusiast
Jump to solution

@LucD  / @knikolov  Script is taking quite a long time to fetch the report for just few hosts (i.e. 20). but i am planning to schedule this script for 2000+ hosts. Is there any way to improve the speed? Kindly advise.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The Get-ScsiLun cmdlet is rather expensive in execution time.
An alternative is to use the internal StorageDevice info directly.
That is way faster, but also a bit more complicated to code against.
See for example Solved: Re: Get-ScsiLun/Get-SCSiLunPath Faster - VMware Technology Network VMTN


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

0 Kudos
987135
Contributor
Contributor
Jump to solution

We need to active and dead path path details with custom hosts.

0 Kudos
wetnose88
Enthusiast
Enthusiast
Jump to solution

Thanks LucD, this is good, can be improved if we changed

SizeGB = $lun.CapacityGB

to

SizeGB = [system.math]::Round($lun.CapacityGB)

0 Kudos
VMwareGeek_
Enthusiast
Enthusiast
Jump to solution

Hi,

On the scipt, where can I define output file for example as csv or xlsx file format? How to add directory detail as well to output the result?
When I run this command, it just goes to next command line without any output.

0 Kudos
wetnose88
Enthusiast
Enthusiast
Jump to solution

##########Define the varible for output after connect to vCenter
$outputFile = "$env:USERPROFILE\Outputs\VMHostHBAs\EsxiPathDetails_$($vcenter)_$(get-date -Format yyyy-MM-dd-HH-mm).csv"

Then add the following line to export the $result to csv file you defined

$result | Export-CSV -Path $outputFile -NoTypeInformation

 

0 Kudos