First run against real hardware over Redfish: an X10DRL-i (BMC 3.91) with
SFT-OOB-LIC. Its Redfish tree is recorded under
tests/fixtures/supermicro-x10drl-i-3.91/redfish, scrubbed.
- A resource refused for want of a further license (403 OemLicenseNotPassed)
no longer fails the getter. Storage then falls back to SimpleStorage. The
firmware list falls back to the BMC and BIOS versions when UpdateService
is withheld.
- get_device_warnings reports bmc_license_partial with the licenses and the
withheld parts (drives, firmware inventory).
- A placeholder system model ("Super Server") is replaced by the board
(PartNumber, else the chassis model).
92 lines
3.2 KiB
Python
92 lines
3.2 KiB
Python
"""RedfishDriver against a recording of a real Supermicro X10DRL-i (BMC 3.91, Redfish 1.0.1).
|
|
|
|
Recorded 2026-10-17 with an SFT-OOB-LIC license only: the service root and most resources
|
|
answer, but ``Systems/1/Storage`` and ``UpdateService`` want the DCMS license as well (403,
|
|
``OemLicenseNotPassed``). Serial numbers, UUIDs, MACs, addresses, the host name and the SNMP
|
|
communities are scrubbed. ``STATUS.json`` lists the paths that did not answer 200; their
|
|
files hold the error body the BMC sent.
|
|
"""
|
|
|
|
import json
|
|
|
|
import pytest
|
|
from napalm_device_types import models
|
|
|
|
from napalm_redfish import RedfishDriver
|
|
from tests.conftest import BASE_URL, FIXTURES, MockupServer
|
|
|
|
MOCKUP = "supermicro-x10drl-i-3.91/redfish"
|
|
REFUSED = json.loads((FIXTURES / MOCKUP / "STATUS.json").read_text())
|
|
|
|
|
|
@pytest.fixture
|
|
def x10(http):
|
|
server = MockupServer(http, MOCKUP)
|
|
for path, status in REFUSED.items():
|
|
body = json.loads((FIXTURES / MOCKUP / path[len("/redfish/v1/"):] / "index.json")
|
|
.read_text())
|
|
server.override("GET", path, status, body)
|
|
return server
|
|
|
|
|
|
@pytest.fixture
|
|
def driver(x10):
|
|
d = RedfishDriver(BASE_URL.removeprefix("https://"), "netork", "secret",
|
|
optional_args={"verify_ssl": False})
|
|
d.open()
|
|
yield d
|
|
d.close()
|
|
|
|
|
|
def test_the_facts_name_the_board_not_super_server(driver):
|
|
facts = driver.get_facts()
|
|
assert facts["vendor"] == "Supermicro"
|
|
# Systems/1 says "Super Server"; the board is its PartNumber and the chassis model.
|
|
assert facts["model"] == "X10DRL-i"
|
|
assert facts["os_version"] == "3.91"
|
|
assert facts["serial_number"] == "ZM000S000001"
|
|
|
|
|
|
def test_the_inventory_survives_the_storage_it_may_not_read(driver):
|
|
inv = driver.get_hardware_inventory()
|
|
assert set(inv) == set(models.HardwareInventoryDict.__annotations__)
|
|
assert inv["model"] == "X10DRL-i"
|
|
assert inv["system_uuid"] == "00000000-0000-0000-0000-00005e00534c"
|
|
assert len(inv["cpus"]) == 2
|
|
assert len(inv["memory"]) == 8
|
|
assert inv["drives"] == []
|
|
|
|
|
|
def test_the_firmware_comes_from_the_manager_and_the_system_without_updateservice(driver):
|
|
assert driver.get_firmware_inventory() == [
|
|
{"name": "BMC", "version": "3.91", "updateable": None},
|
|
{"name": "BIOS", "version": "3.1c", "updateable": None},
|
|
]
|
|
|
|
|
|
def test_the_missing_license_is_named_with_what_it_withholds(driver):
|
|
assert driver.get_device_warnings() == [{
|
|
"code": "bmc_license_partial",
|
|
"meta": {"licenses": "DCMS", "parts": ["drives", "firmware inventory"]},
|
|
}]
|
|
|
|
|
|
def test_the_power_actions_are_the_ones_the_bmc_advertises(driver):
|
|
assert driver.get_power_state() == {
|
|
"state": "On",
|
|
"actions": ["GracefulShutdown", "ForceOff", "GracefulRestart", "ForceRestart"],
|
|
}
|
|
|
|
|
|
def test_the_protocols_report_ipmi_over_lan_on(driver):
|
|
protocols = driver.get_management_protocols()
|
|
assert protocols["ipmi"] == {"enabled": True, "port": 623}
|
|
assert protocols["https"] == {"enabled": True, "port": 443}
|
|
|
|
|
|
def test_the_sensors_and_the_event_log_read(driver):
|
|
env = driver.get_environment()
|
|
assert len(env["temperature"]) == 19
|
|
assert len(env["fans"]) == 4
|
|
assert isinstance(driver.get_event_log(limit=5), list)
|