LUN report – datastore, RDM and node visibility

When you are running multi-node vSphere clusters, you probably already had the experience that one or more of your LUNs were not visible on all nodes. Now you can try to find out which LUN is missing on which node the hard way through the vSphere client. Or you can use the force of PowerCLI and run a script that will report all this in a handy spreadsheet.

To make the script as flexible as possible it should be able to handle any n-node cluster. And as you some of you might know, the Export-CSV cmdlet has some problems with variable length rows. Luckily there is a handy solution I already used in my yadr – A vDisk reporter post.

The script

Annotations

Line 1: The definition of the parameters that can be used with the script. Note that the second parameter takes a default when is not present.

Line 3: If you would run the script multiple times from the same PowerCLI prompt you would get an error saying “Add-Type : Cannot add type. The type name ‘LunInfo’ already exists.“. To avoid this error the script generates on each run a random number between 1 and 99999, which it appends to the type name. This should, unless you have thousands of clusters avoid the error message.

Line 5-19: Since the number of nodes is unknown before the script is actually running, I create a new type, called LunInfon (where n is the random number generated before).

Line 14-16: The new type will contain a property for each node in the cluster. The name of this property is the first qualifier of the FQDN of the host.

Line 21: The script keeps all the information it will gather in a hash table called $scsiTab. The key into the hash table is composed from short hostname and the Canonical name of the LUN.

Line 26-33: From the information provided by the Get-ScsiLun cmdlet, the script will populate the hash table. In this loop the CanonicalName and the Capacity of the LUN are stored in the hash table.

Line 36-43: From the Datastore object the script finds out for all datastores in the cluster which LUN they use.

Line 45-55: The script runs through all the virtual machines on the cluster and checks all virtual disks if they are RDM backed. If the script encounters a RDM it stores the name of the virtual machine and the label of the hard disk in the hash table.

Line 57-68: All the information in the hash table is now grouped per Canonical name. For each Canonical name the script creates a LunInfon object and stores the information from the hash table in that object.

Line 69-70: The array with LunInfon objects is exported to a CSV file and the CSV file is opened.

Usage

You save the script as a .ps1 file. In the example screenshots below I used the name Cluster-LUN-list.ps1.

Start the PowerCLI prompt and make sure that you are connected to the vCenter.

From the PowerCLI prompt you can call the script with the name of a cluster as a parameter.

In this case the script will create the CSV file as C:\Temp\MyCluster17-LUN.csv.

Or you pass the name of the CSV file as a second parameter to the script.

In this case the script will store the report in LunRpt.csv on the root of the D-partition.

Note that some local disks seem to have the same Canonical name on all nodes in a cluster. I experienced that with some IBM RAID Controllers. In that case the entries for those disks will not be correct in the report. In itself this is not really a problem since those disks are local and no LUNs from the SAN.

The report

The following screenshot shows a report made for a 4-node cluster.

You can clearly see which LUNs are:

  • only visible on 1 of the nodes
  • used as RDM disks
  • used for datastores
  • still available

This report will surely make it easier to talk with your Storage Administrator 😉

114 Comments

    George

    I like the script and I want to use it but is not working because hosts name contains dots.

    Our hosts are named with dot inside, basically IP of the host is also set as name, and script failes for this reason.

    I tried to change the script but I can’t make it run, maybe you can give a hint.

    I tried like this:

    param($clusName,$csvName=(“C:\Temp\” + $clusName + “-LUN.csv”))
    $rndNum = Get-Random -Maximum 99999
    $LunInfoDef = @”
    public string ClusterName;
    public string CanonicalName;
    public string UsedBy;
    public string SizeMB;
    “@
    $LunInfoDef = “public struct LunInfo” + $rndNum + “{n" + $LunInfoDef
    $esxServers = Get-Cluster $clusName | Get-VMHost | Sort-Object -Property Name
    $esxServers | %{
    #$LunInfoDef += ("
    ntpublic string " + ($_.Name.Split(".")[0]) + ";")
    #$LunInfoDef += ("
    ntpublic string " + ($_.Name) + ";")
    #$LunInfoDef += ("
    ntpublic string " + [Regex]::Escape(($_.Name)) + ";")
    #$LunInfoDef += ("
    ntpublic string " + """($_.Name)) + "";")
    $LunInfoDef += ("
    ntpublic string " + "“” + ($_) + “";")
    }
    $LunInfoDef += "
    n}”
    Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    #Add-Type -Language Csharp -TypeDefinition $LunInfoDef
    $scsiTab = @{}
    $esxServers | %{
    $esxImpl = $_
    # Get SCSI LUNs
    $esxImpl | Get-ScsiLun | where {$_.LunType -eq “Disk”} | %{
    #$key = $esxImpl.Name.Split(“.”)[0] + “-” + $_.CanonicalName.Split(“.”)[1]
    $key = $esxImpl.Name + “-” + $_.CanonicalName.Split(“.”)[1]
    if(!$scsiTab.ContainsKey($key)){
    $scsiTab[$key] = $_.CanonicalName,””,$_.CapacityMB
    }
    }
    # Get the VMFS datastores
    $esxImpl | Get-Datastore | where {$_.Type -eq “VMFS”} | Get-View | %{
    $dsName = $_.Name
    $_.Info.Vmfs.Extent | %{
    #$key = $esxImpl.Name.Split(“.”)[0] + “-” + $_.DiskName.Split(“.”)[1]
    $key = $esxImpl.Name + “-” + $_.DiskName.Split(“.”)[1]
    $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2]
    }
    }
    }

    but I get this errors:
    PS C:\temp\vmware> .\Cluster-LUN-list.ps1 mhq
    Add-Type : c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(6) : Invalid token ‘”10.1.217.10″‘ in class, struct, or interface member declaration
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(5) : public string SizeMB;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(6) : >>> public string “10.1.217.10”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(7) : public string “10.1.217.20”;
    At C:\temp\vmware\Cluster-LUN-list.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (Microsoft.Power…peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    Add-Type : c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(7) : Invalid token ‘”10.1.217.20″‘ in class, struct, or interface member declaration
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(6) : public string “10.1.217.10”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(7) : >>> public string “10.1.217.20”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(8) : public string “10.1.217.30”;
    At C:\temp\vmware\Cluster-LUN-list.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (Microsoft.Power…peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    Add-Type : c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(8) : Invalid token ‘”10.1.217.30″‘ in class, struct, or interface member declaration
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(7) : public string “10.1.217.20”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(8) : >>> public string “10.1.217.30”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(9) : public string “10.1.217.40”;
    At C:\temp\vmware\Cluster-LUN-list.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (Microsoft.Power…peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    Add-Type : c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(9) : Invalid token ‘”10.1.217.40″‘ in class, struct, or interface member declaration
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(8) : public string “10.1.217.30”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(9) : >>> public string “10.1.217.40”;
    c:\Users\M-2329\AppData\Local\Temp\sbuzupwl.0.cs(10) : }
    At C:\temp\vmware\Cluster-LUN-list.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (Microsoft.Power…peCompilerError:AddTypeCompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    Add-Type : Cannot add type. Compilation errors occurred.
    At C:\temp\vmware\Cluster-LUN-list.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Add-Type], InvalidOperationException
    + FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand

    Gabriel

    Hello Lucd!

    I tested the script in the powershell version, and it worked:

    NameValue
    —- —–
    PSVersion 5.1.14409.1027
    PSEdition Desktop

    but in versions other than 5.1 and variations or version 7 of powershell, I can’t generate the information.

    NameValue
    —- —–
    PSVersion 7.3.3
    PSEdition Core
    GitCommitId 7.3.3
    OS Microsoft Windows 10.0.19044

    Some of the errors I get:

    Line |
    15 | Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    | ~~~~~~~~~~~~~~
    | Cannot bind parameter ‘Language’. Cannot convert value “CsharpVersion3” to type “Microsoft.PowerShell.Commands.Language”. Error: “Unable to match the identifier name CsharpVersion3
    | to a valid enumerator name. Specify one of the following enumerator names and try again: CSharp”
    InvalidOperation: C:\Users\vmware\VMware_CLI\Cluster-LUN-list.ps1:31:1
    Line |
    31 | $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2]
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~
    | Cannot index into a null array.
    InvalidOperation: C:\Users\vmware\VMware_CLI\Cluster-LUN-list.ps1:31:1
    Line |
    31 | $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2]

    My question is this: Are there requirements to use your script? I installed framework 3.5 and still, I can’t successfully run your script in the mentioned versions of powershell.

    Thank you Lucd!

      LucD

      Try replacing

      Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef

      with

      Add-Type -Language Csharp -TypeDefinition $LunInfoDef

    avesh sampara

    Hi LucD,

    How to fetch the details for all the clusters in a vcenter into one file.

    Thanks,
    Avesh

      LucD

      You remove the Export-Csv and Invoke-Item in the script.

      Then create a foreach loop, and in there call the updated script for each cluster.

      Get-Cluster |
      Foreach-Object -Process {
      .\Cluster-LUN-list-updated.ps1 $_.Name
      } |
      Export-Csv -Path .\report.csv -NoTypeInformation -UseCulture

    David

    Hi LucD
    Nice Script thank you very much

    I would like to add the Lun Number for each NAA.* found in the report with this command
    $esxcli.storage.core.path.list($_.DeviceName) | %{new-object PSObject -Property @{LunId =”L”+$_.Lun}}
    if you have an idea
    Thanks

    David

      LucD

      Hi David,
      You can try the version below.
      Instead of ‘OK’ it shows the LUNid in each ESXi column.

      I made this version to discover discrepancies in LUN assignments when using zoning on the SAN.


      param(
      [string]$ClusterName
      )

      $csvName= ".\$($ClusterName)-$(Get-Date -Format 'yyyy-MM-dd-hh-mm')-LUN.csv"

      $rndNum = Get-Random -Maximum 99999

      $LunInfoDef = @"
      public string ClusterName;
      public string CanonicalName;
      public string UsedBy;
      public string DSC;
      public string SizeGB;
      "@
      $LunInfoDef = "public struct LunInfo" + $rndNum + "{
      n" + $LunInfoDef

      $esxServers = Get-Cluster $ClusterName | Get-VMHost | Sort-Object -Property Name
      $esxServers | %{
      $LunInfoDef += ("
      ntpublic string " + ($_.Name.Split(".")[0]) + ";")
      }
      $LunInfoDef += "
      n}"

      Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef

      $scsiTab = @{}
      $esxServers | %{
      $esxImpl = $_

      # $scsiTab layout
      # Key: #
      # Value:
      # 1) canonicalname
      # 2) datastorename or VM/harddiskname
      # 3) capacity (GB)
      # 4) LunId
      # 5) datastoreclustername
      #

      # Get SCSI LUNs
      if(([Version]$esxImpl.Version).Major -lt 6){
      $esxImpl | Get-ScsiLun | where {$_.LunType -eq "Disk"} | %{

      $key = $esxImpl.Name.Split(".")[0] + "#" + $_.CanonicalName.Split(".")[1]
      if(!$scsiTab.ContainsKey($key)){
      $lunId = $_.RuntimeName.Split('L')[1]
      $scsiTab[$key] = $_.CanonicalName,"",$_.CapacityGB,$lunId,""
      }
      }
      }
      Else{
      $esxImpl.ExtensionData.Config.StorageDevice.ScsiLun | Where-Object{$_.LunType -eq 'disk'} |%{
      $key = $esxImpl.Name.Split(".")[0] + "#" + $_.CanonicalName.Split(".")[1]
      $capacityGB = $_.Capacity.Block * $_.Capacity.BlockSize / 1GB
      $lunUuid = $_.Uuid
      $lun = $esxImpl.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | Where-Object{$_.Id -eq $lunUuid}
      $lunId = $lun.Path[0].Name.Split('L')[1]
      $scsiTab[$key] = $_.CanonicalName,"",$capacityGB,$lunId,""
      }
      }

      # Get the VMFS datastores
      $esxImpl | Get-Datastore | Where-Object {$_.Type -eq "VMFS"} | Get-View | %{
      $dsName = $_.Name
      $dscName = ''
      if($_.Parent.Type -eq 'StoragePod'){
      $dscName = Get-View -Id $_.Parent -Property Name -Server $esxImpl.Uid.Split('@')[1].Split(':')[0] | Select -ExpandProperty Name
      }
      $_.Info.Vmfs.Extent | %{
      $key = $esxImpl.Name.Split(".")[0] + "#" + $_.DiskName.Split(".")[1]
      $scsiTab[$key][1] = $dsName
      $scsiTab[$key][4] = $dscName
      }
      }
      }

      # Get the RDM disks
      Get-Cluster $ClusterName | Get-VM | Get-View | %{
      $vm = $_
      $vm.Config.Hardware.Device | Where-Object {$_.gettype().Name -eq "VirtualDisk"} | %{
      if($_.Backing.PSObject.Properties['CompatibilityMode'] -and "physicalMode","virtualmode" -contains $_.Backing.CompatibilityMode){
      $disk = $_.Backing.LunUuid.Substring(10,32)
      $key = (Get-View $vm.Runtime.Host -Server $esxImpl.Uid.Split('@')[1].Split(':')[0]).Name.Split(".")[0] + "#" + $disk
      $scsiTab[$key][1] = $vm.Name + "/" + $_.DeviceInfo.Label
      }
      }
      }

      $scsiTab.GetEnumerator() | Group-Object -Property {$_.Key.Split("#")[1]} | %{
      $lun = New-Object ("LunInfo" + $rndNum)
      $lun.ClusterName = $ClusterName
      $_.Group | %{
      $esxName = $_.Key.Split("#")[0]
      $lun.$esxName = $_.Value[3]
      if(!$lun.CanonicalName){$lun.CanonicalName = $_.Value[0]}
      if(!$lun.UsedBy){$lun.UsedBy = $_.Value[1]}
      if(!$lun.SizeGB){$lun.SizeGB = [math]::Round($_.Value[2],0)}
      $lun.DSC = $_.Value[4]
      }
      $lun
      }

    Joseph

    I use these script alot, LUCD, is there a way to add LUN ID to map the the naa ? that would help alot

    Thanks

    Vechiatto

    How could I list all the clusters in a single report?

    ttekdamar

    You can try to use “.ExtensionData.config.Network.DnsConfig.Hostname” instead of “.Name.Split(“.”)[0]”. This changes solved my problem.

    #### #### #### #### ####
    param($clusName,$csvName=(“C:\Temp\” + $clusName + “-LUN.csv”))

    $rndNum = Get-Random -Maximum 99999

    $LunInfoDef = @”
    public string ClusterName;
    public string CanonicalName;
    public string UsedBy;
    public string SizeMB;
    “@
    $LunInfoDef = “public struct LunInfo” + $rndNum + “{n" + $LunInfoDef

    $esxServers = Get-Cluster $clusName | Get-VMHost | Sort-Object -Property Name
    $esxServers | %{
    $LunInfoDef += ("
    ntpublic string " + ($_.ExtensionData.config.Network.DnsConfig.Hostname) + ";")
    }
    $LunInfoDef += "
    n}”

    Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef

    $scsiTab = @{}
    $esxServers | %{
    $esxImpl = $_

    # Get SCSI LUNs
    $esxImpl | Get-ScsiLun | where {$_.LunType -eq “Disk”} | %{

    $key = $esxImpl.ExtensionData.config.Network.DnsConfig.Hostname + “-” + $_.CanonicalName.Split(“.”)[1]
    if(!$scsiTab.ContainsKey($key)){
    $scsiTab[$key] = $_.CanonicalName,””,$_.CapacityMB
    }
    }

    # Get the VMFS datastores
    $esxImpl | Get-Datastore | where {$_.Type -eq “VMFS”} | Get-View | %{
    $dsName = $_.Name
    $_.Info.Vmfs.Extent | %{
    $key = $esxImpl.ExtensionData.config.Network.DnsConfig.Hostname + “-” + $_.DiskName.Split(“.”)[1]
    $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2]
    }
    }
    }

    # Get the RDM disks
    Get-Cluster $clusName | Get-VM | Get-View | %{
    $vm = $_
    $vm.Config.Hardware.Device | where {$_.gettype().Name -eq “VirtualDisk”} | %{
    if(“physicalMode”,”virtualmode” -contains $_.Backing.CompatibilityMode){
    $disk = $_.Backing.LunUuid.Substring(10,32)
    $key = (Get-View $vm.Runtime.Host).config.Network.DnsConfig.Hostname + “-” + $disk
    $scsiTab[$key][1] = $vm.Name + “/” + $_.DeviceInfo.Label
    }
    }
    }

    $scsiTab.GetEnumerator() | Group-Object -Property {$_.Key.Split(“-“)[1]} | %{
    $lun = New-Object (“LunInfo” + $rndNum)
    $lun.ClusterName = $clusName
    $_.Group | %{
    $esxName = $_.Key.Split(“-“)[0]
    $lun.$esxName = “ok”
    if(!$lun.CanonicalName){$lun.CanonicalName = $_.Value[0]}
    if(!$lun.UsedBy){$lun.UsedBy = $_.Value[1]}
    if(!$lun.SizeMB){$lun.SizeMB = $_.Value[2]}

    }
    $lun
    } | Export-Csv $csvName -NoTypeInformation -UseCulture
    Invoke-Item $csvName
    #### #### #### #### ####

    shanfitz

    LucD, I’m trying to run your script against a VCSA 5.5 envrionment, using PowerCLI 5.5 R1 from a Win2012 box…I am very much a novice with regards PowerCLI, but can normally modify someone else’s code to meet my needs…that said, I’m having issues running this script in my environment…it is a mixed environment of hosts named with IP and others with hostname (something that was implemented prior to me coming here) and that may be part of my problem…below are the errors I see when running the command against a cluster named “Development”…

    Add-Type : c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(6) :
    Invalid token ’10’ in class, struct, or interface member declaration
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(5) : public string
    SizeMB;
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(6) : >>> public
    string 10;
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(7) : public string
    10;
    At C:\_Scripts\Cluster-LUN-List.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (c:\Users\Admini…ber declaration:
    CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.
    AddTypeCommand

    Add-Type : c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(7) :
    Invalid token ’10’ in class, struct, or interface member declaration
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(6) : public string
    10;
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(7) : >>> public
    string 10;
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(8) : public string
    10;
    At C:\_Scripts\Cluster-LUN-List.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (c:\Users\Admini…ber declaration:
    CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.
    AddTypeCommand

    Add-Type : c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(8) :
    Invalid token ’10’ in class, struct, or interface member declaration
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(7) : public string
    10;
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(8) : >>> public
    string 10;
    c:\Users\Administrator\AppData\Local\Temp\u1vjnfrn.0.cs(9) : public string
    rack50node18;
    At C:\_Scripts\Cluster-LUN-List.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (c:\Users\Admini…ber declaration:
    CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.
    AddTypeCommand

    Add-Type : Cannot add type. There were compilation errors.
    At C:\_Scripts\Cluster-LUN-List.ps1:19 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Add-Type], InvalidOperationExc
    eption
    + FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.Ad
    dTypeCommand

    #### When I run $luninfodef, below is what I see (redacted to protect the innocent)…:-)

    public struct LunInfo99362{
    public string ClusterName;
    public string CanonicalName;
    public string UsedBy;
    public string SizeMB;
    public string 10.1xx.xx.11
    public string 10.1xx.xx.15
    public string 10.1xx.xx.26
    public string rack50node18.site.company.net
    public string rack50node20.site.company.net
    public string rack51node17.site.company.net
    public string rack51node20.site.company.net
    }

    ### Any assistance/direction you can provide would be very much appreciated!

    Joe

    Hi LucD,

    I have a cluster with 10 ESXi hosts and about 50 RDM LUN’s. Do you have a script that I can run to detach all these RDM’s on all the hosts in the cluster. The VMware method of detaching RDM’s from vSphere client is fine, but for a couple of RDM’s only.

    Thanks in advance

    Joe

      LucD

      Just to clarify, you mean detach the RDMs from the VMs, in that cluster, to which they are attached ?
      Or do you mean something else ?

    Justin Smith

    Script works great and generates the report Im looking for, minus the VMName which is blank. I do get an error (see below) but it doesnt seem to be talking about the VMName. Is there a reason why the VMName isnt populating in the excel spreadsheet?

    Here’s the error Im getting, but the CanonicalName is populating.

    Get-ScsiLun : Cannot validate argument on parameter ‘CanonicalName’. The argument is null or empty. Provide an
    argument that is not null or empty, and then try the command again.
    At H:\VM Scripts\storage_details.ps1:76 char:59
    + $RuntimeName = Get-ScsiLun -vmhost $vmHost -CanonicalName $naaid | Select -Expan …
    + ~~~~~~
    + CategoryInfo : InvalidData: (:) [Get-ScsiLun], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.Host.GetSc
    siLun

    William

    Is there a way to make this work with host names that are put in by IP address?

    AJ

    Hello all..
    Can we have a updated script for this to run against the vcenter 5.5 and with power CLI 5.5 release 2 . I cant seem to execute this with PCLI rel 2. Any ideas is appreciated .. Thank you ..

    Scott

    LucD, first, wanted to say thanks, I learn so very much from your posts and scripts. Second, I work in a shop with a large VM environmet, including clusters with in excess of 20 hosts and hundreds of LUNs presented to each. We had a need to determine the LUN # of disks on a host by host basis. So I did some HallMark scripting, when you care to copy the very best. When I added a get-ScsiLun to the loops, it took over 12 hours to process a single host in a large cluster. to resolve this, Using your code as the base, and adding a second hash table to store scsi LUN RTN values in, while that takes 10 minutes or so to build, the largest clusters now process in 20 minutes or so. also added logic to process a single cluster or all clusters and messaging. Thought some of your followers might find it helpful.
    if ($args.Length -eq 0) {
    $PClust = $null }
    else {($PClust = $args[0]) }
    function Detail-Clusterdisks {
    param($clusName,$csvName=(“C:\Temp\” + $clusName + “-LUN.csv”))

    $startTime = Get-Date
    Write-Host “Begin $clusName at $starttime”
    $rndNum = Get-Random -Maximum 99999
    $LunInfoDef = @”
    public string ClusterName;
    public string CanonicalName;
    public string UsedBy;
    public string SizeMB;
    “@
    $LunInfoDef = “public struct LunInfo” + $rndNum + “{n" + $LunInfoDef

    # $esxservers is the driver for several loops within this script
    $esxServers = Get-Cluster $clusName | Get-VMHost | Sort-Object -Property Name
    $esxServers | %{
    $LunInfoDef += ("
    ntpublic string " + ($_.Name.Split(".")[0]) + ";")
    }
    $LunInfoDef += "
    n}”

    Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    # We will use two Hashtables $scsiTab will store results for reporting,
    # $LunTab store RuntimeNames used in the report,
    $scsiTab = @{}
    $LunTab = @{}

    # build a table of SCSILuns, and RunTime Names, Use the same $Key for $LunTab as
    # the $scsiTab hash table
    $showtime = Get-Date
    Write-Host “$showtime Building Cluster LUN Runtime Name table.” -ForegroundColor DarkGreen
    $esxServers | %{
    $hname = $_.name
    $lunlist = Get-ScsiLun -VmHost $Hname -luntype disk | select VMHost, CanonicalName, RuntimeName
    $lunlist | %{
    $key = $Hname.Split(“.”)[0] + “-” + $_.CanonicalName.Split(“.”)[1]
    if (!$LunTab.ContainsKey($key)) { $LunTab[$key] = $_.RuntimeName }
    }
    }

    $esxServers | %{
    $esxImpl = $_
    Write-Host “`tprocessing $esxImpl” -ForegroundColor Red

    # Get SCSI LUNs
    $showtime = Get-Date
    Write-Host “$showtime Processing SCSI LUNs” -ForegroundColor DarkGreen
    $esxImpl | Get-ScsiLun | where {$_.LunType -eq “Disk”} | %{
    $key = $esxImpl.Name.Split(“.”)[0] + “-” + $_.CanonicalName.Split(“.”)[1]
    if(!$scsiTab.ContainsKey($key)){
    $scsiTab[$key] = $_.CanonicalName,””,$_.CapacityMB,$_.RuntimeName
    }
    }

    # Get the VMFS datastores
    $showtime = Get-Date
    Write-Host “$showtime Processing VMFS datastores” -ForegroundColor DarkGreen
    $esxImpl | Get-Datastore | where {$_.Type -eq “VMFS”} | Get-View | %{
    $dsName = $_.Name
    $_.Info.Vmfs.Extent | %{
    $key = $esxImpl.Name.Split(“.”)[0] + “-” + $_.DiskName.Split(“.”)[1]
    $RTN = $LunTab[$key]
    $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2], $rtn
    }
    }
    }

    # Get the RDM disks
    $showtime = Get-Date
    Write-Host “$showtime Processing RDM devices” -ForegroundColor DarkGreen
    Get-Cluster $clusName | Get-VM | Get-View | %{
    $vm = $_
    $vm.Config.Hardware.Device | where {$_.gettype().Name -eq “VirtualDisk”} | % {
    if (“physicalMode”,”virtualmode” -contains $_.Backing.CompatibilityMode) {
    $disk = $_.Backing.LunUuid.Substring(10,32)
    $key = (Get-View $vm.Runtime.Host).Name.Split(“.”)[0] + “-” + $disk
    $RTN = $LunTab[$key]
    $scsiTab[$key][1] = $vm.Name + “/” + $_.DeviceInfo.Label
    $scsiTab[$key][3] = $rtn
    }
    }
    }
    $showtime = Get-Date
    Write-Host “$showtime Generating report $csvName”
    $scsiTab.GetEnumerator() | Group-Object -Property {$_.Key.Split(“-“)[1]} | %{
    [int]$cnt = -1
    $lun = New-Object (“LunInfo” + $rndNum)
    $lun.ClusterName = $clusName
    $_.Group | %{ $esxName = $_.Key.Split(“-“)[0]
    $cnt++
    if (!$lun.$esxName) {
    if ($_.Value[1].length -eq 0) {
    $lun.$esxName = $_.Value[3]
    }
    if ($_.Value[3].count -eq 1 ) {
    $lun.$esxName = $_.Value[3]
    } else {
    $lun.$esxName = $_.Value[3][$cnt]
    }
    }
    if(!$lun.CanonicalName){$lun.CanonicalName = $_.Value[0]}
    if(!$lun.UsedBy){$lun.UsedBy = $_.Value[1]}
    if(!$lun.SizeMB){$lun.SizeMB = $_.Value[2]}
    }
    $lun
    } | Export-Csv $csvName -NoTypeInformation -UseCulture
    Write-Host “$csvname is ready for review”
    Invoke-Item $csvName
    $EndTime = Get-Date
    $tspan = New-TimeSpan $startTime $endtime
    $Outmsg = “Processing time for $clusName $tspan”
    Write-Host $Outmsg -BackgroundColor Black -ForegroundColor DarkYellow
    } # End function Detail-ClusterDisks
    #Connect to vCenter Server
    $ProcStart = get-date
    if ($DefaultVIServer -ne “blahblahblah”) { Connect-VIServer blahblahblah}
    if ($pclust -eq $null) {
    Get-Cluster | %{ Detail-ClusterDisks $_ }
    } else {Get-Cluster $pClust | %{ Detail-ClusterDisks $_ }}
    $ProcEnd = get-date
    $tspan = New-TimeSpan $Procstart $ProcEnd
    $Outmsg = “Processing time for all clusters $tspan”
    Write-Host $Outmsg -BackgroundColor Black -ForegroundColor DarkYellow

      LucD

      Wow, thanks Scott, a really great new application of the technique.
      Thanks for sharing this with all of us, I’m pretty sure it will come in handy for a lot of readers.
      Luc

      Justin

      I ran this against one of my test Clusters that have hit the limit of LUN’s per host (Mostly Oracle RDM’s).

      Under each host in a cluster it gives me different letters? h, v, a, m, and b. Not sure what they mean? The ClusterName, CanonicalName, and UsedBy give me data that makes sense, its just the data under the hosts.

    Ryan

    Hey LucD I am getting the errors below when attempting to run the script. Any ideas on what the issue is?

    Add-Type : c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(6) : ; expected
    c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(5) : public string SizeMB;
    c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(6) : >>> public string host1;
    c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(7) : public string host2;
    At C:\PowerCLI\Get-ClusterLunInfo2.ps1:18 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (c:\Users\user…002: ; expected:CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    Add-Type : c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(6) : Invalid token ‘;’ in class, struct, or interface member declaration
    c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(5) : public string SizeMB;
    c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(6) : >>> public string host1;
    c:\Users\user\AppData\Local\Temp\wfrlejmc.0.cs(7) : public string host2;
    At C:\PowerCLI\Get-ClusterLunInfo2.ps1:18 char:1
    + Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (c:\Users\user…ber declaration:CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

      LucD

      Hi Ryan,
      Which PowerShell version are you running ?
      Do a $psversiontable.

      It could also be something went wrong in the copy/paste of the code.
      Double click inside the code window, that should select all code, and then you can do a copy, followed by a paste into your editor.
      Luc

        Ryan

        I’m running powershell version 4.

    shreyas

    hi LUC,

    nice script.. i want to get storage device id and storage array list along with LUN id and cannonical name. Is it possible to get all these data in excel in one click.

    thnaks in advance..

    Leonardo DAngelo Gonçalves

    Just a PERFECT script!!! Exactly I am looking for!!!

    Thanks a lot!!!!

    David

    @LucD ~ Excellent script! Thank you so much for posting this! I have found this VERY useful! I have two feature request – if possible? When you get a chance, can you edit your script and add the following?

    – Add the VM that is using the RDM in the UsedBy column, so the cell is not left empty
    – Find NFS mount points and add them to the list too?

    Once again, thank you for posting your script!

    David

    Johan

    Hi Luc

    Any chance you have a version of this script that can query the entire Virtual Centre. Need to find a way to list all SCSI devices from a specific array to assist with a cleanup or de-comm process.

    Thanks

    Johan

      LucD

      Hi Johan, do you have several clusters in your vCenter ? If yes, you could call the script for each cluster. Something like

      Get-Cluster | %{./Cluster-LUN-List.ps1 $_.Name}

      This would produce a CSV file per cluster.

      If you also have stand-alone ESXi servers in your vCenter, the script would need some changes.
      Btw, do you have shared datastores between the stand-alone ESXi servers ?

    Vineeth

    Hi lucd
    Ton of thanks for this good script but it’s not running in power cli 5.5 any update for this version.

    Error:
    param : The term ‘param’ is not recognized as the name of a cmdlet, function,
    script file, or operable program. Check the spelling of the name, or if a path
    was included, verify that the path is correct and try again.

    Saeed

    Hello,

    Does it work with vCenter 5 & ESXi5, I am not able to run the script

    param : The term ‘param’ is not recognized as the name of a cmdlet, function,
    script file, or operable program. Check the spelling of the name, or if a path
    was included, verify that the path is correct and try again.
    At X:\ps\VMwareCluster-LUNs.ps1

    Thanks

      admin

      @Saeed, yes, the script should work in vSphere 5.*.
      Is the line with the Param keyword, the first line in the .ps1 file ?

        Saeed

        Yes, it’s the first line
        I am not a power shell expert, I just copy and save it as .ps1
        Thanks & appreciate your reply

    Purna.Yeluri

    Hi Lucd,

    This is excellent script, been handy for all FC datastore inconsistent mappings..
    But, we have lot many “NFS datastores” on large number of Clusters..

    Can you provide separate script, which can check whether “NFS datastores” are uniformly mapped to all ESX Hosts in cluster or not?? If any misses highlight same (like your above script)??

    Thank you in adv..

      admin

      Thanks.
      That is a good suggestion, I’ll try to come up with something.

    Sam

    Luc Tried replacing “-” with * on the lines you called out no luck. I weird results in the out put when using replace and other chacther.

    Property ‘opc-c4-vmh00.60a980006465586e424a6a415378374a’ cannot be found on this object; make sure it exists and is settable.
    At C:\temp\SecScripts\CompareLuns.ps1:64 char:3
    + $lun.$esxName = “ok”
    + ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

    Property ‘opc-c4-vmh00.60a9800064656150576f6a4156702d46’ cannot be found on this object; make sure it exists and is settable.
    At C:\temp\SecScripts\CompareLuns.ps1:64 char:3
    + $lun.$esxName = “ok”
    + ~~~~~~~~~~~~~~~~~~~~

    The Script

    param($clusName,$csvName=(“C:\Temp\” + $clusName + “-LUN.csv”))

    $rndNum = Get-Random -Maximum 99999

    $LunInfoDef = @”
    public string ClusterName;
    public string CanonicalName;
    public string UsedBy;
    public string SizeMB;
    “@
    $LunInfoDef = “public struct LunInfo” + $rndNum + “{n" + $LunInfoDef

    $esxServers = Get-Cluster $clusName | Get-VMHost | Sort-Object -Property Name
    $esxServers | %{
    $LunInfoDef += (“
    ntpublic string ” + ($_.Name.Split(“.”)[0].Replace('-','')) + ";")

    }
    $LunInfoDef += "
    n}”

    Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef

    $scsiTab = @{}
    $esxServers | %{
    $esxImpl = $_

    # Get SCSI LUNs
    $esxImpl | Get-ScsiLun | where {$_.LunType -eq “Disk”} | %{

    $key = $esxImpl.Name.Split(“.”)[0] + “.” + $_.CanonicalName.Split(“.”)[1]
    if(!$scsiTab.ContainsKey($key)){

    $scsiTab[$key] = $_.CanonicalName,””,$_.CapacityMB
    }
    }

    # Get the VMFS datastores
    $esxImpl | Get-Datastore | where {$_.Type -eq “VMFS”} | Get-View | %{
    $dsName = $_.Name
    $_.Info.Vmfs.Extent | %{
    $key = $esxImpl.Name.Split(“.”)[0] + “.” + $_.DiskName.Split(“.”)[1]
    $scsiTab[$key] = $scsiTab[$key][0], $dsName, $scsiTab[$key][2]
    }
    }
    }

    # Get the RDM disks
    Get-Cluster $clusName | Get-VM | Get-View | %{
    $vm = $_
    $vm.Config.Hardware.Device | where {$_.gettype().Name -eq “VirtualDisk”} | %{
    if(“physicalMode”,”virtualmode” -contains $_.Backing.CompatibilityMode){
    $disk = $_.Backing.LunUuid.Substring(10,32)
    $key = (Get-View $vm.Runtime.Host).Name.Split(“.”)[0] + “.” + $disk
    $scsiTab[$key][1] = $vm.Name + “/” + $_.DeviceInfo.Label
    }
    }
    }

    $scsiTab.GetEnumerator() | Group-Object -Property {$_.Key.Split(“.”)[1]} | %{
    $lun = New-Object (“LunInfo” + $rndNum)
    $lun.ClusterName = $clusName
    $_.Group | %{
    $esxName = $_.Key.Split(“*”)[0]
    $lun.$esxName = “ok”
    if(!$lun.CanonicalName){$lun.CanonicalName = $_.Value[0]}
    if(!$lun.UsedBy){$lun.UsedBy = $_.Value[1]}
    if(!$lun.SizeMB){$lun.SizeMB = $_.Value[2]}

    }
    $lun
    } | Export-Csv $csvName -NoTypeInformation -UseCulture
    Invoke-Item $csvName

      Aaron Green

      Hi Sam,

      Did you ever get traction on this problem? I’m running into the same thing now and would like to know what you did to fix if so. I get a report with all LUNs but none of the “ok”s show up because of it. Thanks!

      Aaron

        LucD

        Hi Aaron,
        I’ll have a look, hold on.

          Aaron

          Hey LucD,

          Did you ever get anywhere with your look? I admittedly have not had the time to dig in more, but was curious of any ideas to maybe point me in a specific direction. Thanks!

          Aaron

          Aaron

          Hi Luc,

          Thought I’d mention that I got this fixed. It required doing the same -Replace on line 15 on lines 28, 39, and 51.

          Aaron

            LucD

            Thanks for providing the fix.

    vcloudguy

    I am seeing the same error. Were you able to find a fix. Thanks in advance.

    vcloudguy

    @SAL

    vcloudguy

    This looks like a great script. But I am unable to run it because I have hyphens in the ESX host names.

    Is there a workaround to that issue? Your help would be appreciated.

    Joe

    Seems I’ve run into a problem. Been using the script for some time now with no issues. Then suddenly starte getting errors. What seems to be occurring is we now have a few Esx hosts that do not have names, rather their .name is an up address like 10.10.10.10. The current split using a “.” ends up with duplicate since each key/ public struct will be 10. I attempted doing a replace of the “.” with nothing so the name would end up 10101010 but that gives an invalid token.

    Any thoughts? Also note the same cluster has both named hosts and hosts with ip addresses only. The only way I have gotten it to semi work was to first replace all “.” with ‘ ‘ and then add a letter both infront an behind the result. So it would look like a10101010a and aESXSRV1a.

    Any idea’s?

    Thanks
    Joe

    Larryy

    What if the disk is presented to two ESXs, one ESX (lets call it esx1) is in this cluster, and one not (lets call it esx2). In that case we will get that RDM is available, even if some vm on esx2 is using tha RDM disk?

    Ghost

    Hi LucD.
    I’m using a script to create a .csv file to monitor the latency of my datastores.
    In this report I put the information I need in this way:

    Entity = $oEntry.Entity

    EntityId = $oEntry.EntityId

    Instance = $oEntry.Instance

    MetricId = $oEntry.MetricId

    Timestamp = ($oentry.Timestamp).toString(‘dd/MM/yyyy HH:mm’)

    Value = $oEntry.Value

    Unit = $oEntry.Unit

    }

    Now, I would like to know if there is a way to change the , that return something like that: 4d4b3f85-db8f3f4c-3fc4-984be1xxxxxx,
    with the name of the datastore.
    Thank you

    V.

    Sumanth

    I believe few commands / verbs got depriciated / removed in Esxi5.

    Luc can you confirm if the error is coz of that.

      LucD

      @Sumanth, that’s the first I hear of that.
      Which commands/verbs do you mean ?

      Do you also see the same error ?

    SAL

    @LucD

    Also tried in another PC, same behavior, anyone has any ideas?

    thanks in advanced

    SAL

    @LucD

    Just tried running as an admin, no luck 😐

    my .NET version is 3.5.1, S.O. windows 7, running vpshere powerCLI 5

    SAL

    @LucD

    thats not the problem, because I did exactly that, more errors 😛

    Add-Type : Could not find file ‘C:\Users\saldanhapa\AppData\Local\Temp\xmknl8cz
    .dll’.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:19 char:9
    + Add-Type <<<< -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + CategoryInfo : NotSpecified: (:) [Add-Type], FileNotFoundExcept
    ion
    + FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.PowerS
    hell.Commands.AddTypeCommand

      LucD

      @SAL, I have seen that problem before.
      It seems to be related to the Just-In-Time serialisation mechanism of .Net. Not a lot I can do there I’m afraid.

      Could you try the script on another PC ?
      Or eventually start the PowerCLI prompt as Administrator ?

    SAL

    great post LucD,
    but I can’t get my script to work

    its full of errors when I run

    Property ‘CanonicalName’ cannot be found on this object; make sure it exists an
    d is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:63 char:32
    + if(!$lun.CanonicalName){$lun. <<<< CanonicalName = $_.Value[0]}
    + CategoryInfo : InvalidOperation: (CanonicalName:String) [], Run
    timeException
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'UsedBy' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:64 char:25
    + if(!$lun.UsedBy){$lun. <<<< UsedBy = $_.Value[1]}
    + CategoryInfo : InvalidOperation: (UsedBy:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'SizeMB' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:65 char:25
    + if(!$lun.SizeMB){$lun. <<<< SizeMB = $_.Value[2]}
    + CategoryInfo : InvalidOperation: (SizeMB:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null
    .
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:69 char:15
    + } | Export-Csv <<<< $csvName -NoTypeInformation -UseCulture
    + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingV
    alidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
    icrosoft.PowerShell.Commands.ExportCsvCommand

    New-Object : Cannot find type [LunInfo51078]: make sure the assembly containing
    this type is loaded.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:58 char:19
    + $lun = New-Object <<<< ("LunInfo" + $rndNum)
    + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentExcepti
    on
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewOb
    jectCommand

    Property 'ClusterName' cannot be found on this object; make sure it exists and
    is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:59 char:7
    + $lun. <<<< ClusterName = $clusName
    + CategoryInfo : InvalidOperation: (ClusterName:String) [], Runti
    meException
    + FullyQualifiedErrorId : PropertyNotFound

    Property '10' cannot be found on this object; make sure it exists and is settab
    le.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:62 char:8
    + $lun. <<<< $esxName = "ok"
    + CategoryInfo : InvalidOperation: (10:String) [], RuntimeExcepti
    on
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'CanonicalName' cannot be found on this object; make sure it exists an
    d is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:63 char:32
    + if(!$lun.CanonicalName){$lun. <<<< CanonicalName = $_.Value[0]}
    + CategoryInfo : InvalidOperation: (CanonicalName:String) [], Run
    timeException
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'UsedBy' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:64 char:25
    + if(!$lun.UsedBy){$lun. <<<< UsedBy = $_.Value[1]}
    + CategoryInfo : InvalidOperation: (UsedBy:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'SizeMB' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:65 char:25
    + if(!$lun.SizeMB){$lun. <<<< SizeMB = $_.Value[2]}
    + CategoryInfo : InvalidOperation: (SizeMB:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null
    .
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:69 char:15
    + } | Export-Csv <<<< $csvName -NoTypeInformation -UseCulture
    + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingV
    alidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
    icrosoft.PowerShell.Commands.ExportCsvCommand

    New-Object : Cannot find type [LunInfo51078]: make sure the assembly containing
    this type is loaded.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:58 char:19
    + $lun = New-Object <<<< ("LunInfo" + $rndNum)
    + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentExcepti
    on
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewOb
    jectCommand

    Property 'ClusterName' cannot be found on this object; make sure it exists and
    is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:59 char:7
    + $lun. <<<< ClusterName = $clusName
    + CategoryInfo : InvalidOperation: (ClusterName:String) [], Runti
    meException
    + FullyQualifiedErrorId : PropertyNotFound

    Property '10' cannot be found on this object; make sure it exists and is settab
    le.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:62 char:8
    + $lun. <<<< $esxName = "ok"
    + CategoryInfo : InvalidOperation: (10:String) [], RuntimeExcepti
    on
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'CanonicalName' cannot be found on this object; make sure it exists an
    d is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:63 char:32
    + if(!$lun.CanonicalName){$lun. <<<< CanonicalName = $_.Value[0]}
    + CategoryInfo : InvalidOperation: (CanonicalName:String) [], Run
    timeException
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'UsedBy' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:64 char:25
    + if(!$lun.UsedBy){$lun. <<<< UsedBy = $_.Value[1]}
    + CategoryInfo : InvalidOperation: (UsedBy:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'SizeMB' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:65 char:25
    + if(!$lun.SizeMB){$lun. <<<< SizeMB = $_.Value[2]}
    + CategoryInfo : InvalidOperation: (SizeMB:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null
    .
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:69 char:15
    + } | Export-Csv <<<< $csvName -NoTypeInformation -UseCulture
    + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingV
    alidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
    icrosoft.PowerShell.Commands.ExportCsvCommand

    New-Object : Cannot find type [LunInfo51078]: make sure the assembly containing
    this type is loaded.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:58 char:19
    + $lun = New-Object <<<< ("LunInfo" + $rndNum)
    + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentExcepti
    on
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewOb
    jectCommand

    Property 'ClusterName' cannot be found on this object; make sure it exists and
    is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:59 char:7
    + $lun. <<<< ClusterName = $clusName
    + CategoryInfo : InvalidOperation: (ClusterName:String) [], Runti
    meException
    + FullyQualifiedErrorId : PropertyNotFound

    Property '10' cannot be found on this object; make sure it exists and is settab
    le.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:62 char:8
    + $lun. <<<< $esxName = "ok"
    + CategoryInfo : InvalidOperation: (10:String) [], RuntimeExcepti
    on
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'CanonicalName' cannot be found on this object; make sure it exists an
    d is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:63 char:32
    + if(!$lun.CanonicalName){$lun. <<<< CanonicalName = $_.Value[0]}
    + CategoryInfo : InvalidOperation: (CanonicalName:String) [], Run
    timeException
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'UsedBy' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:64 char:25
    + if(!$lun.UsedBy){$lun. <<<< UsedBy = $_.Value[1]}
    + CategoryInfo : InvalidOperation: (UsedBy:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'SizeMB' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:65 char:25
    + if(!$lun.SizeMB){$lun. <<<< SizeMB = $_.Value[2]}
    + CategoryInfo : InvalidOperation: (SizeMB:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null
    .
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:69 char:15
    + } | Export-Csv <<<< $csvName -NoTypeInformation -UseCulture
    + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingV
    alidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
    icrosoft.PowerShell.Commands.ExportCsvCommand

    New-Object : Cannot find type [LunInfo51078]: make sure the assembly containing
    this type is loaded.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:58 char:19
    + $lun = New-Object <<<< ("LunInfo" + $rndNum)
    + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentExcepti
    on
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewOb
    jectCommand

    Property 'ClusterName' cannot be found on this object; make sure it exists and
    is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:59 char:7
    + $lun. <<<< ClusterName = $clusName
    + CategoryInfo : InvalidOperation: (ClusterName:String) [], Runti
    meException
    + FullyQualifiedErrorId : PropertyNotFound

    Property '10' cannot be found on this object; make sure it exists and is settab
    le.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:62 char:8
    + $lun. <<<< $esxName = "ok"
    + CategoryInfo : InvalidOperation: (10:String) [], RuntimeExcepti
    on
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'CanonicalName' cannot be found on this object; make sure it exists an
    d is settable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:63 char:32
    + if(!$lun.CanonicalName){$lun. <<<< CanonicalName = $_.Value[0]}
    + CategoryInfo : InvalidOperation: (CanonicalName:String) [], Run
    timeException
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'UsedBy' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:64 char:25
    + if(!$lun.UsedBy){$lun. <<<< UsedBy = $_.Value[1]}
    + CategoryInfo : InvalidOperation: (UsedBy:String) [], RuntimeExc
    eption
    + FullyQualifiedErrorId : PropertyNotFound

    Property 'SizeMB' cannot be found on this object; make sure it exists and is se
    ttable.
    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\cluster_lun_li
    st.ps1:65 char:25
    + if(!$lun.SizeMB){$lun. <<<< SizeMB = $_.Value[2]}
    + CategoryInfo : InvalidOperation: (SizeMB:String) [], RuntimeExc

      LucD

      Hi Sal,
      It looks as if the Add-Type in line 19 didn’t work.
      Do you get any message before the ones you include in your comment ?
      Are you running the script from a PowerCLI prompt ?
      Luc

      LucD

      @Sal, it looks like you might have copied the line numbers as well.
      In the script box, at the top right, there will be some icons that appear when you hover over them.
      Click the 2nd icon from the left (“copy to clipboard”).
      In an editor you can now do Ctrl-V to paste the script.

    Sumanth

    Sumanth :Hi,
    This script doesnt work against ESX5 environment. Any changes are required ?

      LucD

      @Sumanth, it should work against ESX5.
      Are you using PowerPath ?
      Or do you have hyphens in the names of your ESX5 servers or datastores ?
      Any error messages ?

    Brian

    I am receiving the errors that have been noted. My VM’s and ESXi Hosts have “-” in the names. Not my idea.

    I have tried to add the line
    $LunInfoDef += (“ntpublic string ” + ($_.Name.Split(“.”)[0].Replace(‘-‘,”)) + “;”)

    And attempted to modify all lines with “-“.

    Example:
    Hostname: okc-clu-esx01
    VM: okc-clu-vm01

    Cannot index into a null array.
    At C:\users\nulluser\desktop\LUN.ps1:40 char:36
    + $scsiTab[$key] = $scsiTab[$key][ <<<< 0], $dsName, $scsiTab[$key][2]
    + CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

      LucD

      Hi Brian, I replied in the thread you created on the VMTN PowerCLI Community.
      In short, my earlier reply to Phil, shows how to replace the hyphen in 5 lines with another character to solve the problem.
      I hope that helps.

    Devanshu

    after replacing the luninfo code this what i get

    Unexpected token ‘Replace’ in expression or statement.
    At C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\scripts\DATA_disl.ps1:15 char:70
    + $LunInfoDef += (“ntpublic string ” + ($_.Name.Split(“.”)[0]Replace <<<< ('-','')) + ";")
    + CategoryInfo : ParserError: (Replace:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

      LucD

      @Devanshu, that line should be

      $LunInfoDef += (“
      ntpublic string ” + ($_.Name.Split(“.”)[0].Replace('-','')) + ";")

      But see my answer to Phil, there is no need to eliminate the hyphen in the host names, just pick another character.

    Phil

    @Phil
    should it be:
    $LunInfoDef += (“ntpublic string ” + ($_.Name.Split(“.”)[0] -Replace(‘-‘,”)) + “;”)

    ??

      LucD

      Hi Phil, the hyphen I used to join the hostname and the canonicalname in the hash tab key, is probably not the best choice 🙁 Since the hyphen is an accepted value in a ESX(i) server name.
      The easiest solution would be to replace the hyphen by another character (that is not used in your ESX(i) host names.
      Replace the “-” in lines 28, 39, 51, 57 and 61 by any other character that doesn’t appear in your host names.

    Phil

    Wonderful script. I am having one problem though

    I also have some servers with hyphens in their names. When I try:
    $LunInfoDef += (“ntpublic string ” + ($_.Name.Split(“.”)[0]Replace(‘-‘,”)) + “;”)

    it doesn’t like Replace. PowerGUI shows “unexpected ‘Replace’ in expression or statement”

    alan

    Add-Type : c:\Users\pa-aharrington\AppData\Local\Temp\1\bl3rhkzs.0.cs(6) : Inva
    lid token ‘-‘ in class, struct, or interface member declaration
    c:\Users\pa-aharrington\AppData\Local\Temp\1\bl3rhkzs.0.cs(5) : public stri
    ng SizeMB;
    c:\Users\pa-aharrington\AppData\Local\Temp\1\bl3rhkzs.0.cs(6) : >>> public
    string atl-clv01-01;
    c:\Users\pa-aharrington\AppData\Local\Temp\1\bl3rhkzs.0.cs(7) : public stri
    ng atl-clv01-02;
    At C:\scripts\alan\lunreport.ps1:21 char:9
    + Add-Type <<<< -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + CategoryInfo : InvalidData: (c:\Users\pa-aha…ber declaration:
    CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.
    AddTypeCommand

      LucD

      @Alan, I think I know what happened.
      The script dynamically defines a struct in C#. One of the members of that struct is given the name of the ESX(i) servers in the cluster.
      It seems you have hyphens (-) in the names of your ESX(i) servers, and unfortunately C# doesn’t accept that character in a struct declaration it seems.
      If you replace line 15

      $LunInfoDef += ("
      ntpublic string " + ($_.Name.Split(".")[0]) + ";")

      by this

      $LunInfoDef += ("
      ntpublic string " + ($_.Name.Split(".")[0]Replace('-','')) + ";")

      it might work.
      The disadvantage is that the names of your ESX(i) will be missing the hyphens in their names

    alan

    does this work on powercli 5.0.1 and vcenter 5 with 5 host? i’m getting tons of errors and don’t know where to check…

    thanks!
    alan

    Jason

    I must be missing something. It seems to not like line 19. I have .net3.5.1 installed. But am I supposed to import a module?

    At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\disk_report.ps1:19 char:9
    + Add-Type <<<< -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + CategoryInfo : InvalidData: (c:\Users\anon\A…002: ; expected:CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

      LucD

      @Jason, I suspect you are using PowerShell v1. The Add-Type cmdlet was introduced in PowerShell v2. Do a
      $host.Version
      and check the Major, that should say 2.

    Amit Patange

    @LucD

    Thanks LucD for the script with email and HTML. The script runs into multiple errors… they scroll very fast and hard to capture.

    the one with csv output works fine. Thanks!

    Amit

    Thanks for the great script LucD.

    Is there a way we can get a HTML report for all the clusters in the VC and then add this report to a mail, something like a daily check. This will help to keep a track of the paths and generate some kind of availability report or so.

    Thanks again!

      LucD

      @Amit, that is not that difficult with PowerShell.
      The adapted script will get a LUN report for all the clusters.
      Make sure to update the parameters in the Send-MailMessage cmdlet !
      You can download the script here.

    Andreas

    @LucD
    I’ve tested it with PowerCli 5.0. Also on a different Server.. It’s still the same problem.

    Andreas

    @LucD
    Versions:
    Client OS; Windows Server 2008 R2
    PowerShell: 2.0
    PowerCLI: 4.1.1.28.16
    ESX: 4.1.0
    vCenter:4.1.0

    Thanks for your help.

      LucD

      @Andreas, would it be possible for you to try the same with PowerCLI 5 ?

    Andreas

    I had to run the powershell console as Administrator.. But now I receive the same error as struja:

    Add-Type : c:\Users\tgdnoan4\AppData\Local\Temp\2\1ptgud1r.0.cs(6) : ; expected
    c:\Users\tgdnoan4\AppData\Local\Temp\2\1ptgud1r.0.cs(5) : public string SizeM
    B;
    c:\Users\tgdnoan4\AppData\Local\Temp\2\1ptgud1r.0.cs(6) : >>> public string
    esx01;
    c:\Users\tgdnoan4\AppData\Local\Temp\2\1ptgud1r.0.cs(7) : public string esx
    02;
    At C:\Users\tgdnoan4\Desktop\report.ps1:19 char:9
    + Add-Type <<<>> public string
    esx01;
    c:\Users\tgdnoan4\AppData\Local\Temp\2\1ptgud1r.0.cs(7) : public string esx
    02;
    At C:\Users\tgdnoan4\Desktop\report.ps1:19 char:9
    + Add-Type <<<>> public string
    esx02;
    c:\Users\tgdnoan4\AppData\Local\Temp\2\1ptgud1r.0.cs(8) : public string esx
    03;
    At C:\Users\tgdnoan4\Desktop\report.ps1:19 char:9
    + Add-Type <<<< -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + CategoryInfo : InvalidData: (c:\Users\tgdnoa…002: ; expected:
    CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.
    AddTypeCommand

      LucD

      @Andreas, could you tell me whcih versions your are running ?
      Client OS, PowerShell, PowerCLI, ESX(i) and vCenter ?
      It must be a specific combination of versions that causes this problem.

    Andreas

    @LucD
    The following Versions are installed:
    2.0.50727.4927
    3.0.30729.4926
    3.5.30729.4926

    Andreas

    I get the following error on line 19:
    Add-Type : Could not find file ‘C:\Users\*****\AppData\Local\Temp\2\oc5cfced.dll’.

    What I’m doing wrong?

      LucD

      @Andreas, that could be related to the .Net version you have installed on the PC where you run the script. What .Net version(s) do you have installed ?
      For PowerCLI you have to have “NET 2.0, 3.0, or 3.5 with Service Pack 1” (as per the Release Notes)

    Aman

    The below error wont let me use this script, any help will be appreciated.

    Cannot index into a null array.
    At C:\Program Files\VMware\Infrastructure\vSphere PowerCLI\scripts\Cluster-LUN-list.ps1:40 char:36
    + $scsiTab[$key] = $scsiTab[$key][ <<<< 0], $dsName, $scsiTab[$key][2]
    + CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

    struja

    This script works great, my only problem is that it will not work on my clusters with esxi 4.1 Update 1 hosts. I get the following error on line 9.

    Add-Type : c:\Users\user\AppData\Local\Temp\28\sdqxdcyc.0.cs(6) : ; expected
    c:\Users\user\AppData\Local\Temp\28\sdqxdcyc.0.cs(5) : public string SizeMB;
    c:\Users\user\AppData\Local\Temp\28\sdqxdcyc.0.cs(6) : >>> public string mtc-b04pv01;
    c:\Users\user\AppData\Local\Temp\28\sdqxdcyc.0.cs(7) : public string mtc-b04pv02;
    At P:\PS\LUN-Clueter-Report.ps1:19 char:9
    + Add-Type <<<< -Language CsharpVersion3 -TypeDefinition $LunInfoDef
    + CategoryInfo : InvalidData: (c:\Users\user…002: ; expected:CompilerError) [Add-Type], Exception
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

    MattocG

    Excellent post. Thanks for the advice and tips which have come in handy.

      LucD

      Thanks

    hto

    Hi LucD,
    Your script work great for me. I try to add the LunID property without success.
    Could you help me ?

    Thanks
    HTO

    Huggy Bear

    I am running into the same problem with line 52. If I remove the [1] it almost works. I can it tries to put the name of the vm into the array but it parses it wrong.

    Cannot index into a null array.
    At C:\dev\rdms\datastoreRDMVisability.ps1:52 char:19
    + $scsiTab[$key][ <<<< 1] = $vm.Name + "/" + $_.DeviceInfo.Label
    + CategoryInfo : InvalidOperation: (1:Int32) [], RuntimeExceptio
    n
    + FullyQualifiedErrorId : NullArray

    Cannot index into a null array.
    At C:\dev\rdms\datastoreRDMVisability.ps1:52 char:19
    + $scsiTab[$key][ <<<< 1] = $vm.Name + "/" + $_.DeviceInfo.Label
    + CategoryInfo : InvalidOperation: (1:Int32) [], RuntimeExceptio
    n
    + FullyQualifiedErrorId : NullArray

    Rubeel

    I constantly get errors when i run the script, not sure why this is a problem

    [vSphere PowerCLI] C:\VMScripts> .\storage3.ps1 Utility
    Exception calling “Substring” with “2” argument(s): “Index and length must refer to a location with
    in the string.
    Parameter name: length”
    At C:\VMScripts\storage3.ps1:50 char:40
    + $disk = $_.Backing.LunUuid.Substring <<<< (10,32)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Cannot index into a null array.
    At C:\VMScripts\storage3.ps1:52 char:19
    + $scsiTab[$key][ <<<< 1] = $vm.Name + "/" + $_.DeviceInfo.Label
    + CategoryInfo : InvalidOperation: (1:Int32) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

    Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location with
    in the string.
    Parameter name: length"
    At C:\VMScripts\storage3.ps1:50 char:40
    + $disk = $_.Backing.LunUuid.Substring <<<< (10,32)
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

    Alasdair Carnie

    @LucD
    Hi Luc,

    Yes and no. I’ve had a look at the SDK reference and see what you mean, but if the Device Type is listed just as Virtual Disk, how can I then get a listing of the Properties for a particular disk including the sub properties in the Backing information?

    As far as I can tell, you need to poll the backing info in order to establish the kind of Virtual Disk it is (RDM, PM, VM or regular Disk), or am I making my life more difficult than it needs to be?

    Again, as far as I can tell, I need to be able to list all the properties available to me in order to find a property that matches in both the backing or device info and the properties from either get-scsilun or Config.StorageDevice.Scsilun in order to be able to list the VM, the RDM filename and location, and the LUN number that the RDM is pointing at.

      LucD

      You can use the typename of the object that sits behind the ‘backing’ property to take the correct branch in your code.
      For example:

      switch($dev.backing.GetType().Name){
      'VirtualDiskFlatVer2BackingInfo' {
      # A regular VHD
      }
      'VirtualDiskRawDiskVer2BackingInfo'{
      # A RDM
      }
      }

      Does that make it any clearer ?

    Alasdair Carnie

    Hi Luc,

    I’ve been playing around with the script you wrote on extracting RDM info per VM and I’ve run into a problem. I cannot seem to get a list of all properties for a specific device.

    I ran the script below, but I need to see what other properties are available under the main backing property, and also list the LUN number as part of the report.

    $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, HDDisplayName
    $row.VMName = $vm.Name
    $esx = Get-View $vm.Runtime.Host
    $row.VMHost = ($esx).Name
    $row.HDDeviceName = $dev.Backing.DeviceName
    $row.HDFileName = $dev.Backing.FileName
    $row.HDMode = $dev.Backing.CompatibilityMode
    $row.HDSize = $dev.CapacityInKB
    $row.HDDisplayName = ($esx.Config.StorageDevice.ScsiLun | where {$_.Uuid -eq $dev.Backing.LunUuid}).DisplayName
    $report += $row
    }
    }
    }
    }

    I have tried different permutations of get-member, but get nothing returned. Is there a simple way to get a listing of all properties for backing?

      LucD

      The backing property comes in many flavors, depending on the type of device.
      All these are documented in the SDK Reference.
      For example, for a regular virtual disk you can look at the VirtualDiskFlatVer2BackingInfo object.
      From the base backing object, see VirtualDeviceBackingInfo, you can find all the types in the Extended by section.
      Does that help you ?

    Stew

    Do you have a script that will return the storage path count for each ESX host/vmhba? great script by the way.

      LucD

      @Stew, thanks.
      Do you mean something like this ?

      Get-VMHost | Get-ScsiLun -LunType Disk | `
      Select @{N="Host";E={$_.VMHost.Name}},
      @{N="HBA";E={$_.RuntimeName.Split(':')[0]}},
      @{N="LUN";E={$_.CanonicalName}},
      @{N="#Paths";E={(Get-ScsiLunPath -ScsiLun $_).Count}} | ft -AutoSize

    Rod Repp

    One suggestion, break out not only the LUNs per host, but the luns per host HBA. Trying to find how many hosts amongst hundreds don’t have redundant links to their storage . . . .

      LucD

      @Rodd, that’s a good suggestion. I’ll have a look.

    Todd

    So this script won’t work with a cluster of ESXi servers??? When I run it I get the following:

    The string starting:
    At D:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Scripts\Cluster-LUN-list.ps1:8 char:16
    + $LunInfoDef = <<<< @"
    is missing the terminator: "@.
    At D:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Scripts\Cluster-LUN-list.ps1:139 char:1
    + <<<<
    + CategoryInfo : ParserError: (
    public str…tem $csvName
    :String) [], ParseException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

      LucD

      Hi Todd, I have the impression your copy of the script went wrong somewhere. Hover your mouse of the script window and you should see in the top-right corner of the window 4 icons. Use the 2nd icon from the left, it will copy the script to your clipboard.
      And yes, the script should also work against a cluster of ESXi hosts.

    Roey1206

    Hi lucD,

    The script failed to run at $esxImpl | get-scsiLun | where {$_.Luntype -eq “Disk”} ….

    the error message:
    Get-ScsiLun : Value cannot be null.
    Parameter name: array.

    I tried to run this command with the script… just “get-vmhost | get-scsilun”
    and it failed again with the same error message…

    any idea way?

    Thanks!
    Roey

      admin

      @Roey1206 What do you see when you just do ‘Get-VMHost’ ?
      And what does ‘Get-Cluster $clusName | Get-VMHost’ return ?

    James

    Can you run this against all the clusters in vCenter or do you have to specify a specific cluster?

      LucD

      Hi James, the script, as it is, only runs against a specific cluster specified in the first parameter.
      But it’s quite easy to run against all your clusters. Something like this for example


      Get-Cluster | %{.\Cluster-Lun-List.ps1 $_.Name}

      This will produce a separate CSV file for each cluster.

    Pcli

    Can we use Export-Xls rather than usage of | Export-Csv $csvName -NoTypeInformation -UseCulture

      LucD

      Sure you can.
      Make sure the function Export-Xls is available, define a new param (for example $xlsName instead of $csvName) and then make the last line something like this:
      | Export-Xls -Path $xlsName -WorksheetName "LUN report" -AppendWorksheet:$false

      You can have a worksheet for each of your clusters in one spreadsheet. Great idea.

    Ossie

    @Ossie
    Hi Luc
    Thanks for that. Looks like wait and see for the moment.
    Cheers
    Ossie

    Ossie

    @Ossie
    BTW – PowerCLI is VMware vSphere PowerCLI 4.0 U1 build 208462
    ESX and ESXi is Build 236512

      LucD

      Ossie, I just tested the Get-ScsiLun cmdlet on a non-clustered ESXi build 244038. And it returned the data correctly.
      There is a thread on the PowerCLI Community that mentions the same problem, but there has been no solution yet. 🙁

    Ossie

    Hi Luc

    When I execute Get-VMHost | Get-ScsiLun on ESXi I get an error,

    Get-ScsiLun : Object reference not set to an instance of an object.
    At line:1 char:45
    + Get-VMHost xxxxxxxxxxx | Get-ScsiLun <<<<
    + CategoryInfo : NotSpecified: (:) [Get-ScsiLun], NullReferenceEx
    ception
    + FullyQualifiedErrorId : System.NullReferenceException,VMware.VimAutomati
    on.VimAutomation.Commands.Host.GetScsiLun

    but if I do the same on an ESX host, it lists out all the LUNs.

    Cheers
    Ossie

    Ossie

    Hi Luc

    Could it be that Cluster is of ESXi hosts? Just tried on another cluster of 4 ESX hosts and it worked OK.

    Cheers
    Ossie

      LucD

      Ossie,
      Line 22 is the start of a loop over all ESX servers that are in the cluster.
      Line 23 stores the loop variable ($_) in another variable, called $esxImpl.

      Unfortunately I don’t have a cluster of ESXi hosts handy for testing right now.
      Can you check if

      Get-VMHost "one-of-the-ESXi-hosts" | Get-ScsiLun

      returns anything ?

    Ossie

    Hi Luc

    Thanks for the reply. I did think that might be the issue so as you suggested had tried just the Get-Cluster “cluster name with spaces” | Get-VMHost and it returns the single host in this cluster, with power status and other stats.
    Obviously others have the script working OK so I’m not sure what could be wrong here. BTW -What is the purpose of lines 22 and 23?
    Thanks again
    Ossie

    Ossie

    Hi LucD
    Trying to run your script and getting the below errors. Not being familiar with Powershell scripting I was wondering if you could point out what I may be doing incorrectly.
    Thanks

    Get-ScsiLun : Object reference not set to an instance of an object.
    At D:\Scripts\LUN-report.ps1:26 char:24
    + $esxImpl | Get-ScsiLun <<<< | where {$_.LunType -eq "Disk"} | %{
    + CategoryInfo : NotSpecified: (:) [Get-ScsiLun], NullReferenceEx
    ception
    + FullyQualifiedErrorId : System.NullReferenceException,VMware.VimAutomati
    on.VimAutomation.Commands.Host.GetScsiLun

    Cannot index into a null array.
    At D:\Scripts\LUN-report.ps1:40 char:36
    + $scsiTab[$key] = $scsiTab[$key][ <<<< 0], $dsName, $scsiTab[$key]

      LucD

      Hi Ossie,
      It looks as if there is no ESX server found for the clustername you passed to the script. Could you check if this returns one or more ESX servers ?

      Get-Cluster "clustername" | Get-VMHost

      Where “clustername” is the first parameter you passed in the script call. That would be MyCluster17 in the Usage section sample calls.
      Luc.

    Fred

    Why are you putting *screenshots* of a *console session* ? Wouldn’t copying the text be easier (go through a graphics program, crop the image, save then import the image in your blogging software VS copying two lines from the console)? Not to mention consume less bandwidth?

    Other than those details, looks neat.

      LucD

      Thanks for the advice Fred.
      I’ll try to remember it for future posts.

    Vuong Pham

    works great.. when the cluster names don’t have spaces in the names! 😉

    (okay I didn’t get it to work 100% but the yadr works perfect – just no cluster names. I ran it against the entire vcenter. Sorted the CSV file for RDM=True and viewed the path name to infer the LUN connection/Host / cluster relationship.

    Very handy! Thanks! lots to (more) to learn!

      LucD

      Did you try placing the cluster name between quotes ?
      Something like this

      .\Cluster-LUN-list.ps1 "My Cluster"

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.