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.
151 lines
5.0 KiB
Python
151 lines
5.0 KiB
Python
import pytest
|
|
|
|
from napalm_redfish.parsers import (
|
|
parse_action_info,
|
|
parse_power_state,
|
|
parse_reset_action,
|
|
parse_system,
|
|
)
|
|
|
|
SYSTEM = "/redfish/v1/Systems/437XR1138R2"
|
|
|
|
|
|
def test_system_facts(rackmount):
|
|
s = parse_system(rackmount(SYSTEM))
|
|
assert s["id"] == "437XR1138R2"
|
|
assert s["name"] == "WebFrontEnd483"
|
|
assert s["manufacturer"] == "Contoso"
|
|
assert s["model"] == "3500"
|
|
assert s["serial_number"] == "437XR1138R2"
|
|
assert s["uuid"] == "38947555-7742-3448-3784-823347823834"
|
|
assert s["hostname"] == "web483"
|
|
assert s["sku"] == "8675309"
|
|
assert s["part_number"] == "224071-J23"
|
|
assert s["asset_tag"] == "Chicago-45Z-2381"
|
|
assert s["bios_version"] == "P79 v1.45 (12/06/2017)"
|
|
assert s["system_type"] == "Physical"
|
|
assert s["power_state"] == "On"
|
|
assert s["state"] == "Enabled"
|
|
assert s["health"] == "OK"
|
|
assert s["processor_count"] == 2
|
|
assert s["processor_model"] == "Multi-Core Intel(R) Xeon(R) processor 7xxx Series"
|
|
assert s["memory_gib"] == 96
|
|
|
|
|
|
def test_system_links(rackmount):
|
|
links = parse_system(rackmount(SYSTEM))["links"]
|
|
assert links["Processors"] == SYSTEM + "/Processors"
|
|
assert links["Memory"] == SYSTEM + "/Memory"
|
|
assert links["SimpleStorage"] == SYSTEM + "/SimpleStorage"
|
|
assert links["EthernetInterfaces"] == SYSTEM + "/EthernetInterfaces"
|
|
assert links["LogServices"] == SYSTEM + "/LogServices"
|
|
assert "Storage" not in links
|
|
s = parse_system(rackmount(SYSTEM))
|
|
assert s["chassis"] == ["/redfish/v1/Chassis/1U"]
|
|
assert s["managed_by"] == ["/redfish/v1/Managers/BMC"]
|
|
|
|
|
|
def test_system_placeholders_and_blanks_are_none():
|
|
# Supermicro boards report the DMI defaults the board vendor never filled in.
|
|
s = parse_system(
|
|
{
|
|
"Id": "1",
|
|
"Manufacturer": "Supermicro",
|
|
"Model": "X10DRL-i",
|
|
"SerialNumber": "0123456789",
|
|
"SKU": "To Be Filled By O.E.M.",
|
|
"HostName": "",
|
|
"UUID": " ",
|
|
"PartNumber": "Default string",
|
|
}
|
|
)
|
|
assert s["manufacturer"] == "Supermicro"
|
|
assert s["model"] == "X10DRL-i"
|
|
assert s["serial_number"] is None
|
|
assert s["sku"] is None
|
|
assert s["hostname"] is None
|
|
assert s["uuid"] is None
|
|
assert s["part_number"] is None
|
|
assert s["processor_count"] is None
|
|
assert s["memory_gib"] is None
|
|
assert s["links"] == {}
|
|
assert s["chassis"] == []
|
|
|
|
|
|
def test_power_state(rackmount):
|
|
assert parse_power_state(rackmount(SYSTEM)) == "On"
|
|
|
|
|
|
@pytest.mark.parametrize("value", ["On", "Off", "PoweringOn", "PoweringOff", "Paused"])
|
|
def test_power_state_values(value):
|
|
assert parse_power_state({"PowerState": value}) == value
|
|
|
|
|
|
def test_power_state_missing():
|
|
assert parse_power_state({}) is None
|
|
assert parse_power_state({"PowerState": None}) is None
|
|
|
|
|
|
def test_reset_action_inline_allowable_values(rackmount):
|
|
reset = parse_reset_action(rackmount(SYSTEM))
|
|
assert reset["target"] == SYSTEM + "/Actions/ComputerSystem.Reset"
|
|
assert reset["allowed"] == [
|
|
"On",
|
|
"ForceOff",
|
|
"GracefulShutdown",
|
|
"GracefulRestart",
|
|
"ForceRestart",
|
|
"Nmi",
|
|
"ForceOn",
|
|
"PushPowerButton",
|
|
"FullPowerCycle",
|
|
]
|
|
assert reset["action_info"] is None
|
|
|
|
|
|
def test_reset_action_with_action_info(telemetry):
|
|
reset = parse_reset_action(telemetry("/redfish/v1/Systems/1"))
|
|
assert reset["target"] == "/redfish/v1/Systems/1/Actions/ComputerSystem.Reset"
|
|
# Values live in the ActionInfo resource, not inline: unknown until that is read.
|
|
assert reset["allowed"] is None
|
|
assert reset["action_info"] == "/redfish/v1/Systems/1/ResetActionInfo"
|
|
|
|
|
|
def test_action_info(telemetry):
|
|
allowed = parse_action_info(telemetry("/redfish/v1/Systems/1/ResetActionInfo"))
|
|
assert allowed == [
|
|
"On",
|
|
"ForceOff",
|
|
"GracefulShutdown",
|
|
"GracefulRestart",
|
|
"ForceRestart",
|
|
"Nmi",
|
|
"ForceOn",
|
|
"PushPowerButton",
|
|
]
|
|
|
|
|
|
def test_action_info_other_parameter():
|
|
info = {
|
|
"Parameters": [
|
|
{"Name": "ResetType", "AllowableValues": ["On"]},
|
|
{"Name": "Delay", "AllowableValues": ["0", "5"]},
|
|
]
|
|
}
|
|
assert parse_action_info(info, "Delay") == ["0", "5"]
|
|
assert parse_action_info(info, "Missing") is None
|
|
assert parse_action_info({}) is None
|
|
|
|
|
|
def test_reset_action_manager(rackmount):
|
|
reset = parse_reset_action(rackmount("/redfish/v1/Managers/BMC"), "#Manager.Reset")
|
|
assert reset["target"] == "/redfish/v1/Managers/BMC/Actions/Manager.Reset"
|
|
assert reset["allowed"] == ["ForceRestart", "GracefulRestart"]
|
|
|
|
|
|
def test_reset_action_missing():
|
|
assert parse_reset_action({}) == {"target": None, "allowed": None, "action_info": None}
|
|
# Reset advertised without allowable values: allowed stays unknown, not empty.
|
|
reset = parse_reset_action({"Actions": {"#ComputerSystem.Reset": {"target": "/x"}}})
|
|
assert reset == {"target": "/x", "allowed": None, "action_info": None}
|