**Update May 07, 2012 – Use the new script here: Updated: Finding WWNs for HBAs in ESXi hosts, now with Get-VMHostHba
When building a new cluster, your storage team (or you) may need to add several hosts into the shared storage zone. It’s a pain to go to each host, configuration, storage adapters, then copy out the WWN.
With this script, you can supply a vCenter server and Cluster/Folder/Datacenter (any logical container) and it will list all the WWNs for Fibre Channel devices. But what if you don’t have vCenter stood up yet? No problem, you can also supply a list of ESX/ESXi hosts to scan.
Shawn & I built this because we have 20 hosts we need the WWNs from to provide to our storage team, and vCenter isn’t alive yet.
Our script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
#lets get our cli args param([string]$vc = "vc", [string]$container = "container", [string[]]$esx_hosts = "esx_hosts") #add the snapin, just in case Add-PSSnapin VMware.VimAutomation.Core #usage info function usage() { Write-host -foregroundcolor green `n`t"This script is used to retreive WWNs for all hosts provided." Write-host -foregroundcolor green `n`t"You can either specify -esx_hosts as an array:" write-host -foregroundcolor green `n`t`t"Get-WWN -esx_hosts (`"host1`",`"host2`",`"host3`")" Write-host -foregroundcolor green `n`t"or specify -vc and -container, where container is a host name, cluster, folder, datacenter, etc:" write-host -foregroundcolor green `n`t`t"Get-WWN -vc vcenterserver -container cluster1" `n write-host -foregroundcolor green `t"You can use either -esx_hosts or -vc and -container, not a combination of them." `n } #get the WWNs function GetWWN() { if ($esx -eq 1) #do this only if connecting directly to ESX hosts { $esx_host_creds = $host.ui.PromptForCredential("ESX/ESXi Credentials Required", "Please enter credentials to log into the ESX/ESXi host.", "", "") } if ($vcenter -eq 1) #do this if connecting to vCenter to populate esx_hosts { $vc_creds = $host.ui.PromptForCredential("vCenter Credentials Required", "Please enter credentials to log into vCenter.", "", "") connect-viserver $vc -credential $vc_creds > $NULL 2>&1 $esx_hosts = get-vmhost -location $container | sort name } foreach ($esx_host in $esx_hosts) { if ($esx -eq 1) #do this only if connecting directly to ESX hosts { connect-viserver $esx_host -credential $esx_host_creds > $NULL 2>&1 } Write-Host `n Write-Host -foregroundcolor green "Server: " $esx_host $hbas = Get-View (Get-View (Get-VMHost -Name $esx_host).ID).ConfigManager.StorageSystem foreach ($hba in $hbas.StorageDeviceInfo.HostBusAdapter) { if ($hba.gettype().name -eq "HostFibreChannelHba") { $wwn = "{0:x}" -f $hba.PortWorldWideName Write-Host -foregroundcolor green `t $wwn } } if ($esx -eq 1) #disconnect from the current ESX host before going to the next one { disconnect-viserver -confirm:$false } } write-host `n if ($vcenter -eq 1) #disconnect from vcenter { disconnect-viserver -confirm:$false } } #check to make sure we have all the args we need if (($esx_hosts -eq "esx_hosts") -and (($vc -eq "vc") -or ($container -eq "container"))) #if esx_hosts, vc, or container is blank { usage break } elseif (($esx_hosts -ne "esx_hosts") -and (($vc -ne "vc") -or ($container -ne "container"))) #if esx_hosts and vc or container is used { usage break } elseif (($esx_hosts -ne "esx_hosts") -and (($vc -eq "vc") -or ($container -eq "container"))) #if only esx_hosts is used, set our esx variable to 1 { $esx = 1 GetWWN } elseif (($esx_hosts -eq "esx_hosts") -and (($vc -ne "vc") -and ($container -ne "container"))) #if vc and container are used, { $vcenter = 1 GetWWN } #garbage collection, just in case... $esx_host_creds = $null $vc_creds = $null $esx_hosts = $null $vc = $null $container = $null $hba = $null $hbas = $null $wwn = $null $esx = $null $vcenter = $null |
The usage is pretty simple, and the switches are self explanatory:
Get-WWN.ps1 -esx_hosts ("Host1","Host2","Host3")
Get-WWN.ps1 -vc drtapw0015001 -container drtcrl0011102
Main thing is you have to use one OR the other (ESX hosts OR vCenter info), you don’t need both, so why would you try to confuse this script with it.
Also, when it prompts for credentials, I chose to use the $host.ui.PromptForCredential vs Get-Credential because $host.ui.PromptForCredential allows me to specify a window title and caption to differentiate between the vCenter login and Host login.
$host.ui.PromptForCredential("window title", "text", "username", "password")
For the third arg, you could use something like “$env:userdomain\$env:username” and it’ll populate with your current domain\user info, but I left it blank, same with password.
I wanted to add, make sure you don’t fat-finger your password if your ESX hosts are AD integrated, or you’ll have instant death in the form of an account lock-out. BTDT, moving on…
I’m getting the following error when I run it with -vc and specify the Datacenter:
Server: SERVER.FQDN.COM
Get-View : Cannot validate argument on parameter ‘VIObject’. The argument is null or empty. Supply an argument that is not null or empty and the
n try the command again.
At D:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Get-WWN.ps1:44 char:29
+ $hbas = Get-View (Get-View <<<< (Get-VMHost -Name $esx_host).ID).ConfigManager.StorageSystem
+ CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView
You cannot call a method on a null-valued expression.
At D:\Program Files\VMware\Infrastructure\vSphere PowerCLI\Get-WWN.ps1:47 char:20
+ if ($hba.gettype <<<< ().name -eq "HostFibreChannelHba")
+ CategoryInfo : InvalidOperation: (gettype:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Interesting, can you paste the command line you used? I tested using -vc -container and it worked fine. I tried pointing to clusters, too, like this: get-wwn.ps1 -vc -container and that worked as well. The only time I got it to error out was when I -container was a hostname.
My vCenter name is vcprod, and one of my clusters is ar-core, so the cli is:
Get-WWN.ps1 -vc vcprod -container ar-core
**Apparently WordPress doesn’t like the gt & lt signs. Below is how I typed it:
I tested using -vc [vcenter] -container [vDC] and it worked fine. I tried pointing to clusters, too, like this: get-wwn.ps1 -vc [vcenter] -container [clustername] and that worked as well.
I actually just got the same error you got when I was connected to more than one vCenter in the PowerCLI:
Get-View : Cannot validate argument on parameter ‘VIObject’. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At test.ps1:16 char:26
+ $ds = Get-View (Get-View <<<< (Get-VMHost -Name $vmhost).ID).ConfigManager.StorageSystem + CategoryInfo : InvalidData: (:) [Get-View], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView You may want to make sure you're not connected to any vCenter before running the script.
it worked. how abt including the nodename in the output? the current output has just portname. i think having nodename+portname would be the good idea.
`rgds
I’ll take a look and see what’s needed. If it’s pretty simple, I’ll add it.
Thanks!
It was actually a piece of cake.
Take a look at line 49 & 50, it should have this:
$wwn = "{0:x}" -f $hba.PortWorldWideName
Write-Host -foregroundcolor green
t $wwn
Replace those 2 lines with these 4 lines:
$wwpn = "{0:x}" -f $hba.PortWorldWideName
t "World Wide Port Name:" $wwpn$wwnn = "{0:x}" -f $hba.NodeWorldWideName
Write-Host -foregroundcolor green
Write-Host -foregroundcolor green `t "World Wide Node Name:" $wwnn
Since it cycles through each HBA pulling those, output will look like this:
Server: esx
World Wide Port Name: 210000e08b9c86a3
World Wide Node Name: 200000e08b9c86a3
World Wide Port Name: 210000e08b9ca2a5
World Wide Node Name: 200000e08b9ca2a5
Great article!
Great script, question is there a way of getting both paths for each hba?
cool script !!! Thank you !!!
Cool script!
In PowerCLI 4.0 Update 1 the PowerCLI team introduced the Get-VMHostHba cmdlet that does almost the same!
Thanks! I’ll write an updated version of this script to reflect that. The original is quite old.
use “whoami” from the powershell environment instead using $env
And for the “:” use this if wanted:
Store the name of the WWN on a variable $item, for example and then:
(}) -join’:’
({for ($i=0;$i -lt $item.length;$i+=2){$item.substring($i,2)}}) -join’:’