-
Notifications
You must be signed in to change notification settings - Fork 87
Description
Hey I run netbox-sync from development branch and I have this as a platform
2026-02-19 11:22:02,558 - INFO: Created new platform object: Usage: lsb_release [-a|--all] [-i|--id] [-d|--description] [-r|--release] [-c|-codename] [-s] [-b|-
2026-02-19 11:22:02,558 - INFO: Virtual machine 'xxxxxx' attribute 'platform' changed from 'Other 5.x or later Linux (64-bit)' to 'Usage: lsb_release [-a|--all] [-i|--id] [-d|--description] [-r|--release] [-c|-codename] [-s] [-b|-'
2
vmware shows i as
Guest OS | Other 5.x or later Linux (64-bit)
VMware Tools | Running, version:2147483647 (Guest Managed
I did a research about that you can check if that's accurate
The platform detection code in module/sources/vmware/connection.py add_virtual_machine() method (around line 2178-2189) follows this flow:
# Step 1: Get correct VMware guest OS name ✅
platform = get_string_or_none(grab(obj, "config.guestFullName"))
# e.g., "Other 5.x or later Linux (64-bit)"
# Step 2: Override with guest tools name (usually also correct) ✅
platform = get_string_or_none(grab(obj, "guest.guestFullName", fallback=platform))
# Step 3: Extract prettyName from extraConfig - THIS OVERRIDES WITH GARBAGE ❌
extra_config = [x.value for x in grab(obj, "config.extraConfig", fallback=[])
if x.key == "guestOS.detailed.data"]
if len(extra_config) > 0:
pretty_name = [x for x in quoted_split(extra_config[0].replace("' ", "', "))
if x.startswith("prettyName")]
if len(pretty_name) > 0:
platform = pretty_name[0].replace("prettyName='","")
# platform is now "Usage: lsb_release [-a|--all] ..."
# Step 4: Apply user mapping
platform = self.get_object_relation(platform, "vm_platform_relation", fallback=platform)What happens: VMware guest tools (open-vm-tools) internally run lsb_release to populate the guestOS.detailed.data extraConfig key. When lsb_release is not installed or misconfigured on the guest VM, instead of returning the OS pretty name, it returns its usage/help text. This gets stored by VMware as the prettyName in guestOS.detailed.data, and netbox-sync blindly uses it as the platform name, overriding the correct guestFullName from steps 1-2.
Environment
- netbox-sync version:
v1.8.0-22-gbb61e32(development branch, commitbb61e32) - NetBox version: 4.x
- VMware vCenter: 7.x/8.x
- Guest OS: Ubuntu 24.04 with open-vm-tools (Guest Managed)
- Guest VM
lsb_release: not installed or broken
Suggested Fix
Add validation to the prettyName extraction to ensure the value looks like a reasonable OS name before using it. If validation fails, fall back to the previously determined config.guestFullName / guest.guestFullName value.
Option A: Basic sanity check (minimal change)
extra_config = [x.value for x in grab(obj, "config.extraConfig", fallback=[])
if x.key == "guestOS.detailed.data"]
if len(extra_config) > 0:
pretty_name = [x for x in quoted_split(extra_config[0].replace("' ", "', "))
if x.startswith("prettyName")]
if len(pretty_name) > 0:
extracted_name = pretty_name[0].replace("prettyName='", "")
# Validate prettyName - reject values that look like command output/error text
if extracted_name and not extracted_name.startswith("Usage:") and len(extracted_name) < 100:
platform = extracted_name
else:
log.debug(f"Ignoring invalid prettyName from guestOS.detailed.data: '{extracted_name}'")**Option B: More robust validation **
extra_config = [x.value for x in grab(obj, "config.extraConfig", fallback=[])
if x.key == "guestOS.detailed.data"]
if len(extra_config) > 0:
pretty_name = [x for x in quoted_split(extra_config[0].replace("' ", "', "))
if x.startswith("prettyName")]
if len(pretty_name) > 0:
extracted_name = pretty_name[0].replace("prettyName='", "").rstrip("'")
# Validate: reject empty values, command output, or obviously invalid names
invalid_patterns = ["Usage:", "Error:", "command not found", "No such file"]
if extracted_name and not any(extracted_name.startswith(p) for p in invalid_patterns):
platform = extracted_name
else:
log.warning(f"VM '{name}': Ignoring invalid prettyName from guest tools: "
f"'{extracted_name}'. Using fallback: '{platform}'")thank you