The making of a New-VIProperty called lunID

An interesting question arrived in my mailbox this morning. Robert wanted to know what was the most efficient way to create a new property, called lunID,Β  for the objects returned by the Get-ScsiLun cmdlet.

The new property had to show the lunID, as it is returned in the LUN column in the vSphere client.

Getting there

There are of course multiple ways for getting at the lunID (aren’t there always πŸ˜‰ ).

After a quick look at the properties of the Get-ScsiLun cmdlet, I concluded that the most obvious way to get there, was to use the RunTimeName property.

The trick would be to extract the lunID from the string in a general and fast way.

Luckily PowerShell allows one to use RegEx expressions to do just that. With the Select-String cmdlet I should be able to extract the lunID. A quick test, showed that it was quiet easy.

The pattern says that the cmdlet should look at the end of the string (the $ character), for a string that starts with ‘:L’, followed by 1 or more numeric characters. And since it are these numeric characters we are after, we ask to group them, which is indicated by the ‘()’ in the pattern. Note that we had to escape the double colon, since it has a special meaning in a RegEx expression.

A test run produced the following.

Note that the results of this RegEx operation are returned in the $matches property. To access the actual value we can use an array index, but I find using a name is easier. Luckily we can give names to a group in the RegEx expression. This gives the following script.

Which produces this output.

Everything is now in place to create our New-VIProperty definition.

The script

Annotations

Line 1: The object returned by the Get-ScsiLun cmdlet is a ScsiLun object.
Line 4: The script converts the lunID to an [int] value. The RegEx expression returns all matches as a [string] by default.

Trial run

Let’s take the new property for a spin.

Annotations

Line 6: The output of the New-VIProperty is thrown away by piping it to Out-Null.

And this produces

13 Comments

    Arvinth

    Hello Luc,

    Need your help to sort out the below requirement

    I am using a seperate script for extracting RDM attached VM’s & seperate one for extracting LUN id for the respective devices
    I used to edit this scripts based on requirment , whether to run at VC level or host or cluster.

    But now i have got a requirement to combine both the scripts
    to list the below details using single script

    VMName,VMHost,HDDeviceName,HDMode,HDsize,LunId

    I have attached the scripts below , Request your help in getting as a single output

    β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”-

    $report = @()
    $vms = Get-VM | Get-View
    foreach($vm in $vms){
    foreach($dev in $vm.Config.Hardware.Device){
    if(($dev.gettype()).Name -eq β€œVirtualDisk”){
    if(($dev.Backing.CompatibilityMode -eq β€œphysicalMode”) -or
    ($dev.Backing.CompatibilityMode -eq β€œvirtualMode”)){
    $row = β€œβ€ | select VMName, VMHost, HDDeviceName, HDFileName, HDMode, HDsize
    $row.VMName = $vm.Name
    $row.VMHost = (Get-View $vm.Runtime.Host).Name
    $row.HDDeviceName = $dev.Backing.DeviceName
    $row.HDFileName = $dev.Backing.FileName
    $row.HDMode = $dev.Backing.CompatibilityMode
    $row.HDSize = $dev.CapacityInKB
    $report += $row
    }
    }
    }
    }
    $report

    β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”-
    To get the LUN id

    Get-VM |
    Get-HardDisk |

    Where-Object {$_.DiskType -eq β€œRawPhysical”} |
    Select-Object -Property @{N=”VM”;E={$_.Parent}},
    @{N=”HardDisk”;E={$_.Name}},
    @{N=”Lun”;E={
    $HardDisk = $_
    $lun = Get-VMHost -VM $_.Parent |

    Get-ScsiLun -LunType Disk |
    Where-Object {$_.CanonicalName -eq $HardDisk.ScsiCanonicalName}
    [int](Select-String β€œ:L(?\d+)$”

    -InputObject $lun.RuntimeName).Matches[0].Groups[‘lunID’].Value
    }}
    β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”-

    Arvinth

    Hey Luc,

    I am using a seperate script for extracting RDM attached VM’s & seperate one for extracting LUN id for the respective devices
    I used to edit this scripts based on requirment , whether to run at VC level or host or cluster.

    But now i have got a requirement to combine both the scripts
    to list the below details using single script

    VMName,VMHost,HDDeviceName,HDMode,HDsize,LunId

    I have attached the scripts below , Request your help in getting as a single output

    ————————————————————————————————————-

    $report = @()
    $vms = Get-VM | Get-View
    foreach($vm in $vms){
    foreach($dev in $vm.Config.Hardware.Device){
    if(($dev.gettype()).Name -eq “VirtualDisk”){
    if(($dev.Backing.CompatibilityMode -eq “physicalMode”) -or
    ($dev.Backing.CompatibilityMode -eq “virtualMode”)){
    $row = “” | select VMName, VMHost, HDDeviceName, HDFileName, HDMode, HDsize
    $row.VMName = $vm.Name
    $row.VMHost = (Get-View $vm.Runtime.Host).Name
    $row.HDDeviceName = $dev.Backing.DeviceName
    $row.HDFileName = $dev.Backing.FileName
    $row.HDMode = $dev.Backing.CompatibilityMode
    $row.HDSize = $dev.CapacityInKB
    $report += $row
    }
    }
    }
    }
    $report

    ——————————————————————————————————————-
    To get the LUN id

    Get-VM |
    Get-HardDisk |

    Where-Object {$_.DiskType -eq “RawPhysical”} |
    Select-Object -Property @{N="VM";E={$_.Parent}},
    @{N="HardDisk";E={$_.Name}},
    @{N="Lun";E={
    $HardDisk = $_
    $lun = Get-VMHost -VM $_.Parent |

    Get-ScsiLun -LunType Disk |
    Where-Object {$_.CanonicalName -eq $HardDisk.ScsiCanonicalName}
    [int](Select-String ":L(?\d+)$"

    -InputObject $lun.RuntimeName).Matches[0].Groups[‘lunID’].Value
    }}
    —————————————————————————————————————-

    AndrΓ©

    Thank LucD, this note helped me a lot.

    Alessandro

    Hi there, thank you for the script. I would like to find a way to balance the preferred path on the odd/even lunID. I must say I am a novice of powershell… Does someone have something ready?
    Thank you in advance.

      LucD

      @Alessandro, there a couple of such script around.
      The one from Glenn, one of my co-authors, is called PowerCLI: Balance LUN paths for a Cluster. It’s not exactly how you want to organise the load balance, but it should be not too difficult to adapt Glenn’s script.
      There is another script that us quite good, it’s Rob’s script from the storage-path script thread on the PowerCLI Community.

    Suhail

    Thanks for sharing some great information.

    I am trying to get the LUN ids via your script but the output is only CanonicalName, the lunID column is blank.

    There is no error when i run the script.

    Could you please help me.

    Thanks,
    Suhail.

    ranjit

    @LucD

    LucD ,thanks for your reply.
    Get-VMHost $esxName | Get-ScsiLun when i run ,..i get following output
    CanonicalN ConsoleDeviceName LunType CapacityMB MultipathPolicy
    ame
    ———- —————– ——- ———- —————
    naa.600… /vmfs/devices/disks/naa.600… disk 1228800 Fixed

    yesterday i tried to much on this but not able to get lunID ,if i put lunID in select then i get error but it displays information of other selected fileds.

    my powercli version is:- (get-powercliversion)
    PowerCLI Version
    —————-
    VMware vSphere PowerCLI 4.1 U1 build 332441
    —————
    Snapin Versions
    —————
    VMWare vSphere PowerCLI 4.1 U1 build 332441

    ————————————————————
    currently i am connecting to esx from powercli and then running the script ..can run this script for vcenter..so that i will get information for all esx server and if i could get esx server name in first coloumn then it will be great.

    thanks in advance.

    ranjit

    New-VIProperty -Name lunID -ObjectType ScsiLun -Value {
    param($lun)

    [int](Select-String “:L(?\d+)$”`
    -InputObject $lun.RuntimeName).Matches[0].Groups[‘lunID’].Value
    } -Force | Out-Null

    $esxName = “esx04”
    Get-VMHost $esxName | Get-ScsiLun | Select CanonicalName, LunType, CapacityMB, MultipathPolicy, lunID

    i have saved above script as .ps1 but getting error
    Select-Object : Cannot index into a null array.
    At C:\scripts\LunNumber.ps1:15 char:43
    + Get-VMHost $esxName | Get-ScsiLun | Select <<<< CanonicalName, LunType, CapacityMB, MultipathPol
    icy, lunID

    could you please help ..can i get esx server name in first coloumn it will be ver usefull.

      LucD

      @Ranjit, can you check if the following returns anything ?

      $esxName = "esx04"
      Get-VMHost $esxName | Get-ScsiLun

    Albert

    Wow, this is very useful script to know which LUN ID a datastore is recognized in ESXi level.

    I have modified the last line of the script as follows:

    Get-VMHost | Get-ScsiLun | Select -Unique CanonicalName, CapacityMB, lunID | Sort lunID | ft -AutoSize

    to display the unique datastore that is accessible by the ESXi hosts in my VCenter, However is there any way to translate the NAA.id into the datastore name to make it more meaning ful ?

    instead of naa.60060160e31027923fdea652e3512345 it should display the name like in Get-Datastore cmdlet ?

      LucD

      @Albert, everything is possibile πŸ˜‰
      The following new property will display the DatastoreName.

      New-VIProperty -Name lunDatastoreName -ObjectType ScsiLun -Value {
      param($lun)

      $ds = $lun.VMHost.ExtensionData.Datastore | %{Get-View $_} | `
      where {$_.Summary.Type -eq "VMFS" -and
      ($_.Info.Vmfs.Extent | where {$_.DiskName -eq $lun.CanonicalName})}
      if($ds){
      $ds.Name
      }
      } -Force | Out-Null

      You can use it like this

      Get-VMHost $esxName | Get-ScsiLun | Select CanonicalName, CapacityMB, lunID,lunDatastoreName

      Just one word of warning, this new property is very slow as you will notice.

    Robert van den Nieuwendijk

    This is an interesting New-VIProperty command. But it only works for vSphere 4. It will also work for VMware Infrastructure 3.5 if you change it into:

    New-VIProperty -Name lunID -ObjectType ScsiLun -Value {
    param($lun)

    if ($lun.RuntimeName) {
    [int](Select-String “:L(?\d+)$” `
    -InputObject $lun.RuntimeName).Matches[0].Groups[‘lunID’].Value
    }
    else {
    $lun.CanonicalName.Split(“:”)[-1]
    }
    } -Force

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.