Get ESXi Host CDP Info With PowerCLI
Introduction
I recently had to provide our networking team with a list of ESXi hosts and which switchports each of their physical NICs were connected to. Like many other environments, we are primarily a Cisco house and therefore I was able to get this data by querying the Cisco Discovery Protocol (CDP) information via PowerCLI. Here is how I went about it.
The Process
I will initially show you how to pull this information for a specific host. However, later in the post I will show you a helpful script that I put together to pull this information for multiple hosts based on host or cluster name.
The first thing to do is connect to your vCenter server.
Connect-VIServer vcenter.example.com
Next, get a specific host object and store it in the $VMHost
variable.
$VMHost = Get-VMHost -Name esxi01.example.com
The CDP information is actually found within the NetworkSystem
managed object of the HostConfigManager
object. This can be accessed using the Get-View
CmdLet as follows.
$NetSystem = Get-View $VMHost.ExtensionData.ConfigManager.NetworkSystem
If you pipe the $NetSystem
object to the Get-Member
CmdLet you should see something similar to this.
$NetSystem | Get-Member
TypeName: VMware.Vim.HostNetworkSystem
Name MemberType Definition
---- ---------- ----------
AddPortGroup Method void AddPortGroup(VMware.Vim.HostPortGroupSpec portgrp)
AddServiceConsoleVirtualNic Method string AddServiceConsoleVirtualNic(string portgroup, VMware.Vim.HostVirtualNicSpec nic)
AddVirtualNic Method string AddVirtualNic(string portgroup, VMware.Vim.HostVirtualNicSpec nic)
AddVirtualSwitch Method void AddVirtualSwitch(string vswitchName, VMware.Vim.HostVirtualSwitchSpec spec)
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
QueryNetworkHint Method VMware.Vim.PhysicalNicHintInfo[] QueryNetworkHint(string[] device)
RefreshNetworkSystem Method void RefreshNetworkSystem()
...
...
This displays all available methods and properties for this object. The method that we are going to use is QueryNetworkHint
. To find out the arguments that this method requires you can run the method on its own.
$NetSystem.QueryNetworkHint
OverloadDefinitions
-------------------
VMware.Vim.PhysicalNicHintInfo[] QueryNetworkHint(string[] device)
We can see that the QueryNetworkHint
method requires a single argument, which is an individual physical network device for the host. Helpfully, this information is readily available in our $VMHost
variable from earlier. Running the following will list all physical devices for the specific host.
$VMHost.ExtensionData.Config.Network.Pnic
With these two pieces of information we are able to loop through each physical network device and run the QueryNetworkHint
method.
foreach ($Pnic in $VMHost.ExtensionData.Config.Network.Pnic) {
$NetSystem.QueryNetworkHint($Pnic.Device)
}
...
Device : vmnic5
Subnet : {3506, 3505}
Network :
ConnectedSwitchPort : VMware.Vim.PhysicalNicCdpInfo
LldpInfo :
Device : vmnic6
Subnet :
Network :
ConnectedSwitchPort :
LldpInfo :
Device : vmnic7
Subnet : {3506, 3505}
Network :
ConnectedSwitchPort : VMware.Vim.PhysicalNicCdpInfo
LldpInfo :
...
Looking at that output we can see that the information we are interested in is in the ConnectedSwitchPort
property. I can expand the foreach
loop as follows to get this information.
foreach ($Pnic in $VMHost.ExtensionData.Config.Network.Pnic) {
$PnicInfo = $NetSystem.QueryNetworkHint($Pnic.Device)
$PnicInfo.ConnectedSwitchPort
}
CdpVersion : 2
Timeout : 60
Ttl : 137
Samples : 21334
DevId : N5K_1
Address : 10.222.0.236
PortId : Ethernet108/1/15
DeviceCapability : VMware.Vim.PhysicalNicCdpDeviceCapability
SoftwareVersion : Cisco Nexus Operating System (NX-OS) Software, Version 7.0(7)N1(1)
HardwarePlatform : N5K-C5596UP
IpPrefix : 0.0.0.0
IpPrefixLen : 0
Vlan : 1
FullDuplex : True
Mtu : 1500
SystemName : N5K_1
SystemOID : 1.3.6.1.4.1.9.12.3.1.3.1038
MgmtAddr : 10.123.96.141
Location :
CdpVersion : 2
Timeout : 60
Ttl : 148
Samples : 21334
DevId : N5K_2
Address : 10.222.0.235
PortId : Ethernet108/1/15
DeviceCapability : VMware.Vim.PhysicalNicCdpDeviceCapability
SoftwareVersion : Cisco Nexus Operating System (NX-OS) Software, Version 7.0(7)N1(1)
HardwarePlatform : N5K-C5596UP
IpPrefix : 0.0.0.0
IpPrefixLen : 0
Vlan : 1
FullDuplex : True
Mtu : 1500
SystemName : N5K_2
SystemOID : 1.3.6.1.4.1.9.12.3.1.3.1038
MgmtAddr : 10.123.96.142
Location :
There is a lot of information available in this property, most of which I am not interested in. Also, it is not very helpful that I can’t tell from this output which physical device (e.g. vmnic0) that each of these blocks of information relate to. To tidy this up we can create a new PSCustomObject
in the foreach
loop and return only the information we want to see.
foreach ($Pnic in $VMHost.ExtensionData.Config.Network.Pnic) {
$PnicInfo = $NetSystem.QueryNetworkHint($Pnic.Device)
[PSCustomObject] @{
'Device' = $Pnic.Device
'DevId' = $PnicInfo.ConnectedSwitchPort.DevId
'PortId' = $PnicInfo.ConnectedSwitchPort.PortId
}
}
Device DevId PortId
------ ----- ------
vmnic0
vmnic1
vmnic2
vmnic3
vmnic4
vmnic5 N5K_1 Ethernet108/1/14
vmnic6
vmnic7 N5K_2 Ethernet108/1/14
A Helper Script
Now that we understand how we can get this information via PowerCLI, I want to show you a helper script/function that I have put together. This script enables us to target specific hosts by hostname or cluster name and also allows us to filter which physical NICs we are interested in. The script is available on my GitHub.
Once you have the script downloaded you will need to connect to your vCenter server before running it.
Connect-VIServer -Server vcenter.example.com
Here are a few examples of how you can use this script, note that the script excludes any physical NICs which do not have CDP information available. First, lets get a single host’s CDP information.
.\Get-VMHostCDPInfo.ps1 -VMHost 'esxi01.example.com' | Format-Table
I am using Format-Table
to present the large dataset in a more friendy way. Now lets get CDP information for all hosts in the cluster Cluster01
.
.\Get-VMHostCDPInfo.ps1 -Cluster 'Cluster01' | Format-Table -GroupBy VMHost
VMHost: esxi01.example.com
VMHost Pnic CdpVersion Timeout Ttl Samples DevId Address PortId DeviceCapability
------ ---- ---------- ------- --- ------- ----- ------- ------ ----------------
esxi01.example.com vmnic0 2 60 125 351248 N5K_5 10.222.0.231 Ethernet109/1/30 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi01.example.com vmnic1 2 60 124 351248 N5K_5 10.222.0.231 Ethernet109/1/29 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi01.example.com vmnic3 2 60 135 351249 N5K_5 10.222.0.231 Ethernet109/1/27 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi01.example.com vmnic4 2 60 163 351249 N5K_5 10.222.0.230 Ethernet109/1/31 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi01.example.com vmnic5 2 60 160 351249 N5K_5 10.222.0.230 Ethernet109/1/30 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi01.example.com vmnic7 2 60 160 351250 N5K_5 10.222.0.230 Ethernet109/1/29 VMware.Vim.PhysicalNicCdpDeviceCapability
VMHost: esxi02.example.com
VMHost Pnic CdpVersion Timeout Ttl Samples DevId Address PortId DeviceCapability
------ ---- ---------- ------- --- ------- ----- ------- ------ ----------------
esxi02.example.com vmnic0 2 60 143 346948 N5K_5 10.222.0.231 Ethernet101/1/21 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi02.example.com vmnic1 2 60 143 346948 N5K_5 10.222.0.231 Ethernet101/1/20 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi02.example.com vmnic3 2 60 165 346948 N5K_5 10.222.0.231 Ethernet101/1/19 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi02.example.com vmnic4 2 60 131 346947 N5K_5 10.222.0.230 Ethernet101/1/21 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi02.example.com vmnic5 2 60 170 346948 N5K_5 10.222.0.230 Ethernet101/1/20 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi02.example.com vmnic7 2 60 156 346948 N5K_5 10.222.0.230 Ethernet101/1/19 VMware.Vim.PhysicalNicCdpDeviceCapability
In this example I also used the -GroupBy
parameter of Format-Table
to display the information grouped by each host. Now lets get CDP information for both esxi01.example.com
and esxi02.example.com
but filter the results to show just vmnic5
and vmnic7
.
.\Get-VMHostCDPInfo.ps1 -VMHost 'esxi01.example.com', 'esxi02.exmple.com' -Vmnic 'vmnic5', 'vmnic7' | Format-Table -GroupBy VMHost
VMHost: esxi01.example.com
VMHost Pnic CdpVersion Timeout Ttl Samples DevId Address PortId DeviceCapability
------ ---- ---------- ------- --- ------- ----- ------- ------ ----------------
esxi01.example.com vmnic5 2 60 155 436320 N5K_5 10.222.0.231 Ethernet105/1/20 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi01.example.com vmnic7 2 60 133 436320 N5K_5 10.222.0.231 Ethernet105/1/18 VMware.Vim.PhysicalNicCdpDeviceCapability
VMHost: esxi02.example.com
VMHost Pnic CdpVersion Timeout Ttl Samples DevId Address PortId DeviceCapability
------ ---- ---------- ------- --- ------- ----- ------- ------ ----------------
esxi02.example.com vmnic5 2 60 121 341221 N5K_5 10.222.0.235 Ethernet102/1/7 VMware.Vim.PhysicalNicCdpDeviceCapability
esxi02.example.com vmnic7 2 60 146 341222 N5K_5 10.222.0.235 Ethernet102/1/6 VMware.Vim.PhysicalNicCdpDeviceCapability
And obviously you can use Select-Object
to return only the columns that you require if you wish.
.\Get-VMHostCDPInfo.ps1 -VMHost 'esxi01.example.com' -Vmnic 'vmnic5', 'vmnic7' | Select-Object VMhost, Pnic, DevId, Address, PortId
VMHost : esxi01.example.com
Pnic : vmnic5
DevId : N5K_5
Address : 10.222.0.231
PortId : Ethernet105/1/20
VMHost : esxi01.example.com
Pnic : vmnic7
DevId : N5K_5
Address : 10.222.0.231
PortId : Ethernet105/1/18
Conclusion
I hope you have found this post and the helper script useful. It really did come in handy for me when gathering this information for our network team recently!