def run_command(cmd, check=True, **kwargs):
import subprocess
+ from test.support import has_subprocess_support
+
+ if not has_subprocess_support:
+ # subprocess is not supported by the current platform
+ return ''
+
timeout = COMMAND_TIMEOUT
cmd_str = ' '.join(cmd)
return None
+def wmi_query(query):
+ try:
+ import _wmi
+ except ImportError:
+ return {}
+
+ try:
+ data = _wmi.exec_query(query)
+ except OSError:
+ return {}
+
+ dict_data = {}
+ for item in data.split("\0"):
+ key, _, value = item.partition("=")
+ dict_data[key] = value
+ return dict_data
+
+
def collect_windows(info_add):
if not MS_WINDOWS:
# Code specific to Windows
call_func(info_add, 'windows.ansi_code_page', _winapi, 'GetACP')
call_func(info_add, 'windows.oem_code_page', _winapi, 'GetOEMCP')
- # windows.version_caption: "wmic os get Caption,Version /value" command
- output = run_command(["wmic", "os", "get", "Caption,Version", "/value"],
- # When wmic.exe output is redirected to a pipe,
- # it uses the OEM code page
- encoding="oem")
- if output:
- for line in output.splitlines():
- line = line.strip()
- if line.startswith('Caption='):
- line = line.removeprefix('Caption=').strip()
- if line:
- info_add('windows.version_caption', line)
- elif line.startswith('Version='):
- line = line.removeprefix('Version=').strip()
- if line:
- info_add('windows.version', line)
+ # Get operating system caption and version using WMI
+ data = wmi_query("SELECT Caption, Version FROM Win32_OperatingSystem")
+ caption = data.get('Caption', '')
+ if caption:
+ info_add('windows.version_caption', caption)
+ version = data.get('Version', '')
+ if version:
+ info_add('windows.version', version)
# windows.ver: "ver" command
output = run_command(["ver"], shell=True)
return None
-def detect_virt():
+def detect_virt_windows(info_add):
+ # On Windows, use WMI to detect the virtualization.
+ #
+ # Microsoft Hyper-V:
+ # - Win32_Bios.Version = 'VRTUAL - 12001807'
+ # - Win32_Bios.Manufacturer = 'American Megatrends Inc.'
+ # - Win32_ComputerSystem.Model = 'Virtual Machine'
+ # - Win32_ComputerSystem.Manufacturer = 'Microsoft Corporation'
+ #
+ # VMware:
+ # - Win32_ComputerSystem.Model = 'VMware'
+ # - Win32_ComputerSystem.Manufacturer = 'VMWare' (uppercase W in Ware)
+ # - Win32_Bios.SerialNumber starts with 'VMware-'
+ #
+ # QEMU:
+ # - Win32_ComputerSystem.Manufacturer = 'QEMU'
+ # - Win32_ComputerSystem.Model = 'Standard PC (Q35 + ICH9, 2009)'
+ # - Win32_Bios.Version = 'BOCHS - 1'
+ # - Win32_Bios.Manufacturer = 'EDK II'
+ #
+ # Parallels:
+ # - Win32_Bios.Version = 'PARALLELS'
+ #
+ # VirtualBox:
+ # - Win32_Bios.Version = 'VBOX'
+ # - Win32_ComputerSystem.Model = 'VirtualBox'
+ # - Win32_ComputerSystem.Manufacturer = 'innotek GmbH'
+ #
+ # Amazon EC2:
+ # - Win32_Bios.Version = 'AMAZON - 1'
+ # - Win32_Bios.Manufacturer = 'Amazon EC2'
+ # - Win32_ComputerSystem.Model = 'm7i.4xlarge'
+ # - Win32_ComputerSystem.Manufacturer = 'Amazon EC2'
+
+ KNOWN_VIRT = (
+ 'Amazon EC2',
+ 'QEMU',
+ 'VMware',
+ 'VirtualBox',
+ 'Xen',
+ 'oVirt',
+ )
+ KNOWN_BIOS_VERSIONS = {
+ 'PARALLELS': 'Parallels',
+ 'VBOX': 'VirtualBox',
+ }
+
+ computer = wmi_query('SELECT Model, Manufacturer FROM Win32_ComputerSystem')
+ computer_model = computer.get('Model', '')
+ computer_manufacturer = computer.get('Manufacturer', '')
+ if computer_manufacturer == 'Amazon EC2':
+ # Log the VM model (ex: 'm7i.4xlarge')
+ info_add('system.computer.model', computer_model)
+ return computer_manufacturer
+ if computer_model in KNOWN_VIRT:
+ return computer_model
+ if computer_manufacturer in KNOWN_VIRT:
+ return computer_manufacturer
+
+ bios = wmi_query('SELECT Version, Manufacturer FROM Win32_Bios')
+
+ bios_version = bios.get('Version', '')
+ if bios_version in KNOWN_VIRT:
+ return bios_version
+ if (bios_version.startswith('VRTUAL - ')
+ and computer_manufacturer == 'Microsoft Corporation'):
+ return 'Microsoft Hyper-V'
+ try:
+ return KNOWN_BIOS_VERSIONS[bios_version]
+ except KeyError:
+ pass
+
+ bios_manufacturer = bios.get('Manufacturer', '')
+ if bios_manufacturer in KNOWN_VIRT:
+ return bios_manufacturer
+
+ # Log the values to update the code if a new VM is discovered
+ if computer_model:
+ info_add('system.computer.model', computer_model)
+ if computer_manufacturer:
+ info_add('system.computer.manufacturer', computer_manufacturer)
+ if bios_version:
+ info_add('system.bios.version', bios_version)
+ if bios_manufacturer:
+ info_add('system.bios.manufacturer', bios_manufacturer)
+
+
+def detect_virt(info_add):
+ if MS_WINDOWS:
+ return detect_virt_windows(info_add)
+
# Run systemd-detect-virt command
virt = run_command(["systemd-detect-virt"], check=False)
if virt and virt != "none":
uptime = f'{uptime} sec'
info_add('system.uptime', uptime)
- virt = detect_virt()
+ virt = detect_virt(info_add)
if virt:
info_add('system.virt', virt)