Mechanical: ruff format, and ruff check --fix with the rule set every NAPALM driver uses (E, F, I, UP, B at line length 100, Python 3.10). Mapping and Iterable come from collections.abc, imports are sorted. What ruff cannot fix comes in the next commit.
190 lines
5.9 KiB
Python
190 lines
5.9 KiB
Python
from napalm_redfish.parsers import (
|
|
parse_drive,
|
|
parse_memory,
|
|
parse_processor,
|
|
parse_simple_storage,
|
|
parse_storage,
|
|
)
|
|
|
|
SYSTEM = "/redfish/v1/Systems/437XR1138R2"
|
|
|
|
|
|
# --- Processors ----------------------------------------------------------------------------
|
|
|
|
|
|
def test_processor(rackmount):
|
|
cpu = parse_processor(rackmount(SYSTEM + "/Processors/CPU1"))
|
|
assert cpu == {
|
|
"id": "CPU1",
|
|
"name": "Processor",
|
|
"socket": "CPU 1",
|
|
"processor_type": "CPU",
|
|
"manufacturer": "Intel(R) Corporation",
|
|
"model": "Multi-Core Intel(R) Xeon(R) processor 7xxx Series",
|
|
"architecture": "x86",
|
|
"instruction_set": "x86-64",
|
|
"max_speed_mhz": 3700,
|
|
"cores": 8,
|
|
"threads": 16,
|
|
"serial_number": None,
|
|
"present": True,
|
|
"state": "Enabled",
|
|
# The CPU itself is OK; its HealthRollup (temperature warning) is not its health.
|
|
"health": "OK",
|
|
}
|
|
|
|
|
|
def test_processor_absent(rackmount):
|
|
cpu = parse_processor(rackmount(SYSTEM + "/Processors/CPU2"))
|
|
assert cpu["present"] is False
|
|
assert cpu["state"] == "Absent"
|
|
assert cpu["health"] is None
|
|
assert cpu["socket"] == "CPU 2"
|
|
assert cpu["model"] is None
|
|
assert cpu["cores"] is None
|
|
|
|
|
|
def test_processor_fpga(rackmount):
|
|
fpga = parse_processor(rackmount(SYSTEM + "/Processors/FPGA1"))
|
|
assert fpga["processor_type"] == "FPGA"
|
|
assert fpga["model"] == "Stratix 10"
|
|
# No Socket property: the location label stands in.
|
|
assert fpga["socket"] == "U168"
|
|
|
|
|
|
# --- Memory --------------------------------------------------------------------------------
|
|
|
|
|
|
def test_memory(rackmount):
|
|
dimm = parse_memory(rackmount(SYSTEM + "/Memory/DIMM1"))
|
|
assert dimm == {
|
|
"id": "DIMM1",
|
|
"name": "DIMM Slot 1",
|
|
"location": "DIMM 1",
|
|
"capacity_mib": 32768,
|
|
"memory_device_type": "DDR4",
|
|
"base_module_type": "RDIMM",
|
|
"speed_mhz": None,
|
|
"manufacturer": None,
|
|
"part_number": None,
|
|
"serial_number": None,
|
|
"present": True,
|
|
"state": "Enabled",
|
|
"health": "OK",
|
|
}
|
|
|
|
|
|
def test_memory_absent(rackmount):
|
|
dimm = parse_memory(rackmount(SYSTEM + "/Memory/DIMM4"))
|
|
assert dimm["present"] is False
|
|
assert dimm["capacity_mib"] is None
|
|
assert dimm["location"] == "DIMM 4"
|
|
|
|
|
|
def test_memory_older_schema():
|
|
# Memory 1.0-1.x: DeviceLocator instead of Location, speed in OperatingSpeedMhz.
|
|
dimm = parse_memory(
|
|
{
|
|
"Id": "1",
|
|
"Name": "Memory 1",
|
|
"DeviceLocator": "P1-DIMMA1",
|
|
"CapacityMiB": 16384,
|
|
"OperatingSpeedMhz": 2133,
|
|
"Manufacturer": "Samsung ",
|
|
"PartNumber": "M393A2G40DB0-CPB",
|
|
"SerialNumber": "12345678",
|
|
"MemoryDeviceType": "DDR4",
|
|
"Status": {"State": "Enabled", "Health": "OK"},
|
|
}
|
|
)
|
|
assert dimm["location"] == "P1-DIMMA1"
|
|
assert dimm["speed_mhz"] == 2133
|
|
assert dimm["manufacturer"] == "Samsung"
|
|
assert dimm["serial_number"] == "12345678"
|
|
|
|
|
|
def test_memory_zero_capacity_is_empty_slot():
|
|
# Some BMCs list empty slots as enabled with a capacity of 0.
|
|
dimm = parse_memory({"Id": "DIMM9", "CapacityMiB": 0, "Status": {"State": "Enabled"}})
|
|
assert dimm["present"] is False
|
|
|
|
|
|
# --- Storage -------------------------------------------------------------------------------
|
|
|
|
|
|
def test_storage(localstorage):
|
|
st = parse_storage(localstorage(SYSTEM + "/Storage/1"))
|
|
assert st["id"] == "1"
|
|
assert st["name"] == "Local Storage Controller"
|
|
assert st["state"] == "Enabled"
|
|
assert st["health"] == "OK"
|
|
assert st["controllers"] == [
|
|
{
|
|
"name": "Contoso Integrated RAID",
|
|
"manufacturer": "Contoso",
|
|
"model": "12Gbs Integrated RAID",
|
|
"serial_number": "2M220100SL",
|
|
"firmware_version": "1.0.0.7",
|
|
"speed_gbps": 12,
|
|
"state": "Enabled",
|
|
"health": "OK",
|
|
}
|
|
]
|
|
assert st["drive_paths"] == [
|
|
"/redfish/v1/Chassis/1U/Drives/35D38F11ACEF7BD3",
|
|
"/redfish/v1/Chassis/1U/Drives/3F5A8C54207B7233",
|
|
"/redfish/v1/Chassis/1U/Drives/32ADF365C6C1B7BD",
|
|
"/redfish/v1/Chassis/1U/Drives/3D58ECBC375FD9F2",
|
|
]
|
|
assert st["controllers_path"] is None
|
|
|
|
|
|
def test_storage_with_controller_collection():
|
|
# Storage 1.15 and later link a StorageController collection instead of an array.
|
|
st = parse_storage({"Id": "RAID", "Controllers": {"@odata.id": "/redfish/v1/x/Controllers"}})
|
|
assert st["controllers"] == []
|
|
assert st["controllers_path"] == "/redfish/v1/x/Controllers"
|
|
assert st["drive_paths"] == []
|
|
|
|
|
|
def test_drive(localstorage):
|
|
drive = parse_drive(localstorage("/redfish/v1/Chassis/1U/Drives/35D38F11ACEF7BD3"))
|
|
assert drive == {
|
|
"id": "35D38F11ACEF7BD3",
|
|
"name": "Drive Sample",
|
|
"manufacturer": "Contoso",
|
|
"model": "C123",
|
|
"serial_number": "1234567",
|
|
"part_number": "C123-1111",
|
|
"revision": "100A",
|
|
"capacity_bytes": 899527000064,
|
|
"media_type": "HDD",
|
|
"protocol": "SAS",
|
|
"failure_predicted": False,
|
|
"present": True,
|
|
"state": "Enabled",
|
|
"health": "OK",
|
|
}
|
|
|
|
|
|
def test_simple_storage(rackmount):
|
|
st = parse_simple_storage(rackmount(SYSTEM + "/SimpleStorage/1"))
|
|
assert st["id"] == "1"
|
|
assert st["name"] == "Simple Storage Controller"
|
|
assert st["health"] == "OK"
|
|
assert [d["name"] for d in st["drives"]] == [
|
|
"SATA Bay 1",
|
|
"SATA Bay 2",
|
|
"SATA Bay 3",
|
|
"SATA Bay 4",
|
|
]
|
|
bay1, bay2, bay3, _ = st["drives"]
|
|
assert bay1["model"] == "3000GT8"
|
|
assert bay1["capacity_bytes"] == 8000000000000
|
|
assert bay1["present"] is True
|
|
assert bay2["health"] == "Warning"
|
|
assert bay3["present"] is False
|
|
assert bay3["model"] is None
|
|
# Same keys as parse_drive, so callers can treat both alike.
|
|
assert set(bay1) == set(parse_drive({}))
|