Extend parsers for the driver
parse_power_supply also reads items of the legacy Power.PowerSupplies array, parse_ethernet_interface exposes the raw LinkStatus, and parse_network_protocol reports protocols that carry a Port without a ProtocolEnabled flag.
This commit is contained in:
4 files changed
+38
-14
No files matched your search
@@ -134,16 +134,12 @@ def parse_power(power: Mapping[str, Any]) -> dict[str, Any]:
|
|||||||
"""``Chassis/{id}/Power``: ``power`` (supplies), ``voltages``, ``consumed_watts``."""
|
"""``Chassis/{id}/Power``: ``power`` (supplies), ``voltages``, ``consumed_watts``."""
|
||||||
supplies: dict[str, Any] = {}
|
supplies: dict[str, Any] = {}
|
||||||
for index, item in _members(power, "PowerSupplies"):
|
for index, item in _members(power, "PowerSupplies"):
|
||||||
if not present(item):
|
psu = parse_power_supply(item)
|
||||||
|
if not psu["present"]:
|
||||||
continue
|
continue
|
||||||
name = unique_name(supplies, _name(item, "Name"), item.get("MemberId", index))
|
name = unique_name(supplies, psu["name"], item.get("MemberId", index))
|
||||||
capacity = number(item.get("PowerCapacityWatts"))
|
supplies[name] = {"status": psu["status"], "capacity": psu["capacity"],
|
||||||
output = number(item.get("LastPowerOutputWatts"))
|
"output": psu["output"]}
|
||||||
supplies[name] = {
|
|
||||||
"status": _ok(item),
|
|
||||||
"capacity": capacity if capacity is not None else -1.0,
|
|
||||||
"output": output if output is not None else -1.0,
|
|
||||||
}
|
|
||||||
|
|
||||||
voltages: dict[str, Any] = {}
|
voltages: dict[str, Any] = {}
|
||||||
for index, item in _members(power, "Voltages"):
|
for index, item in _members(power, "Voltages"):
|
||||||
@@ -210,12 +206,18 @@ def parse_fan(fan: Mapping[str, Any]) -> dict[str, Any]:
|
|||||||
|
|
||||||
def parse_power_supply(supply: Mapping[str, Any],
|
def parse_power_supply(supply: Mapping[str, Any],
|
||||||
metrics: Mapping[str, Any] | None = None) -> dict[str, Any]:
|
metrics: Mapping[str, Any] | None = None) -> dict[str, Any]:
|
||||||
"""One member of ``PowerSubsystem/PowerSupplies``, with its ``Metrics`` if read."""
|
"""One member of ``PowerSubsystem/PowerSupplies``, with its ``Metrics`` if read.
|
||||||
|
|
||||||
|
An item of the legacy ``Power.PowerSupplies`` array parses too (``MemberId`` as id,
|
||||||
|
``LastPowerOutputWatts`` as output).
|
||||||
|
"""
|
||||||
state, health = status(supply)
|
state, health = status(supply)
|
||||||
capacity = number(supply.get("PowerCapacityWatts"))
|
capacity = number(supply.get("PowerCapacityWatts"))
|
||||||
output = _excerpt(metrics, "OutputPowerWatts") if metrics else None
|
output = _excerpt(metrics, "OutputPowerWatts") if metrics else None
|
||||||
|
if output is None:
|
||||||
|
output = number(supply.get("LastPowerOutputWatts"))
|
||||||
return {
|
return {
|
||||||
"id": text(supply.get("Id")),
|
"id": text(supply.get("Id")) or text(supply.get("MemberId")),
|
||||||
"name": _name(supply, "Name"),
|
"name": _name(supply, "Name"),
|
||||||
"present": present(supply),
|
"present": present(supply),
|
||||||
"status": _ok(supply),
|
"status": _ok(supply),
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ def parse_ethernet_interface(iface: Mapping[str, Any]) -> dict[str, Any]:
|
|||||||
"ipv6": _ipv6(iface.get("IPv6Addresses")),
|
"ipv6": _ipv6(iface.get("IPv6Addresses")),
|
||||||
"hostname": text(iface.get("HostName")),
|
"hostname": text(iface.get("HostName")),
|
||||||
"fqdn": text(iface.get("FQDN")),
|
"fqdn": text(iface.get("FQDN")),
|
||||||
|
"link_status": link_status,
|
||||||
"vlan": vlan_id,
|
"vlan": vlan_id,
|
||||||
"permanent_mac_address": _mac(iface.get("PermanentMACAddress")) or None,
|
"permanent_mac_address": _mac(iface.get("PermanentMACAddress")) or None,
|
||||||
}
|
}
|
||||||
@@ -107,13 +108,13 @@ def parse_ethernet_interface(iface: Mapping[str, Any]) -> dict[str, Any]:
|
|||||||
def parse_network_protocol(proto: Mapping[str, Any]) -> dict[str, Any]:
|
def parse_network_protocol(proto: Mapping[str, Any]) -> dict[str, Any]:
|
||||||
"""``Managers/{id}/NetworkProtocol``: which services the BMC runs, NTP and SNMP.
|
"""``Managers/{id}/NetworkProtocol``: which services the BMC runs, NTP and SNMP.
|
||||||
|
|
||||||
``protocols`` holds every property with a ``ProtocolEnabled`` flag, so OEM-free services
|
``protocols`` holds every property with a ``ProtocolEnabled`` flag or a ``Port``, so
|
||||||
the schema adds later show up without code changes. NTP servers and the SNMP details
|
services the schema adds later show up without code changes. NTP servers and the SNMP details
|
||||||
exist only in newer schema versions; missing values are ``None``.
|
exist only in newer schema versions; missing values are ``None``.
|
||||||
"""
|
"""
|
||||||
protocols = {}
|
protocols = {}
|
||||||
for key, value in proto.items():
|
for key, value in proto.items():
|
||||||
if isinstance(value, Mapping) and "ProtocolEnabled" in value:
|
if isinstance(value, Mapping) and ("ProtocolEnabled" in value or "Port" in value):
|
||||||
protocols[key] = {
|
protocols[key] = {
|
||||||
"enabled": boolean(value.get("ProtocolEnabled")),
|
"enabled": boolean(value.get("ProtocolEnabled")),
|
||||||
"port": integer(value.get("Port")),
|
"port": integer(value.get("Port")),
|
||||||
|
|||||||
@@ -281,3 +281,17 @@ def test_build_environment_from_new_resources(rackmount):
|
|||||||
def test_build_environment_empty():
|
def test_build_environment_empty():
|
||||||
assert build_environment() == {
|
assert build_environment() == {
|
||||||
"fans": {}, "temperature": {}, "power": {}, "voltages": {}, "consumed_watts": None}
|
"fans": {}, "temperature": {}, "power": {}, "voltages": {}, "consumed_watts": None}
|
||||||
|
|
||||||
|
|
||||||
|
def test_power_supply_legacy_item(rackmount):
|
||||||
|
# Items of the legacy Power.PowerSupplies array parse the same way: MemberId as id,
|
||||||
|
# LastPowerOutputWatts as output.
|
||||||
|
(item,) = rackmount(CHASSIS + "/Power")["PowerSupplies"]
|
||||||
|
psu = parse_power_supply(item)
|
||||||
|
assert psu["id"] == "0"
|
||||||
|
assert psu["name"] == "Power Supply Bay"
|
||||||
|
assert psu["capacity"] == 800.0
|
||||||
|
assert psu["output"] == 325.0
|
||||||
|
assert psu["model"] == "499253-B21"
|
||||||
|
assert psu["serial_number"] == "1Z0000001"
|
||||||
|
assert psu["status"] is False
|
||||||
@@ -57,6 +57,7 @@ def test_ethernet_interface(rackmount):
|
|||||||
assert eth["fqdn"] == "web483-bmc.dmtf.org"
|
assert eth["fqdn"] == "web483-bmc.dmtf.org"
|
||||||
assert eth["vlan"] == 101
|
assert eth["vlan"] == 101
|
||||||
assert eth["permanent_mac_address"] == "23:11:8A:33:CF:EA"
|
assert eth["permanent_mac_address"] == "23:11:8A:33:CF:EA"
|
||||||
|
assert eth["link_status"] == "LinkUp"
|
||||||
|
|
||||||
|
|
||||||
def test_ethernet_interface_without_link_status(rackmount):
|
def test_ethernet_interface_without_link_status(rackmount):
|
||||||
@@ -64,6 +65,7 @@ def test_ethernet_interface_without_link_status(rackmount):
|
|||||||
eth = parse_ethernet_interface(rackmount(MANAGER + "/EthernetInterfaces/ToHost"))
|
eth = parse_ethernet_interface(rackmount(MANAGER + "/EthernetInterfaces/ToHost"))
|
||||||
assert eth["interface"]["is_up"] is True
|
assert eth["interface"]["is_up"] is True
|
||||||
assert eth["ipv4"] == {"192.168.20.55": {"prefix_length": 24}}
|
assert eth["ipv4"] == {"192.168.20.55": {"prefix_length": 24}}
|
||||||
|
assert eth["link_status"] is None
|
||||||
assert eth["vlan"] is None
|
assert eth["vlan"] is None
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +153,11 @@ def test_network_protocol_ntp(telemetry):
|
|||||||
"communities": []}
|
"communities": []}
|
||||||
|
|
||||||
|
|
||||||
|
def test_network_protocol_port_without_flag():
|
||||||
|
np = parse_network_protocol({"IPMI": {"Port": 623}, "Proxy": {"Enabled": True}})
|
||||||
|
assert np["protocols"] == {"IPMI": {"enabled": None, "port": 623}}
|
||||||
|
|
||||||
|
|
||||||
def test_network_protocol_ntp_blank_entries():
|
def test_network_protocol_ntp_blank_entries():
|
||||||
servers = ["", None, " pool.ntp.org ", "pool.ntp.org"]
|
servers = ["", None, " pool.ntp.org ", "pool.ntp.org"]
|
||||||
np = parse_network_protocol({"NTP": {"ProtocolEnabled": True, "NTPServers": servers}})
|
np = parse_network_protocol({"NTP": {"ProtocolEnabled": True, "NTPServers": servers}})
|
||||||
|
|||||||
Reference in new issue
Block a user