An `amt` driver (napalm_amt.AmtDriver), a ManagementControllerDriver for the management controller of Intel vPro machines, with its own lean WS-Management client (requests + ElementTree, HTTP Digest, ports 16992/16993). It reads the machine's identity, hardware with the SMBIOS system UUID, firmware (AMT with build, BIOS), power state and the hardware event log, reports what AMT listens on (plain HTTP or TLS, KVM incl. port 5900, IDE-R), and switches the machine's power. AMT cannot be reset over WS-Management, so there is no reboot_host. Discovery recognises AMT by its ports and its Server header. Tested against Intel's published AMT 12 recordings (go-wsman-messages, Apache-2.0, see NOTICE). `python -m napalm_amt.record` records a real AMT read-only; the first test devices are two Lenovo ThinkCentre M910x.
57 lines
1.5 KiB
Python
57 lines
1.5 KiB
Python
"""Helpers shared by the parsers: WS-Management values are strings, lists or missing."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
#: Values firmware puts where it has nothing to say (SMBIOS defaults), compared lowercased.
|
|
PLACEHOLDERS = frozenset(
|
|
{
|
|
"",
|
|
"0",
|
|
"none",
|
|
"default string",
|
|
"not specified",
|
|
"to be filled by o.e.m.",
|
|
"system product name",
|
|
"system serial number",
|
|
"123456789",
|
|
}
|
|
)
|
|
|
|
|
|
def as_list(value: Any) -> list[Any]:
|
|
"""A repeated element as a list; a single one as a list of one; none as empty."""
|
|
if value is None or value == "":
|
|
return []
|
|
return value if isinstance(value, list) else [value]
|
|
|
|
|
|
def first(value: Any) -> Any:
|
|
"""The first of a value that may be repeated."""
|
|
values = as_list(value)
|
|
return values[0] if values else None
|
|
|
|
|
|
def to_int(value: Any) -> int | None:
|
|
try:
|
|
return int(str(first(value)).strip())
|
|
except (TypeError, ValueError):
|
|
return None
|
|
|
|
|
|
def is_true(value: Any) -> bool:
|
|
return str(first(value)).strip().lower() in ("true", "1")
|
|
|
|
|
|
def text(value: Any) -> str:
|
|
"""A string value, stripped; a missing or nested one as empty."""
|
|
value = first(value)
|
|
return value.strip() if isinstance(value, str) else ""
|
|
|
|
|
|
def meaningful(value: Any) -> str:
|
|
"""``text(value)``, or empty for a firmware placeholder."""
|
|
result = text(value)
|
|
return "" if result.lower() in PLACEHOLDERS else result
|