PS DS-LUN-v4.ps1

From vWiki
Jump to navigation Jump to search
# ======================================================
# Datastore and LUN Enumerator
# ======================================================
# Simon Strutt        Nov 2010
# ======================================================
#
# ESX v3 
# Thieved and adapted from the good work by catman...
# http://communities.vmware.com/thread/240466
#
# ESX v4
# Thieved and adapted from the good work by notorious_bdg...
# http://communities.vmware.com/thread/171214
#
# Version 3 - Nov 2010
# - Enumerate for a VC (rather than just an ESX)
#
# Version 4 - Nov 2010
# - Added handling for ESX v4
#
# TO DO...
# - Get-DS-LUNs assumes all ESX's connected to a VC are same version, resolve
#
# ======================================================

function Get-DS-LUNs ($objESXs) {
    $esx = $objESXs | Select -First 1
    if (($esx.Version) -ge 4) {
        Get-DS-LUNs-v4
    } else {
        Get-DS-LUNs-v3 ($objESXs)
    }
}

function Get-DS-LUNs-v3 ($objESXs) {
    $results = @()
    foreach ($objESX in $objESXs) {
        #Write-Host "Checking datastores on " $objESX.Name

        # Get .NET views for host and storage system
        $objViewESX = Get-View -id $objESX.id
        $objViewESXstorageSys = Get-View -id $objViewESX.ConfigManager.StorageSystem

        # Get FC HBAs
        $HBAs = $objViewESXstorageSys.StorageDeviceInfo.HostBusAdapter | Where-Object {$_.Key -like "*FibreChannelHba*"}
        #$HBAs

        foreach ($hba in $HBAs) {
            # Enumerate LUNs
            $LUNcount = $objViewESXstorageSys.StorageDeviceInfo.MultiPathInfo.Lun.Length
            #Write-Host ("Enumerating $LUNcount LUNs on " + $hba.Device)
            
            for ($LUNidx = 0; $LUNidx -lt $LUNcount; $LUNidx++ ) {
                $objScsiLUN = $objViewESXstorageSys.StorageDeviceInfo.MultiPathInfo.Lun[$LUNidx]
                #$objScsiLUN
                
                # Enumerate paths on LUN
                $PathCount = $objScsiLUN.Path.Length
                #Write-Host ("Enumerating $PathCount paths on " + $objScsiLUN.Id)
                
                for ($PathIdx = 0; $PathIdx -lt $PathCount; $PathIdx++) {
                    $objSCSIpath = $objViewESXstorageSys.StorageDeviceInfo.MultiPathInfo.Lun[$LUNidx].Path[$PathIdx]
                    #Write-Host ($objSCSIpath.Name + " - " + $objSCSIpath.PathState)
                    
                    # Only care about one path, active on current HBA
                    if (($objSCSIpath.PathState -eq "active") -and ($objSCSIpath.Adapter -eq $hba.Key)) {
                        # Now get the disk that we want
                        $objSCSIdisk = $objViewESXstorageSys.StorageDeviceInfo.ScsiLun | Where-Object{ ($_.CanonicalName -eq $objScsiLUN.Id) -and ($_.DeviceType -eq "disk") }
                        #$objSCSIdisk
                        
                        # Now get the datastore info for disk
                        $MountCount = $objViewESXstorageSys.FileSystemVolumeInfo.MountInfo.Length
                        #Write-Host ("Enumerating $MountCount mounts on " + $objSCSIdisk.CanonicalName)
                        
                        for ($MountIdx = 0; $MountIdx -lt $MountCount; $MountIdx++ ) {
                            if ($objViewESXstorageSys.FileSystemVolumeInfo.MountInfo[$MountIdx].Volume.Type -eq "VMFS" ) {
                                $objVolume = $objViewESXstorageSys.FileSystemVolumeInfo.MountInfo[$MountIdx].Volume
                                #$objVolume
                                
                                $ExtentCount = $objVolume.Extent.Length
                                #Write-Host ("Enumerating $ExtentCount mounts on " + $objVolume.Name)
                                
                                for ($ExtentIdx = 0; $ExtentIdx -lt $ExtentCount; $ExtentIdx++ ) {
                                    $objExtent = $objVolume.Extent[$ExtentIdx]
                                    
                                    # Match extent name to disk name
                                    if ($objExtent.DiskName -eq $objSCSIdisk.CanonicalName) {
                                        #Write-Host($objSCSIdisk.Vendor + " " + $objSCSIdisk.Model + " " + $objSCSIdisk.CanonicalName + "`t" + $objVolume.Name)
                                        
                                        $row = "" | Select Datastore, Make, Model, LUN
                                        $row.Datastore = $objVolume.Name
                                        $row.Make = ($objSCSIdisk.Vendor).TrimEnd()
                                        $row.Model = ($objSCSIdisk.Model).TrimEnd()
                                        $row.LUN = ([regex]::matches($objSCSIdisk.CanonicalName, "(?<=:)([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$")).Item(0).Value
                                        
                                        # Only add datastore to array if it doesn't already exist
                                        if ( ! ($results | ?{$_.Datastore -eq $row.Datastore}) ) {$results = $results + $row}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    $results
}

function Get-DS-LUNs-v4 {
    foreach ($cluster in (Get-View -ViewType "ClusterComputeResource")) {
      $vmhostsview = $cluster.host | % { Get-View $_ }
      $vmhostview  = $vmhostsview | Select -first 1
      $ScsiLuns    = $vmhostsview | % { $_.Config.StorageDevice.ScsiLun } | Select -unique *
      $UUIDs       = $ScsiLuns | Select -unique UUID
      $Datastores  = $vmhostsview | % { $_.Config.FileSystemVolume.MountInfo } | % { $_.Volume } | Select -Unique *
      $HostLUN     = $vmhostsview | % { $_.Config.StorageDevice.ScsiTopology.Adapter } | % { $_.Target | % { $_.LUN } } | Select -unique *
      foreach ($UUID in $UUIDs) {
        $Lun = $ScsiLuns | ? { $_.UUID -eq $UUID.UUID } | Select -first 1
        $objVolume               = "" | Select Datastore, Make, Model, LUN

        $objVolume.LUN       = ($HostLUN | ? { $_.ScsiLun -eq $Lun.Key } | select -unique LUN).LUN
        $objVolume.Make        = $Lun.Vendor
        $objVolume.Model         = $Lun.Model
        foreach ($vol in $Datastores) {
          if ($vol.extent | % { $_.diskname -eq $Lun.CanonicalName}) {
            $objVolume.Datastore  = $vol.Name
          }
        }
        $objVolume
      }
    }
}