fix: read DMI fields separately to avoid shell quoting issues
The combined printf approach silently produced empty values when product_name/version contained special chars or the shell split tokens incorrectly. Read each /sys/class/dmi/id/ file via a separate cat, collect lines, then apply vendor-specific model name selection: - Intel NUC: product_name='NUC6CAYH' (marketing) preferred over product_version='J26843-409' (part number) - Lenovo: product_name='10MYS03U00' (type code, all-caps+digits) → prefer product_version='ThinkCentre M910x' (marketing name) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
a3b0414d99
commit
d9b3ac12ea
+29
-20
@@ -357,34 +357,43 @@ class ProxmoxDriver(
|
|||||||
os_version = f"Proxmox VE {pve_version}" if pve_version else f"Proxmox VE {release}"
|
os_version = f"Proxmox VE {pve_version}" if pve_version else f"Proxmox VE {release}"
|
||||||
|
|
||||||
# Physical hardware info from Linux DMI sysfs.
|
# Physical hardware info from Linux DMI sysfs.
|
||||||
# product_version often contains the marketing name (e.g. "ThinkCentre M910x")
|
# Read each field separately to avoid shell quoting issues with printf.
|
||||||
# while product_name holds the machine-type code (e.g. "10MYS03U00").
|
# Field priority for model:
|
||||||
# We prefer product_version when it is set and not identical to product_name.
|
# product_name — human-readable name on most vendors (e.g. "NUC6CAYH",
|
||||||
|
# "ThinkCentre M910x")
|
||||||
|
# product_version — sometimes the marketing name on Lenovo; on Intel NUC
|
||||||
|
# it is the board part number (less useful as model name)
|
||||||
|
# We prefer product_name; fall back to product_version only when
|
||||||
|
# product_name looks like a raw type code (all uppercase + digits, no spaces).
|
||||||
vendor = ""
|
vendor = ""
|
||||||
model = ""
|
model = ""
|
||||||
serial = ""
|
serial = ""
|
||||||
try:
|
try:
|
||||||
dmi_cmd = (
|
dmi_cmd = (
|
||||||
"printf '%s\\t%s\\t%s\\t%s' "
|
"v=$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null); "
|
||||||
"\"$(cat /sys/class/dmi/id/sys_vendor 2>/dev/null)\" "
|
"n=$(cat /sys/class/dmi/id/product_name 2>/dev/null); "
|
||||||
"\"$(cat /sys/class/dmi/id/product_name 2>/dev/null)\" "
|
"r=$(cat /sys/class/dmi/id/product_version 2>/dev/null); "
|
||||||
"\"$(cat /sys/class/dmi/id/product_version 2>/dev/null)\" "
|
"s=$(cat /sys/class/dmi/id/product_serial 2>/dev/null); "
|
||||||
"\"$(cat /sys/class/dmi/id/product_serial 2>/dev/null)\""
|
"printf '%s\\n%s\\n%s\\n%s\\n' \"$v\" \"$n\" \"$r\" \"$s\""
|
||||||
)
|
)
|
||||||
raw = self._exec_ssh_command(dmi_cmd).strip()
|
lines = self._exec_ssh_command(dmi_cmd).splitlines()
|
||||||
parts = raw.split("\t")
|
if len(lines) >= 4:
|
||||||
if len(parts) >= 4:
|
vendor = lines[0].strip()
|
||||||
vendor = parts[0].strip()
|
product_name = lines[1].strip()
|
||||||
product_name = parts[1].strip()
|
product_version = lines[2].strip()
|
||||||
product_version = parts[2].strip()
|
serial = lines[3].strip()
|
||||||
serial = parts[3].strip()
|
|
||||||
# Prefer product_version (marketing name) over product_name (type code)
|
_bad = {"none", "n/a", "not specified", "to be filled by o.e.m."}
|
||||||
# unless it is empty, "None", or identical to product_name.
|
pv_ok = (
|
||||||
if (
|
|
||||||
product_version
|
product_version
|
||||||
and product_version.lower() not in ("none", "n/a", "not specified")
|
and product_version.lower() not in _bad
|
||||||
and product_version != product_name
|
and product_version != product_name
|
||||||
):
|
)
|
||||||
|
# Use product_version as model when product_name looks like a
|
||||||
|
# raw type code (Lenovo style: all uppercase letters and digits)
|
||||||
|
import re as _re
|
||||||
|
pn_is_code = bool(_re.fullmatch(r"[A-Z0-9]+", product_name))
|
||||||
|
if pn_is_code and pv_ok:
|
||||||
model = product_version
|
model = product_version
|
||||||
else:
|
else:
|
||||||
model = product_name
|
model = product_name
|
||||||
|
|||||||
Reference in New Issue
Block a user