I need help. I'm trying to make a "translator script" for our network engineers, so they can find most wanted LUN details for them.
Plan is simple: we know LUN Id (simple digits in the LUN column), and by knowing this, we must find NAA (canonical name), runtime name (ldev is kinda important), RDM (what virtual machine have this LUN) and datastore.
ATM im trying to use this script (thank you, LucD):
foreach ($clusterName in Get-Cluster) {
$report += Get-Cluster -Name $clusterName | Get-VMHost | %{
$esxcli = Get-EsxCli -VMHost $_
$esxcli.storage.core.device.list() |
Select @{N='ESX';E={$esxcli.VMHost.Name}},Device,
@{N='lunID'; E={
$d = $_
if(([Version]$esxcli.VMHost.Version).Major -lt 6){
$lun = Get-ScsiLun -VmHost $esxcli.VMhost | Where {$_.CanonicalName -eq $d.Device}
$runtime = $lun.RuntimeName
}
else{
$lun = $esxcli.VMHost.ExtensionData.Config.StorageDevice.ScsiLun | Where-Object{$_.CanonicalName -eq $d.Device}
$lunUuid = $lun.Uuid
$runtime = ($esxcli.VMHost.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | Where-Object{$_.Id -eq $lunUuid}).Path[0].Name
}
$runtime.Split('L')[1]
}}
}
}
$report
But it's rly slow, because it's trying to do with every host.. And if i'll try to search the datastores, it will take forever.. But anyway. I need help with this task. How can I find all I want, knowing just LUN Id? This task is hard for me.
P.S. Powercli version 6.5
Try like this
$dsTab = @{}
foreach($ds in (Get-Datastore | where{$_.ExtensionData.Summary.MultipleHostAccess})){
$ds.ExtensionData.Info.Vmfs.Extent | %{
if($_.DiskName){
$dsTab.Add($_.DiskName,$ds.Name)
}
}
}
foreach ($esx in Get-VMHost){
$adapterTab = @{}
$pathTab = @{}
$lunTab = @{}
$rdmTab = @{}
$esx.ExtensionData.Config.StorageDevice.HostBusAdapter | %{
$adapterTab.Add($_.Key,$_.Device)
}
$esx.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | %{
$pathTab.Add($_.Lun,$_.Path.Name)
}
$esx.ExtensionData.Config.StorageDevice.ScsiLun | %{
$lunTab.Add($_.Key,$_.CanonicalName)
}
foreach($rdm in (Get-VM -Location $esx | Get-HardDisk -DiskType RawPhysical,RawVirtual)){
if($rdm){
$rdmTab.Add($rdm.ScsiCanonicalName,@{
VM = $rdm.Parent.Name
HD = $rdm.Name
})
}
}
foreach($adapter in $esx.ExtensionData.Config.StorageDevice.ScsiTopology.Adapter){
foreach($target in $adapter.Target){
foreach($lun in $target.Lun){
$lun | Select @{N='ESX';E={$esx.Name}},
@{N='Adapter';E={$adapterTab[$adapter.Adapter]}},
@{N='Canonical';E={$lunTab[$lun.ScsiLun]}},
@{N='Path';E={$pathTab[$lun.ScsiLun]}},
Lun,
@{N='Datastore';E={$dsTab[$lunTab[$lun.ScsiLun]]}},
@{N='RDM';E={"$($rdmTab[$lunTab[$lun.ScsiLun]].VM) $($rdmTab[$lunTab[$lun.ScsiLun]].HD)"}}
}
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You can use a hash table to lookup datastorenames via the canonicalname.
Something like this
$report = @()
$dsTab = @{}
foreach($ds in (Get-Datastore | where{$_.ExtensionData.Summary.MultipleHostAccess})){
$ds.ExtensionData.Info.Vmfs.Extent | %{
if($_.DiskName){
$dsTab.Add($_.DiskName,$ds.Name)
}
}
}
foreach ($clusterName in Get-Cluster) {
$report += Get-Cluster -Name $clusterName | Get-VMHost | %{
$esxcli = Get-EsxCli -VMHost $_
$esxcli.storage.core.device.list() |
Select @{N='ESX';E={$esxcli.VMHost.Name}},Device,
@{N='lunID'; E={
$d = $_
if(([Version]$esxcli.VMHost.Version).Major -lt 6){
$lun = Get-ScsiLun -VmHost $esxcli.VMhost | Where {$_.CanonicalName -eq $d.Device}
$runtime = $lun.RuntimeName
}
else{
$lun = $esxcli.VMHost.ExtensionData.Config.StorageDevice.ScsiLun | Where-Object{$_.CanonicalName -eq $d.Device}
$lunUuid = $lun.Uuid
$runtime = ($esxcli.VMHost.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | Where-Object{$_.Id -eq $lunUuid}).Path[0].Name
}
$runtime.Split('L')[1]
}},
@{N='Datastore';E={$dsTab[$_.Device]}}
}
}
$report
But note that this will only cover datastores, not RDMs.
Perhaps you could have a look at my LUN Report – Datastore, RDM And Node Visibility post?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
For RDM I can use a oneliner to make another hash table.
get-datacenter | Get-VM | Get-HardDisk -DiskType "RawPhysical","RawVirtual"
is it fine or there's a better way?
And finally via CNAME I can find runtimename by get-scsilunpath..
Will try it
No, hash table is fine.
Not quite sure what you mean by the CNAME, that is a DNS concept for me, but I'm probably missing something there :smileygrin:
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Ok, I think I can make a huge table with all data I need and then just select.
But I want to know one more thing. Luc, is there a way to get LUN info, if you have only ID or RuntimeName like vmhba2:C0:T0:L58?
*CNAME - just short canonical name
That info is available and can be stored in a couple of hash tables.
Something like this for example.
Note that this needs to be expanded (the $pathTab hash table), when a LUN has multiple paths.
Now the script only takes the first available path
$esxName = 'MyEsx'
$esx = Get-VMHost -Name $esxName
$adapterTab = @{}
$esx.ExtensionData.Config.StorageDevice.HostBusAdapter | %{
$adapterTab.Add($_.Key,$_.Device)
}
$pathTab = @{}
$esx.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | %{
$pathTab.Add($_.Lun,$_.Path[0].Name)
}
$lunTab = @{}
$esx.ExtensionData.Config.StorageDevice.ScsiLun | %{
$lunTab.Add($_.Key,$_.CanonicalName)
}
foreach($adapter in $esx.ExtensionData.Config.StorageDevice.ScsiTopology.Adapter){
foreach($target in $adapter.Target){
foreach($lun in $target.Lun){
$lun | Select @{N='Adapter';E={$adapterTab[$adapter.Adapter]}},
@{N='Canonical';E={$lunTab[$lun.ScsiLun]}},
@{N='Path';E={$pathTab[$lun.ScsiLun]}},
Lun
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Got the plan. LOTS OF HASH TABLES
Big thanks for help.
*UPD. Need more help, please.
So with this script
$adapterTab = @{}
$pathTab = @{}
$lunTab = @{}
$dsTab = @{}
foreach($ds in (Get-Datastore | where{$_.ExtensionData.Summary.MultipleHostAccess})){
$ds.ExtensionData.Info.Vmfs.Extent | %{
if($_.DiskName){
$dsTab.Add($_.DiskName,$ds.Name)
}
}
}
foreach ($esx in Get-VMHost){
$esx.ExtensionData.Config.StorageDevice.HostBusAdapter | %{
$adapterTab.Add($_.Key,$_.Device)
}
$esx.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | %{
$pathTab.Add($_.Lun,$_.Path.Name)
}
$esx.ExtensionData.Config.StorageDevice.ScsiLun | %{
$lunTab.Add($_.Key,$_.CanonicalName)
}
foreach($adapter in $esx.ExtensionData.Config.StorageDevice.ScsiTopology.Adapter){
foreach($target in $adapter.Target){
foreach($lun in $target.Lun){
$lun | Select @{N='ESX';E={$esx.Name}},
@{N='Adapter';E={$adapterTab[$adapter.Adapter]}},
@{N='Canonical';E={$lunTab[$lun.ScsiLun]}},
@{N='Path';E={$pathTab[$lun.ScsiLun]}},
Lun,
@{N='Datastore';E={$dsTab[$lunTab[$lun.ScsiLun]]}}
}
}
}
}
I get information I need. It search every host, and write expanded paths. Am I going right way, or I'm breaking gravity?
And one more question. How can I add RDMs in hash table?
$RDMS = get-datacenter | Get-VM | Get-HardDisk -DiskType "RawPhysical","RawVirtual"
$RDMS | %{$rdmTable.add($_.parent, $_.scsicanonicalname)}
isnt work, because I need pairs... It makes me mad
Try like this
$dsTab = @{}
foreach($ds in (Get-Datastore | where{$_.ExtensionData.Summary.MultipleHostAccess})){
$ds.ExtensionData.Info.Vmfs.Extent | %{
if($_.DiskName){
$dsTab.Add($_.DiskName,$ds.Name)
}
}
}
foreach ($esx in Get-VMHost){
$adapterTab = @{}
$pathTab = @{}
$lunTab = @{}
$rdmTab = @{}
$esx.ExtensionData.Config.StorageDevice.HostBusAdapter | %{
$adapterTab.Add($_.Key,$_.Device)
}
$esx.ExtensionData.Config.StorageDevice.MultipathInfo.Lun | %{
$pathTab.Add($_.Lun,$_.Path.Name)
}
$esx.ExtensionData.Config.StorageDevice.ScsiLun | %{
$lunTab.Add($_.Key,$_.CanonicalName)
}
foreach($rdm in (Get-VM -Location $esx | Get-HardDisk -DiskType RawPhysical,RawVirtual)){
if($rdm){
$rdmTab.Add($rdm.ScsiCanonicalName,@{
VM = $rdm.Parent.Name
HD = $rdm.Name
})
}
}
foreach($adapter in $esx.ExtensionData.Config.StorageDevice.ScsiTopology.Adapter){
foreach($target in $adapter.Target){
foreach($lun in $target.Lun){
$lun | Select @{N='ESX';E={$esx.Name}},
@{N='Adapter';E={$adapterTab[$adapter.Adapter]}},
@{N='Canonical';E={$lunTab[$lun.ScsiLun]}},
@{N='Path';E={$pathTab[$lun.ScsiLun]}},
Lun,
@{N='Datastore';E={$dsTab[$lunTab[$lun.ScsiLun]]}},
@{N='RDM';E={"$($rdmTab[$lunTab[$lun.ScsiLun]].VM) $($rdmTab[$lunTab[$lun.ScsiLun]].HD)"}}
}
}
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
About
$RDMS = get-datacenter | Get-VM | Get-HardDisk -DiskType "RawPhysical","RawVirtual"
$RDMS | %{$rdmTable.add($_.parent, $_.scsicanonicalname)}
I just forgot, that the $_.key parameter must be equal. So
$RDMS | %{$rdmtab.add($_.scsicanonicalname, $_.parent)}
version is working.
More than 24h without sleeping is really bad. You can forgot all basics
Is it working now?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes. Thank you very much for your help