PowerShell function to get disk SCSI Lun number

PowerShell logoFor our Boot From SAN servers we wanted to know the SCSI Lun number of the disks. You can get this information via WMI. But to retrieve it you need four different WMI objects. I made a PowerShell advanced function that combines these four WMI objects to relate the disk with the LUN number.

The Get-DiskScsiLun function

The Get-DiskScsiLun function uses the following WMI objects:
Win32_LogicalDisk, Win32_LogicalDiskToPartition, Win32_DiskDriveToDiskPartition and Win32_DiskDrive.

The first object contains the drive letter. The last object contains the Lun number. And the two other objects are needed to relate the drive letter to the Lun number.

function Get-DiskScsiLun {
<#
  .SYNOPSIS
    Retrieves the SCSI Lun information for a disk.

  .DESCRIPTION
    Retrieves the SCSI Lun information for a disk.

  .PARAMETER  DeviceID
    Specify the disk name for wich the Scsi Lun information should be retrieved.

  .PARAMETER  ComputerName
    Specifies the computer against which you want to run the management operation.
    The value can be a fully qualified domain name, a NetBIOS name, or an IP
    address. Use the local computer name, use localhost, or use a dot (.) to specify the local
    computer. The local computer is the default.
    When the remote computer is in a different domain from the user, you must use a fully
    qualified domain name. This parameter can also be piped to the cmdlet.

    This parameter does not rely on Windows PowerShell remoting, which uses WS-Management.
    You can use the ComputerName parameter of Get-WmiObject even if your computer is not
    configured to run WS-Management remote commands.

  .PARAMETER  Credential
    Specifies a user account that has permission to perform this action. The default is
    the current user. Type a user name, such as "User01", "Domain01\User01",
    or User@Contoso.com. Or, enter a PSCredential object, such as an object that is
    returned by the Get-Credential cmdlet. When you type a user name, you will be prompted
    for a password.

  .EXAMPLE
    PS C:\> Get-DiskScsiLun

  .EXAMPLE
    PS C:\> Get-DiskScsiLun -DeviceID C: -ComputerName Server01 -Credential Domain01\User01

  .EXAMPLE
    PS C:\> "Server01","Server02" | Get-DiskScsiLun -Credential Domain01\User01
		
  .INPUTS
    System.String,PSCredential

  .OUTPUTS
    PSObject

  .NOTES
    Author: Robert van den Nieuwendijk
    Version: 1.1
    Date: 17-1-2013

  .LINK

http://rvdnieuwendijk.com/

#>

 [CmdletBinding()]
  param([Parameter(Mandatory = $false,
                   Position = 0)]
        [alias("Disk")]
        [string] $DeviceID = '*',
        [Parameter(Mandatory = $false,
                   Position = 1,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [alias("CN")]
        [String[]] $ComputerName = $env:COMPUTERNAME,
        [Parameter(Mandatory=$false,
                   Position = 2)]
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty
  )
  
  process {
    if ($ComputerName)
    {
      # Loop through all computers in the parameter list
      foreach ($Computer in $ComputerName) {
      try {
        if ($Computer -eq "$($env:COMPUTERNAME)" -or $Computer -eq "." -or $Computer -eq "localhost")
        {
          # Define the Get-WmiObject parameter set for the local computer
          $Parameters = @{
            Impersonation = 3
            ErrorAction = 'Stop'
          }
        }
        else
        {
          # Define the Get-WmiObject parameter set for remote computers
          $Parameters = @{
            ComputerName = $Computer
            Credential = $Credential
            ErrorAction = 'Stop'
          }
        }
		  
        # Test if the computer can be connected
        if (Test-Connection -ComputerName $Computer -Count 1 -Quiet)	 
        {		  
          # Get the  WMI objects
          $Win32_LogicalDisk = Get-WmiObject -Class Win32_LogicalDisk @Parameters |
            Where-Object {$_.DeviceID -like $DeviceID}
          $Win32_LogicalDiskToPartition = Get-WmiObject -Class Win32_LogicalDiskToPartition @Parameters 
          $Win32_DiskDriveToDiskPartition = Get-WmiObject -Class Win32_DiskDriveToDiskPartition @Parameters 
          $Win32_DiskDrive = Get-WmiObject -Class Win32_DiskDrive @Parameters 
  
          # Search the SCSI Lun Unit for the disk
          $Win32_LogicalDisk |
            ForEach-Object {
              if ($_)
              {
                $LogicalDisk = $_
                $LogicalDiskToPartition = $Win32_LogicalDiskToPartition |
                  Where-Object {$_.Dependent -eq $LogicalDisk.Path}
                if ($LogicalDiskToPartition)
                {
                  $DiskDriveToDiskPartition = $Win32_DiskDriveToDiskPartition |
                    Where-Object {$_.Dependent -eq $LogicalDiskToPartition.Antecedent}
                  if ($DiskDriveToDiskPartition)
                  {
                    $DiskDrive = $Win32_DiskDrive |
                      Where-Object {$_.__Path -eq $DiskDriveToDiskPartition.Antecedent}
                    if ($DiskDrive)
                    {
                      # Return the results
                      New-Object -TypeName PSObject -Property @{
                        Computer = $Computer
                        DeviceID = $LogicalDisk.DeviceID
                        SCSIBus = $DiskDrive.SCSIBus
                        SCSIPort = $DiskDrive.SCSIPort
                        SCSITargetId = $DiskDrive.SCSITargetId
                        SCSILogicalUnit = $DiskDrive.SCSILogicalUnit
                      }
                    }
                  }
                }
              }
            }
          }
          else
          {
            Write-Warning "Unable to connect to computer $Computer."
          }
        }
        catch {
          Write-Warning "Unable to get disk information for computer $Computer.`n$($_.Exception.Message)"
        }
      }
    }
  }
}

Listing 1. The PowerShell advanced function Get-DiskScsiLun that retrieves the SCSI Lun number for a disk.

Annotations

Line 79-95: Build the parameter sets for the Get-WmiObject function calls.

Line 100-105: Retrieve the WMI objects.

Line 107-138: Match the disk drive letter to the SCSI Lun information.

Sample usage

Output 1 will show you an example of the results you can get when you run the Get-DiskScsiLun function.

Computer  DeviceID SCSIBus SCSIPort SCSITargetId SCSILogicalUnit
--------  -------- ------- -------- ------------ ---------------
server001 C:             0        2            5               1
server001 D:             0        0            4               0
server001 E:             0        2            4               2
server001 F:             0        1            5               3
server001 G:             0        2            4               4
server001 H:             0        1            5              13
server001 I:             0        1            5               5
server001 J:             0        2            5               6
server001 K:             0        2            4               7
server001 L:             0        2            5               8
server001 M:             0        1            4               9
server001 N:             0        1            4              10
server001 O:             0        2            5              11
server001 P:             0        2            5              12

Output 1. Sample output of the Get-DiskScsiLun function.

Update 17-1-2013: I modified the Get-DiskScsiLun function to not only retrieve the SCSILogicalUnit but also SCSIBus, SCSIPort and SCSITargetId.

About these ads

About Robert van den Nieuwendijk
Robert van den Nieuwendijk is a freelance systems administrator with over twenty years of experience in the IT industry. His main focus is VMware vSphere and Microsoft Windows Server. He tries to automate as much of his work as possible using Microsoft Windows PowerShell. Robert is a frequent contributor and moderator at the VMware VMTN Communities. He has a bachelor degree in software engineering and holds the following IT certifications and accreditations: VSP 5, VTSP 5, VCP4-DCV, VCP5-DCV, MCSE, MCSA, MCP and MCP+I. In 2012 and in 2013 Robert received the VMware vExpert title for his contribution to the community of VMware users over the past year.

6 Responses to PowerShell function to get disk SCSI Lun number

  1. Kelvin Wong says:

    This don’t work for mount points though :-(

  2. Ben says:

    My output shows all LUN#’s as ’0′, this comes from $Win32_DiskDrive, all the LUN #’s on a VMware LSI Logic SAS.

    PS C:\> $Win32_DiskDrive | select Name,SCSILogicalUnit | ft -AutoSize

    Name SCSILogicalUnit
    —- —————
    \\.\PHYSICALDRIVE1 0
    \\.\PHYSICALDRIVE0 0

  3. Thomas Burger says:

    That is pretty normal since LSI-Logic Controllers are incrementing the target number.
    So your second RAID-Volume shows up as Target1:Lun0
    3rd ist Target2:Lun0 etc.
    in SCSI Targets are counted starting with 0

  4. Pingback: Enumerate DiskLuns | digital36 Blog-sphere

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 414 other followers

%d bloggers like this: