Since its been about 3 months, I figured its about time for another post. A few weeks ago, a colleague of mine and I were discussing ways to identify which network cards were which when we build new Hyper-V cluster nodes. It can get a little nuts when you have 2 iSCSI networks, 1 Corp connection, and one connection that is tagged for VM’s on different VLAN’s, and a Heartbeat network.
We found that there is no real way to predict which NIC will be named “Local Area Connection”, “Local Area Connection 2”, Local Area Connection N …” and so on. However, poking around we did find that there is one thing in common across all of our servers. Assuming the NICS were all plugged into the switch in order, we could identify them by their PCI bus, device, and function ID as shown in the screenshot below.
Well that’s all good but how can we leverage that information and automate our network configuration for new cluster nodes. First, we need to come up with a standard. We know the PCI Bus information for each NIC in the server. Once we made that map, we can specify which NIC gets which IP Address. Once you manually create that map, you still need a way to identify which NIC has what Bus information. Enter PowerShell.
This gets a little nuts because we have to piece this together from a couple different sources. The first bit of information that we need for each NIC is something called the PnPDeviceID. You can pull this wit WMI using the win32_networkAdapter class.
So what does this buy us. It turns out this is part of the path in the registry that stores the PCI bus information. Lets assume you store the PnPDeviced id in $deviceID. You can get the PCI Bus information with the following:
Those last 3 numbers that are circled in red are the BusID, DeviceID, and FunctionID. Note that this is for 2008 and 2008 R2. All I really need is those last 3 numbers so some regex trickery along with multi-variable assignment comes in pretty handy here.
So once we have that, we can put this all together in a couple functions
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043
| Function Get-NicBusFunctionID { $adapters = get-wmiobject win32_networkadapter -filter "netenabled=true" foreach ($adapter in $adapters) { $deviceId = $adapter.PnPDeviceID $locationInfo = (get-itemproperty -path "HKLM:\SYSTEM\CurrentControlSet\Enum\$deviceID" ` -name locationinformation).locationINformation $businfo = Resolve-PCIBusInfo -locationInfo $locationinfo new-object psobject -property @{ "Name" = $adapter.NetConnectionID; "MacAddress" = $adapter.MacAddress "Index" = $adapter.Index; "PCIBusID" = $businfo.BusID; "PCIDeviceID" = $businfo.DeviceID; "PCIFunctionID" = $businfo.FunctionID } } } Function Resolve-PCIBusInfo { param ( [parameter(ValueFromPipeline=$true,Mandatory=$true)] [string] $locationInfo ) PROCESS { [void]($locationInfo -match "\d,\d,\d") $busId,$deviceID,$functionID = $matches[0] -split "," new-object psobject -property @{ "BusID" = $busID; "DeviceID" = "$deviceID" "FunctionID" = "$functionID" } } }
|
And a screenshot of how to use it