David2021
Contributor
Contributor

Create a report of Datastore information

Hello,

 

Regarding the intersting script report of LucD from this link  lun-report-datastores-rdms-and-node-visibility 

 

I would like complete this script and the report with additionnal points Uuid, lun Number, Datastore Name, Snapshot Volume and modify Capacity in GB instead of MB


ClusterName | CanonicalName | Uuid | Lun Number | Datastore Name | UsedBy | Snapshot Volume | Capacity GB | ESXi Name | ESXi Name | ....

Cluster1         | naa.xxxxxxxxx   | xxxx | xxx                | xxxxxxxxxxx        | xxxxxx   | Name of volume  | xxx GB          | OK              |   OK

 

If someone can help me on these points.

regards,
David

0 Kudos
14 Replies
LucD
Leadership
Leadership

In the comments (dated DECEMBER 21, 2019 at 07:01) you will find a version that shows the LUN number instead of OK.

Changing MB to GB is a matter of changing line 31 to 

			$scsiTab[$key] = $_.CanonicalName,"",$_.CapacityGB

The Datastore name, if applicable, is mentioned in the column "UsedBy"


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

0 Kudos
David2021
Contributor
Contributor

Hello LucD,

I have tested your script but He didn't works with errors concerning this part:

$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
}

The type of error that I have had repeatedly without stopping I need to type Ctrl + C to stop. And, nothing is genarated.

The property 'esx-test' cannot be found on this object. Verify that the property exists and can be set.
At D:Scripts\Info-Datastore.ps1:94 char:1
+ $lun.$esxName = $_.Value[3]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

The property 'CanonicalName' cannot be found on this object. Verify that the property exists and can be set.
At D:Scripts\Info-Datastore.ps1:95 char:25
+ if(!$lun.CanonicalName){$lun.CanonicalName = $_.Value[0]}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

The property 'UsedBy' cannot be found on this object. Verify that the property exists and can be set.
At D:Scripts\Info-Datastore.ps1:96 char:18
+ if(!$lun.UsedBy){$lun.UsedBy = $_.Value[1]}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

The property 'SizeGB' cannot be found on this object. Verify that the property exists and can be set.
At D:Scripts\Info-Datastore.ps1:97 char:18
+ if(!$lun.SizeGB){$lun.SizeGB = [math]::Round($_.Value[2],0)}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

The property 'DSC' cannot be found on this object. Verify that the property exists and can be set.
At D:Scripts\Info-Datastore.ps1:98 char:1
+ $lun.DSC = $_.Value[4]
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

New-Object : Cannot find type [LunInfo63605]: verify that the assembly containing this type is loaded.
At D:Scripts\Info-Datastore.ps1:90 char:8
+ $lun = New-Object ("LunInfo" + $rndNum)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

The property 'ClusterName' cannot be found on this object. Verify that the property exists and can be set.
At D:Scripts\Info-Datastore.ps1:91 char:1
+ $lun.ClusterName = $ClusterName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

0 Kudos
LucD
Leadership
Leadership

Looks like the $LunInfoDef definition is not correct.
That could be a wrong quote or a misalignment in the source.
I would need to see the code you are using.


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

0 Kudos
David2021
Contributor
Contributor

Hello LucD,

This the code that I use:

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
} | Export-Csv $csvName -NoTypeInformation -UseCulture
Invoke-Item $csvName

0 Kudos
LucD
Leadership
Leadership

As I suspected, the back-ticks were lost somewhere.
Attached is a working version (rename .txt to .ps1 before)


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

0 Kudos
David2021
Contributor
Contributor

I have another issue with this line of script concerning to add language:

Add-Type -Language CsharpVersion3 -TypeDefinition $LunInfoDef

 

 

Issue

Add-Type : xxxxxxxxxxxxxxxxxxxxxx : Invalid token '-' in class, struct, or interface member declaration
c:\xxxxxxxxxxxxxxx : public string esx-test1;
c:\xxxxxxxxxxxxxxxxxxx : >>> public string esx-test2;
c:\xxxxxxxxxxxxxxxxxxxxxxxx : public string esx-test3;
At T:\xxxxxxxxxxxxx\Info-Lun.ps1:24 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:\xxxxxxxxxxxxxxxxxxxxxx : ; expected
c:\xxxxxxxxxxxxxxxxxxxxxx : public string esx-test2;
c:\xxxxxxxxxxxxxxxxxxxxxx : >>> public string esx-test3";
c:\xxxxxxxxxxxxxxxxxxxxxx : }
At T:\xxxxxxxxxxxxxxxxxxxxxx\Info-Lun.ps1:24 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

0 Kudos
LucD
Leadership
Leadership

That is because a dash (-) is not allowed in C#.
Since the script uses the hostname as a column name there is not a lot I can do I'm afraid.


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

0 Kudos
David2021
Contributor
Contributor

ok. I understand.

Another language can be use instead of CsharpVersion3 which accept symbol as dash (-) and/or underscore (_) ?

0 Kudos
LucD
Leadership
Leadership

Unfortunately, the Add-Type cmdlet parameter Language only accepts CSharp.


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

0 Kudos
David2021
Contributor
Contributor

Ok LucD

Other way.

If I take this function from your script Get-FreeScsiLun.ps1 :

function Get-FreeScsiLun {
param (
[parameter(ValueFromPipeline = $true,Position=1)]
[ValidateNotNullOrEmpty()]
[VMware.VimAutomation.Client20.VMHostImpl]
$VMHost
)

process{
$storMgr = Get-View $VMHost.ExtensionData.ConfigManager.DatastoreSystem

$storMgr.QueryAvailableDisksForVmfs($null) | %{
New-Object PSObject -Property ([ordered]@{
VMHost = $VMHost.Name
CanonicalName = $_.CanonicalName
Uuid = $_.Uuid
CapacityGB = [Math]::Round($_.Capacity.Block * $_.Capacity.BlockSize / 1GB,2)
})
}
}
}

I would like take for Datastores CanonicalName and not VMHost as reference and find for each of them additionnal in this function : Lun Number/ID, Snapshot volume name (for example when you have PPRC) and list missing VMHost hostname not attach.

0 Kudos
LucD
Leadership
Leadership

That is a bit of a contradiction, the QueryAvailableDisksForVmfs method only returns free LUNs.
In other words not used for anything.


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

0 Kudos
David2021
Contributor
Contributor

Yes LucD. You complety right.

So I have included with success to get LUNID with this :

 

function Get-FreeScsiLun {

param (

[parameter(ValueFromPipeline = $true,Position=1)]

[ValidateNotNullOrEmpty()]

[VMware.VimAutomation.Client20.VMHostImpl]

$VMHost

)

process{

$storMgr = Get-View $VMHost.ExtensionData.ConfigManager.DatastoreSystem

$storMgr.QueryAvailableDisksForVmfs($null) | %{

$result = $_

$lun = $VMHost.ExtensionData.Config.StorageDevice.ScsiLun | Where{$_.CanonicalName -eq $result.CanonicalName}

$lunId = $VMHost.ExtensionData.Config.StorageDevice.ScsiTopology.Adapter | %{

$_.Target | %{$_.Lun | where {$_.ScsiLun -match $lun.key}}

}

New-Object PSObject -Property ([ordered]@{

VMHost = $VMHost.Name

CanonicalName = $_.CanonicalName

Uuid = $_.Uuid

LunID = if($lunId){$lunId[0].Lun}else{'na'}

CapacityGB = [Math]::Round($_.Capacity.Block * $_.Capacity.BlockSize / 1GB,2)

}) | Sort-Object -Property CanonicalName -Descending

}

}

}

 

Do you know how to get the snapshot volume name when a Datastore is use for PPRC or other Datastore replication for example in this function?

0 Kudos
LucD
Leadership
Leadership

Sorry, I don't know anything about PPRC


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

0 Kudos
David2021
Contributor
Contributor

OK Nevermind.

Thanks a lot LucD for your help.

0 Kudos