Skip to content

Windows hardware detection - #22942

Merged
thiagoftsm merged 28 commits into
netdata:masterfrom
thiagoftsm:win_vm
Jul 13, 2026
Merged

Windows hardware detection #22942
thiagoftsm merged 28 commits into
netdata:masterfrom
thiagoftsm:win_vm

Conversation

@thiagoftsm

@thiagoftsm thiagoftsm commented Jul 2, 2026

Copy link
Copy Markdown
Contributor
Summary

Fixed an issue reported by the customer in which VMs were detected as bare metal.
mkt

Test Plan
Additional Information
For users: How does this change affect me?

Summary by cubic

Fixes Windows virtualization and container detection so VMs aren’t mislabeled as bare metal and Kubernetes/Windows Server containers are correctly identified. Adds a WMI → SMBIOS → registry probe chain with normalized strings, bounded WMI timeouts, aligned host/container OS fields, exported detection env vars, and updated docs/API.

  • Bug Fixes

    • Correctly classify virtualization on Windows: vmware, oracle, qemu, kvm, microsoft, xen, amazon, digitalocean, parallels; none for bare metal; unknown when unsure.
    • Detect containers: Kubernetes via KUBERNETES_SERVICE_{HOST,PORT}; Windows Server containers via HKLM\SYSTEM\CurrentControlSet\Control\ContainerType. Populate and export NETDATA_SYSTEM_CONTAINER and NETDATA_SYSTEM_CONTAINER_DETECTION.
    • Align OS fields: host OS set to unknown inside containers; container OS set to none on bare metal. Always set kernel name/version. Read NETDATA_OFFICIAL_IMAGE and export NETDATA_CONTAINER_IS_OFFICIAL_IMAGE.
    • Harden WMI and prevent hangs/crashes: shared BSTR→UTF‑8 helper, guarded VARIANT use, accept RPC_E_TOO_LATE, per‑query timeout via NETDATA_WMI_STARTUP_TIMEOUT_MS, and cap ConnectServer with WBEM_FLAG_CONNECT_USE_MAX_WAIT (~2 minutes). Windows build fixes included.
  • New Features

    • Add WMI helper GetWin32ComputerSystemInfo() (Win32_ComputerSystem) with per‑query timeout, a registry key‑existence probe, and expose dmi_is_virtual_machine() for SMBIOS fallback. Add virtualization string normalizer, probe resolution logic, and wire Windows unit tests into the test runner.
    • Add wmi startup timeout in netdata.conf (default 5000 ms, clamped 100–60000) to set NETDATA_WMI_STARTUP_TIMEOUT_MS. Docs clarify per‑query timeout vs. the separate ~2‑minute connect cap.
    • Export detection env vars: NETDATA_SYSTEM_VIRTUALIZATION, NETDATA_SYSTEM_VIRT_DETECTION, NETDATA_SYSTEM_CONTAINER, NETDATA_SYSTEM_CONTAINER_DETECTION, NETDATA_SYSTEM_CPU_DETECTION, NETDATA_SYSTEM_RAM_DETECTION, NETDATA_SYSTEM_DISK_DETECTION, NETDATA_CONTAINER_IS_OFFICIAL_IMAGE.
    • Update API docs to explain Windows virtualization/container values and detection methods.

Written for commit 9b68e46. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 16 files

Confidence score: 2/5

  • In src/libnetdata/os/windows-wmi/windows-wmi-GetSystemInfo.c, the helper can call cleanup on an uninitialized VARIANT when a WMI Get fails, which can crash the agent or corrupt memory on error paths; initialize vtProp before Get (or only clear it after successful initialization) before merging.
  • In src/daemon/win_system-info.c, detect_virt() may treat an SMBIOS “unknown” sentinel as a final result and skip registry fallback, so some virtualized hosts can be misclassified; adjust the control flow so “unknown” still triggers registry-based detection before merge.
Architecture diagram
sequenceDiagram
    participant Main as netdata_main
    participant WinSys as win_system-info
    participant WMI as WMI Provider
    participant SMBIOS as DMI / SMBIOS
    participant Reg as Windows Registry
    participant SysInfo as System Info Store
    participant Env as Environment Variables
    participant UnitTest as Unit Test

    Note over Main,Env: Windows Hardware Detection Probe Chain

    Main->>WinSys: netdata_windows_get_system_info()
    activate WinSys

    WinSys->>WinSys: netdata_windows_detect_virtualization()
    WinSys->>WinSys: netdata_windows_detect_virt()

    alt WMI query succeeds
        WinSys->>WMI: GetWin32ComputerSystemInfo()
        WMI-->>WinSys: Model, Manufacturer
        WinSys->>WinSys: netdata_windows_normalize_virt_string()
        Note over WinSys: Returns canonical name (e.g., "vmware", "microsoft", "kvm"...)
    else WMI fails
        WinSys->>SMBIOS: dmi_is_virtual_machine() via os_dmi_info_get()
        SMBIOS-->>WinSys: true/false + product name
        WinSys->>WinSys: netdata_windows_normalize_virt_string()
    else SMBIOS fails
        WinSys->>Reg: netdata_registry_key_exists(HKLM\SOFTWARE\VMware..., Oracle..., Parallels...)
        Reg-->>WinSys: true/false
    else all probes fail
        Note over WinSys: Fallback to "none" (bare metal)
    end

    WinSys->>SysInfo: rrdhost_system_info_set(NETDATA_SYSTEM_VIRTUALIZATION)
    WinSys->>Env: nd_setenv("NETDATA_SYSTEM_VIRTUALIZATION", ...)
    WinSys->>SysInfo: rrdhost_system_info_set(NETDATA_SYSTEM_VIRT_DETECTION, "windows-api")
    WinSys->>Env: nd_setenv("NETDATA_SYSTEM_VIRT_DETECTION", "windows-api")

    WinSys->>WinSys: netdata_windows_detect_container_state()
    alt Kubernetes env vars present
        WinSys->>WinSys: getenv(KUBERNETES_SERVICE_HOST) and getenv(KUBERNETES_SERVICE_PORT)
        Note over WinSys: Detected as Kubernetes container
    else WMI caption contains "container"
        WinSys->>WMI: GetWin32OperatingSystemInfo()
        WMI-->>WinSys: Caption
        WinSys->>WinSys: netdata_windows_str_contains_ci(Caption, "container")
        Note over WinSys: Detected as Windows Server container
    else neither
        Note over WinSys: No container environment detected
    end

    WinSys->>SysInfo: rrdhost_system_info_set(NETDATA_SYSTEM_CONTAINER, ...)
    WinSys->>Env: nd_setenv("NETDATA_SYSTEM_CONTAINER", ...)
    WinSys->>SysInfo: rrdhost_system_info_set(NETDATA_SYSTEM_CONTAINER_DETECTION, ...)
    WinSys->>Env: nd_setenv("NETDATA_SYSTEM_CONTAINER_DETECTION", ...)

    deactivate WinSys

    Note over Main,Env: Unit Test (Windows only)
    Main->>UnitTest: unit_test_windows_virt_normalize()
    activate UnitTest
    UnitTest->>WinSys: netdata_windows_normalize_virt_string() with test cases
    WinSys-->>UnitTest: canonical string
    UnitTest->>UnitTest: strcmp() against expected
    alt all matched
        UnitTest-->>Main: return 0 (OK)
    else failures
        UnitTest-->>Main: return 1 (ERROR)
    end
    deactivate UnitTest
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/libnetdata/os/windows-wmi/windows-wmi-GetSystemInfo.c
Comment thread src/daemon/win_system-info.c Outdated
Comment thread src/daemon/win_system-info.c Fixed
@thiagoftsm
thiagoftsm marked this pull request as ready for review July 2, 2026 19:31
@thiagoftsm
thiagoftsm requested review from a team and vkalintiris as code owners July 2, 2026 19:31
@thiagoftsm
thiagoftsm requested review from ktsaou and stelfrag July 2, 2026 19:33
@ktsaou

ktsaou commented Jul 2, 2026

Copy link
Copy Markdown
Member

Thanks for fixing the original Windows VM detection bug. The direction looks right, and the earlier hardcoded none values for Windows virtualization/container fields are clearly the root cause this PR addresses.

Before merge, I think there are two issues worth tightening:

  1. The new WMI helper uses WBEM_INFINITE while system info is collected synchronously during startup. That means a slow or unhealthy WMI provider can block agent startup before rrd_init(). Since the code already has SMBIOS/registry fallback paths, a bounded WMI timeout with graceful fallback should be safer.

  2. The Swagger text says Windows emits the same canonical virtualization values as the systemd taxonomy, but the current normalizer only covers a subset and the tests explicitly keep some known VM markers as unknown (Microsoft Hv, OpenStack, Linode). Either the mapping/tests should be expanded, or the docs should avoid promising full parity.

A good minimal fix would be: bound the WMI Next() wait, handle timeout as a failed WMI probe, and either expand the normalization table for the promised taxonomy or narrow the API wording. Longer term, adding a CPUID-based layer would make Windows VM detection more robust and closer to systemd-style detection.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 8 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/libnetdata/os/windows-wmi/windows-wmi-GetSystemInfo.c Outdated
Comment thread src/daemon/unit_test.c Fixed
Comment thread src/daemon/unit_test.c Fixed
Comment thread src/daemon/unit_test.c Fixed
Comment thread src/daemon/unit_test.c Fixed
@stelfrag

stelfrag commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

May need to consider WBEM_FLAG_CONNECT_USE_MAX_WAIT on ConnectServer() here: the new timeout only bounds Next(), but InitializeWMI()'s connect to winmgmt is unbounded, and since these probes now run on the daemon's synchronous startup path, a hung WMI would block agent startup indefinitely (the service already reports RUNNING, so it would look alive while serving nothing).

The flag caps the connect at ~2 min — not the configured timeout, but it turns an indefinite hang into a bounded delay. Note both startup probes would retry the connect, so worst case is ~2×2 min.

@stelfrag

Copy link
Copy Markdown
Collaborator
  • NETDATA_OFFICIAL_IMAGE handling is a no-op. The new netdata_windows_container_is_official_image() reads the env var and passes the value to rrdhost_system_info_set_by_name(), but that function discards the NETDATA_CONTAINER_IS_OFFICIAL_IMAGE key (src/database/rrdhost-system-info.c:167 — it returns without storing), and the Windows path doesn't nd_setenv() it either.

  • README overclaims "never blocks startup". The code comment in windows-wmi.c is honest that ConnectServer() with WBEM_FLAG_CONNECT_USE_MAX_WAIT can still take ~2 minutes, which is outside the configurable 100–60000 ms range. Worst case on an unhealthy WMI service is ~2 min connect + 2× the query timeout. Suggest the daemon README say "bounded" and mention the connect cap, so operators debugging slow startup aren't misled.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/daemon/win_system-info.c Outdated
Comment thread src/daemon/win_system-info.c Outdated
@thiagoftsm
thiagoftsm requested a review from stelfrag July 13, 2026 16:51
@sonarqubecloud

Copy link
Copy Markdown

@thiagoftsm
thiagoftsm merged commit 6734f30 into netdata:master Jul 13, 2026
153 of 156 checks passed
@thiagoftsm
thiagoftsm deleted the win_vm branch July 13, 2026 22:43
stelfrag pushed a commit to stelfrag/netdata that referenced this pull request Jul 14, 2026
Backport to 2.10.x. The feature files apply cleanly. During conflict
resolution the unit-test wiring was trimmed to what exists on this branch:
the OS_WINDOWS virt/container tests are kept, but the neighbouring
ringbuffer/log_stack/clocks/ws_client/mqtt_ng unittest registrations
(from netdata#22878 and later PRs, not present in 2.10.x) were excluded, along
with their unit_test.c includes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@stelfrag stelfrag mentioned this pull request Jul 14, 2026
Ferroin pushed a commit that referenced this pull request Jul 15, 2026
Backport to 2.10.x. The feature files apply cleanly. During conflict
resolution the unit-test wiring was trimmed to what exists on this branch:
the OS_WINDOWS virt/container tests are kept, but the neighbouring
ringbuffer/log_stack/clocks/ws_client/mqtt_ng unittest registrations
(from #22878 and later PRs, not present in 2.10.x) were excluded, along
with their unit_test.c includes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants