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>

Sources