11 September 2011

Find VM by NIC MAC Address with PowerShell -- Fast Like!

There is the occasion on which it would be handy to find a VM based on a known MAC address. Say, for example, there is a duplicate IP address on the network, and the network team informs you of the offending MAC addresses. Unfortunately, there is not a simple/easy way to go about this.

There are some places on the web that discuss this topic, but none were satisfactory. Some were overly complex, storing objects and data without need. Others were written with the ease of writing being considered. While these will work, they do not suffice if the size of the environment is larger. Memory usage climbs in the PowerShell session, and the time-to-run grows far past what is necessary and desirable.

Yet another problem was the reliance of some scripts on VMware Tools to get the information. Granted, VMs would ideally have Tools current and running, but, we all know that in the real world, that just does not always happen.

So, we wrote a little nugglet that will get the VM(s) that have VirtualEthernetCard(s) with the given MAC address:
## Script function: find all VMs with one or more NIC with the given MAC address
## Author: vNugglets.com -- Aug 2011

## MAC addr of NIC(s) to find
$strMacToFind = "00:50:56:83:00:69"
## return the .NET View object(s) for the VM(s) with the NIC w/ the given MAC
Get-View -Viewtype VirtualMachine -Property Name, Config.Hardware.Device | ?{$_.Config.Hardware.Device | ?{($_ -is [VMware.Vim.VirtualEthernetCard]) -and ($_.MacAddress -eq $strMacToFind)}}

This is pretty straight forward to use: just set the variable for the MAC address to find, and then run the next line of code. This returns the .NET View object(s) for the VM(s) that have a NIC with the given MAC address. One could then do as they pleased with the objects.

To just report the info about the VM(s) with a NIC with the given MAC address, one could add a simple Select-Object statement. The following returns a list of matching VMs' names and their associated NICs' MAC addresses:
Get-View -Viewtype VirtualMachine -Property Name, Config.Hardware.Device | ?{$_.Config.Hardware.Device | `
?{($_ -is [VMware.Vim.VirtualEthernetCard]) -and ($_.MacAddress -eq $strMacToFind)}} | `
Select name, @{n="MAC(s)"; e={($_.Config.Hardware.Device | ?{($_ -is [VMware.Vim.VirtualEthernetCard])} | %{$_.MacAddress}) -join ","}}

The output would be something like:
Name     MAC(s)
----     ------
myVM     00:50:56:83:00:69,00:0c:29:00:08:01

PS C:\>

As for speed: this method of finding VMs with a given MAC address took around 25 seconds when run in a test environment of about 3200 VMs. Fast. Enjoy.

Update (30 Oct 2011 -- response to comment):
To use a similar technique to find a VMHost with a given MAC address, you can look at the Config.Network.Pnic property of a HostSystem .NET View object.  To find a VMHost with a given MAC, and quick like, use:
## to find a VMHost with given MAC address:
$strMacOfNICOnVMHostToFind = "00:0e:0c:00:00:01"

Get-View -ViewType HostSystem -Property Name, Config.Network.Pnic | ?{$_.Config.Network.Pnic | ?{$_.Mac -eq $strMacOfNICOnVMHostToFind}} | select Name, @{n="MAC(s)"; e={($_.Config.Network.Pnic | %{$_.Mac}) -join ","}}

The output is similar to the output above, but the Name will be of the given VMHost, and MAC(s) will be that host's MAC addresses. Enjoy, "Anonymous" commenter.