feat: report the licenses a BMC asks for as facts (0.5.0)

get_licenses (napalm-device-types LicenseMixin, 4.15) on redfish and bmc,
for NetOrk/netork#1111.

- A BMC that refuses Redfish altogether reports each license it names as
  missing, with its message.
- One that answers but withholds parts reports the license with withholds,
  e.g. DCMS withholding drives and the firmware inventory on an X10 with
  only SFT-OOB-LIC.
- ipmi knows no licenses.

get_device_warnings keeps its two codes until netOrk derives them.
This commit is contained in:
Christian Manivong committed 2026-10-17 11:32:59 +02:00
1 parent e9ad7951cd
commit 5b24675a12
9 files changed
+86 -7

No files matched your search

+9
View File
@@ -156,3 +156,12 @@ def test_over_ipmi_the_protocol_netork_talks_is_known_to_be_on(unlicensed):
def test_the_bmc_is_not_reset_over_ipmi(unlicensed):
with pytest.raises(RuntimeError, match="needs Redfish"):
unlicensed.reboot_host()
def test_the_license_facts_are_redfish_s_even_while_ipmi_reads(unlicensed):
assert [lic["name"] for lic in unlicensed.get_licenses()] == ["SUM", "DCMS", "OOB"]
def test_ipmi_knows_no_licenses():
assert not hasattr(ipmi.IpmiDriver, "get_licenses")
assert callable(getattr(BmcDriver, "get_licenses", None))
+14
View File
@@ -511,6 +511,20 @@ def test_unlicensed_bmc_still_opens(server):
}
def test_unlicensed_bmc_names_every_license_it_asks_for_as_missing(server):
licenses = _unlicensed(server).get_licenses()
assert [(lic["name"], lic["status"]) for lic in licenses] == [
("SUM", "missing"), ("DCMS", "missing"), ("OOB", "missing")]
# Refused altogether: nothing is withheld in part.
assert all("withholds" not in lic and "Not licensed" in lic["detail"] for lic in licenses)
def test_a_licensed_bmc_reports_no_license_facts(server):
d = RedfishDriver("bmc.example.net", "netork", "s3cret", optional_args={"verify_ssl": False})
d.open()
assert d.get_licenses() == []
def test_unlicensed_bmc_reports_the_missing_license(server):
(warning,) = _unlicensed(server).get_device_warnings()
assert warning["code"] == "bmc_license_required"
+11
View File
@@ -89,3 +89,14 @@ def test_the_sensors_and_the_event_log_read(driver):
assert len(env["temperature"]) == 19
assert len(env["fans"]) == 4
assert isinstance(driver.get_event_log(limit=5), list)
# ── licenses as facts (#1111) ───────────────────────────────────────────
def test_the_missing_license_is_a_fact_with_what_it_withholds(driver):
assert driver.get_licenses() == [{
"name": "DCMS",
"status": "missing",
"withholds": ["drives", "firmware inventory"],
}]