Determine Hypervisor when running an Ubuntu based appliance
Sometimes you're in need to know in which environment your program or maybe even your virtual Linux appliance is running. There are some methods to acquire that information.
The following was tested on Ubuntu Linux 16 and 18.
General information
General information can be obtained by the systemd-detect-virt
. It prints information about the container and / or hypervisor (VM) the system is running on.
From the manual page:
systemd-detect-virt detects execution in a virtualized environment. It identifies the virtualization technology and can distinguish full machine virtualization from container virtualization. systemd-detect-virt exits with a return value of 0 (success) if a virtualization technology is detected, and non-zero (error) otherwise. By default, any type of virtualization is detected, and the options --container and --vm can be used to limit what types of virtualization are detected. Table 1. Known virtualization technologies (both VM, i.e. full hardware virtualization, and container, i.e. shared kernel virtualization) +--------------------------------------------------------------------------------+ ¦Type ¦ ID ¦ Product ¦ +----------+----------------+----------------------------------------------------¦ ¦VM ¦ qemu ¦ QEMU software virtualization ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ kvm ¦ Linux KVM kernel virtual machine ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ zvm ¦ s390 z/VM ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ vmware ¦ VMware Workstation or Server, and related products ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ microsoft ¦ Hyper-V, also known as Viridian or Windows Server ¦ ¦ ¦ ¦ Virtualization ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ oracle ¦ Oracle VM VirtualBox (historically marketed by ¦ ¦ ¦ ¦ innotek and Sun Microsystems) ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ xen ¦ Xen hypervisor (only domU, not dom0) ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ bochs ¦ Bochs Emulator ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ uml ¦ User-mode Linux ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ parallels ¦ Parallels Desktop, Parallels Server ¦ +----------+----------------+----------------------------------------------------¦ ¦Container ¦ openvz ¦ OpenVZ/Virtuozzo ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ lxc ¦ Linux container implementation by LXC ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ lxc-libvirt ¦ Linux container implementation by libvirt ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ systemd-nspawn ¦ systemd's minimal container implementation, see ¦ ¦ ¦ ¦ systemd-nspawn(1) ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ docker ¦ Docker container manager ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ rkt ¦ rkt app container runtime ¦ ¦ +----------------+----------------------------------------------------¦ ¦ ¦ wsl ¦ Windows Subsystem for Linux[1] ¦ +--------------------------------------------------------------------------------+
Pretty neat, isn't it.
Using the -c
/ --container
parameter the program will return the container, using the -v
/ --vm
parameter it will return the hypervisor.
If no container / no hypervisor is detected, the program will print none
and return with an exit code 1
.
Another program we can use is lshw
(list hardware). But I'll discuss that for in the section of each hypervisor.
VMware
root@machine:~# systemd-detect-virt vmware
root@machine:~# lshw -xml
This will produce this output. The interesting part here is:
<list> <node> <product>VMware Virtual Platform</product> <vendor>VMware, Inc.</vendor> <version>None</version> </node> </list>
Also that information doesn't help much as it doesn't contain more information than the systemd-detect-virt
output. But at least it is an alternative.
Normally you have the open-vm-tools
package installed on a VMware guest. And those tools provide a lot more information. But be aware that - also the tools are installed - all information is maybe not available on all systems. E.g. while I got the example down below on an Ubuntu Linux 16 system running on a ESXi 6.5 farm, I wasn't able to obtain them on an Ubuntu Linux 18 system running on a single ESXi 5.1 machine (Failed to get stat: This value is not available on this host
).
The stat
parameter of the vmware-toolbox-cmd
returns information about the status of the virtual machine.
The raw
sub-parameter returns raw status information.
The xml
parameter returns the information in XML format. text
, json
and yaml
are also possible.
First let's get some information about the current session (which also includes the name and version of the VMware hypervisor):
root@machine:~# vmware-toolbox-cmd stat raw xml session
<metrics session="6897940133359773512"> <metric name="session" type="static" units="int">6897940133359773512</metric> <metric name="uptime" type="static" units="us">2571919492350</metric> <property name="version">VMware ESX 6.5.0 build-5969303</property> <property name="provider"/> <property name="uuid.bios">42 1a 00 9b 04 d0 bb 3f-17 c3 d3 38 6f 9d 94 1b</property> </metrics>
Now we can get also some extra information about the host, the resources, the hard disk interface and the network interface:
root@machine:~# vmware-toolbox-cmd stat raw xml host
<metrics session="6897940133359773512"> <metric name="host.cpu.processorMHz" type="instant" units="MHz">2199</metric> <metric name="host.cpu.coresPerPkg" type="static" units="count">10</metric> </metrics>
root@machine:~# vmware-toolbox-cmd stat raw xml resources
<metrics session="6897940133359773512"> <metric name="vm.cpu.reserved" type="static" units="MHz">0</metric> <metric name="vm.cpu.limit" type="static" units="MHz">-1</metric> <metric name="vm.cpu.used" type="accumulate" units="us">123470134602</metric> <metric name="vm.cpu.contention.cpu" type="accumulate" units="us">7855668547</metric> <metric name="vm.cpu.contention.mem" type="accumulate" units="us">0</metric> <metric name="vm.numa.local" type="instant" units="KB">2084864</metric> <metric name="vm.numa.remote" type="instant" units="KB">12288</metric> <metric name="guest.mem.reserved" type="static" units="KB">0</metric> <metric name="guest.mem.limit" type="static" units="KB">-1</metric> <metric name="guest.mem.mapped" type="instant" units="KB">2097152</metric> <metric name="guest.mem.consumed" type="instant" units="KB">2097152</metric> <metric name="guest.mem.swapped" type="instant" units="KB">0</metric> <metric name="guest.mem.ballooned" type="instant" units="KB">0</metric> <metric name="guest.mem.swapIn" type="accumulate" units="KB">0</metric> <metric name="guest.mem.swapOut" type="accumulate" units="KB">0</metric> <metric name="ovhd.mem.swapped" type="instant" units="KB">0</metric> <metric name="ovhd.mem.swapIn" type="accumulate" units="KB">0</metric> <metric name="ovhd.mem.swapOut" type="accumulate" units="KB">0</metric> </metrics>
root@machine:~# vmware-toolbox-cmd stat raw xml vscsi
<metrics session="6897940133359773512"> <category>session</category> <category>host</category> <category>resources</category> <category>vscsi scsi0:0</category> <category>vnet 00:50:56:9a:fb:de</category> </metrics>
root@machine:~# vmware-toolbox-cmd stat raw xml vscsi scsi0:0
<metrics session="6897940133359773512"> <metric name="num.reads" type="accumulate" units="int">368</metric> <metric name="num.writes" type="accumulate" units="int">124066</metric> <metric name="size.reads" type="accumulate" units="bytes">6164480</metric> <metric name="size.writes" type="accumulate" units="bytes">2731978752</metric> <metric name="latency.reads" type="accumulate" units="us">2965596</metric> <metric name="latency.writes" type="accumulate" units="us">39164420</metric> </metrics>
root@machine:~# vmware-toolbox-cmd stat raw xml vnet
<metrics session="6897940133359773512"> <category>session </category> <category>host </category> <category>resources </category> <category>vscsi scsi0:0</category> <category>vnet 00:50:56:9a:fb:de</category> </metrics>
root@machine:~# vmware-toolbox-cmd stat raw xml vnet vnet 00:50:56:9a:fb:de
<metrics session="6897940133359773512"> </metrics>
Hyper-V
root@machine:~# systemd-detect-virt microsoft
root@machine:~# lshw -xml
This will produce this output. The interesting part here is:
<list> <node> <product>Virtual Machine</product> <vendor>Microsoft Corporation</vendor> <version>7.0</version> </node> </list>
Okay, means the only really interesting part is Microsoft Corporation
. The version - as some may think - is not the version of the virtual machine. In this case it was version 8.0
.
Hyper-V is support is integrated into the Linux kernel starting from Ubuntu Linux 12. If you're machine is running on a Hyper-V hypervisor, you should find the following files in your system:
/var/lib/hyperv/.kvp_pool_0
/var/lib/hyperv/.kvp_pool_1
/var/lib/hyperv/.kvp_pool_2
/var/lib/hyperv/.kvp_pool_3
/var/lib/hyperv/.kvp_pool_4
Each of those files contain a binary form of some kind of registry. In my tests the files #0 to #2 and #4 were all 0 bytes in size. Meaning only file #3 had some content.
The file itself contains key-value pairs with a fixed field length (for the key and the value). All not used space is filled with zeros (means the byte-value 0
, not the number 0
). If you write yourself a little parser, you would get the following (example):
HostName hyper-v16.acme.local HostingSystemEditionId 42 HostingSystemNestedLevel 0 HostingSystemOsMajor 10 HostingSystemOsMinor 0 HostingSystemProcessorArchitecture 9 HostingSystemProcessorIdleStateMax 0 HostingSystemProcessorThrottleMax 100 HostingSystemProcessorThrottleMin 5 HostingSystemSpMajor 0 HostingSystemSpMinor 0 PhysicalHostName HYPER-V16 PhysicalHostNameFullyQualified hyper-v16.acme.local VirtualMachineDynamicMemoryBalancingEnabled 0 VirtualMachineId 8CAE363F-B2BA-46E0-B2B7-4CDF89E48235 VirtualMachineName MyMachine
In this example hyper-v16.acme.local
(respectively HYPER-V16
) is the name of the Hypervisor's host system. MyMachine
is the name of the virtual machine / guest system.
The HostingSystemEditionId
value of 42
(or 2A
in hex) stands for Hyper-V (PRODUCT_HYPERV
with value 0x0000002A
maps to "Microsoft Hyper-V Server").
The HostingSystemOsMajor
value of 10
and the HostingSystemOsMinor
value of 0
result in version 10.0
. This version is reported by the "Windows 10" and "Windows Server 2016".
This all means we deal with a "Hyper-V Server 2016" as host system.
See the GetProductInfo function and Windows Version Numbers links in the Sources section for a table on those numbers.
If we wouldn't be on Linux, but on a Windows guest system, we would be able to obtain this information from the following registry sub-tree: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest
Just as a side node: It seems that is is possible to pass values from the host to the guest via those registry files. For more information see the links in the Sources section.
Xen
root@machine:~# systemd-detect-virt xen
root@machine:~# lshw -xml
This will produce this output. The interesting part here is:
<list> <node> <vendor>Xen</vendor> <version>4.11.1-7.2</version> <node id="core"> <node id="firmware"> <vendor>Xen</vendor> <version>4.11.1-7.2</version> <date>04/12/2019</date> </node> </node> </node> </list>
The version
element contains the version of the Xen hypervisor itself, not the Xen product (in this case it was Xen Server 8.0 which is build upon Xen 4.11).
The date
element contains the build date of Xen.
You can also get all of that in a more compact form:
root@machine:~# lshw -xml -class system
<?xml version="1.0" standalone="yes"?> <!-- generated by lshw-B.02.17 --> <!-- GCC 5.4.0 20160609 --> <!-- Linux 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 --> <!-- GNU libc 2 (glibc 2.23) --> <list> <node id="mysystem" claimed="true" class="system" handle="DMI:0100"> <description>Computer</description> <product>HVM domU</product> <vendor>Xen</vendor> <version>4.11.1-7.2</version> <serial>e4d88b54-fd1b-3fbd-7760-08df2590409a</serial> <width units="bits">64</width> <configuration> <setting id="boot" value="normal"/> <setting id="uuid" value="E4D88B54-FD1B-3FBD-7760-08DF2590409A"/> </configuration> <capabilities> <capability id="smbios-2.4">SMBIOS version 2.4</capability> <capability id="dmi-2.4">DMI version 2.4</capability> <capability id="vsyscall32">32-bit processes</capability> </capabilities> </node> </list>