This comes up all the time in conversations I have.
Q: How can I tell which monitored servers are a VM or a Physical Machine, including VMWare virtual machines?
A: We need to disable a discovery, and add a new customized one in a management pack to accomplish this:
There is a property of the Windows Computer class, called “Virtual Machine”. However, out of the box, we only discover this value and populate it IF the system is running on Hyper-V. You can see my screenshot below easily which are definitely VM’s (true) and which are not populated, and likely physical:
This is populated by a discovery, in the Microsoft.SystemCenter.Internal.mp, named “Discover if Windows Computer is a Virtual Machine” with the ID of Microsoft.SystemCenter.DiscoverIsVirtualMachineTrue. Our built in MP simply has a discovery, that populates this value to true, IF the following WMI query returns valid results:
SELECT Name FROM Win32_BaseBoard WHERE Manufacturer = "Microsoft Corporation"
This is great if you are running Hyper-V, but has two shortcomings:
1. It does not populate the value if the monitored OS is running on some other HyperVisor, such as VMware.
2. It does not discover a “false” value, which is needed, since any machine that never runs the query, or has busted WMI, will show up as “NULL”, and this isn't accurate, it makes them all look like physical.
Ages ago – Pete Zerger posted a nice fix for this, in the form of a very popular community MP:
This MP does three things:
1. Contains a discovery that sets the value to TRUE if we detect the VM runs on VMware via WMI query: SELECT * FROM Win32_ComputerSystem WHERE Manufacturer = "VMware, Inc."
2. Contains another discovery that sets the value to FALSE if SELECT * FROM Win32_BaseBoard WHERE Manufacturer <> "Microsoft Corporation" OR Manufacturer <> "VMware, Inc."
3. Sets an override on the built in discovery to disabled.
The above solution is simple, effective, but not perfect. There are many comments there about things to change to work better. The second discovery – which has an OR statement causes EVERYTHING to get set to false, in my environment. This should be set to an AND statement.
Additionally, the “true” value and “false” values come from different places in WMI, which probably isn't the best way to ensure we don’t get any flip/flop.
Lastly, the MP doesn’t work well out of the box for Hybrid environments either, where you have VM’s from Hyper-V and VMware, because the “true” is only being set for VMware systems.
A better solution would be something like this:
1. Discovery that sets the value to “true” if we detect the Manufacturer is “Microsoft Corporation” OR “VMware, Inc.”
SELECT * FROM Win32_ComputerSystem WHERE Manufacturer = "VMware, Inc." OR Manufacturer = "Microsoft Corporation"
2. Discovery that sets the value to “false” if we detect the Manufacturer is NOT “Microsoft Corporation” AND ALSO NOT “VMware, Inc.”
SELECT * FROM Win32_ComputerSystem WHERE Manufacturer <> "VMware, Inc." AND Manufacturer <> "Microsoft Corporation"
3. Override to disable the built-in discovery for Virtual Machine attribute.
Here is an example of the tweaks:
<Discoveries><Discovery ID="Virtual.Machine.Discovery.Custom.IsVirtualMachineVMware" Enabled="true" Target="Windows!Microsoft.Windows.Computer" ConfirmDelivery="true" Remotable="true" Priority="Normal"><Category>Custom</Category><DiscoveryTypes><DiscoveryClass TypeID="Windows!Microsoft.Windows.Computer"><Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="IsVirtualMachine"/></DiscoveryClass></DiscoveryTypes><DataSource ID="Discover.IsVirtualMachine.VMware" TypeID="Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper"><NameSpace>\\$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$\ROOT\CIMV2</NameSpace><Query><![CDATA[SELECT * FROM Win32_ComputerSystem WHERE Manufacturer ="VMware, Inc." OR Manufacturer ="Microsoft Corporation"]]></Query><Frequency>86400</Frequency><ClassId>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</ClassId><InstanceSettings><Settings><Setting><Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name><Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value></Setting><Setting><Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/IsVirtualMachine$</Name><Value>true</Value></Setting></Settings></InstanceSettings></DataSource></Discovery><Discovery ID="Virtual.Machine.Discovery.Custom.DiscoverIsVirtualMachineFalse" Enabled="true" Target="Windows!Microsoft.Windows.Computer" ConfirmDelivery="true" Remotable="true" Priority="Normal"><Category>Custom</Category><DiscoveryTypes><DiscoveryClass TypeID="Windows!Microsoft.Windows.Computer"><Property TypeID="Windows!Microsoft.Windows.Computer" PropertyID="IsVirtualMachine"/></DiscoveryClass></DiscoveryTypes><DataSource ID="Virtual.Machine.DiscoverIsVirtulMachineFalse" TypeID="Windows!Microsoft.Windows.WmiProviderWithClassSnapshotDataMapper"><NameSpace>\\$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$\ROOT\CIMV2</NameSpace><Query><![CDATA[SELECT * FROM Win32_ComputerSystem WHERE Manufacturer <>"VMware, Inc." AND Manufacturer <>"Microsoft Corporation"]]></Query><Frequency>86400</Frequency><ClassId>$MPElement[Name="Windows!Microsoft.Windows.Computer"]$</ClassId><InstanceSettings><Settings><Setting><Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name><Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value></Setting><Setting><Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/IsVirtualMachine$</Name><Value>false</Value></Setting></Settings></InstanceSettings></DataSource></Discovery>
I am attaching the modified MP to this blog post as well. If you have different WMI values in your own environment, you can easily tweak these two discoveries to make it work well for you. I’d recommend you seal this MP with your own key, because you will likely use this value in computer groups in other management packs.