import pytest from napalm_redfish.parsers import ( parse_ethernet_interface, parse_manager, parse_network_protocol, ) MANAGER = "/redfish/v1/Managers/BMC" def test_manager(rackmount): m = parse_manager(rackmount(MANAGER)) assert m["id"] == "BMC" assert m["name"] == "Manager" assert m["manager_type"] == "BMC" assert m["model"] == "Joo Janta 200" assert m["firmware_version"] == "1.45.455b66-rev4" assert m["uuid"] == "58893887-8974-2487-2389-841168418919" assert m["power_state"] == "On" assert m["date_time"] == "2015-03-13T04:14:33+06:00" assert m["state"] == "Enabled" assert m["health"] == "OK" assert m["links"]["EthernetInterfaces"] == MANAGER + "/EthernetInterfaces" assert m["links"]["NetworkProtocol"] == MANAGER + "/NetworkProtocol" assert m["links"]["LogServices"] == MANAGER + "/LogServices" assert m["manager_for_servers"] == ["/redfish/v1/Systems/437XR1138R2"] assert m["manager_for_chassis"] == ["/redfish/v1/Chassis/1U"] def test_manager_minimal(): m = parse_manager({"Id": "1", "FirmwareVersion": " 3.91 "}) assert m["firmware_version"] == "3.91" assert m["model"] is None assert m["links"] == {} assert m["manager_for_servers"] == [] # --- EthernetInterfaces -------------------------------------------------------------------- def test_ethernet_interface(rackmount): eth = parse_ethernet_interface(rackmount(MANAGER + "/EthernetInterfaces/eth0")) assert eth["name"] == "eth0" assert eth["interface"] == { "is_up": True, "is_enabled": True, "description": "Management network interface on a dedicated port", "last_flapped": -1.0, "speed": 100.0, "mtu": 1500, "mac_address": "23:11:8A:33:CF:EA", } assert eth["ipv4"] == {"192.168.0.10": {"prefix_length": 22}} assert eth["ipv6"] == {"fe80::1ec1:deff:fe6f:1e24": {"prefix_length": 64}} assert eth["hostname"] == "web483-bmc" assert eth["fqdn"] == "web483-bmc.dmtf.org" assert eth["vlan"] == 101 assert eth["permanent_mac_address"] == "23:11:8A:33:CF:EA" assert eth["link_status"] == "LinkUp" def test_ethernet_interface_without_link_status(rackmount): # No LinkStatus (as on older schemas): enabled and Status Enabled counts as up. eth = parse_ethernet_interface(rackmount(MANAGER + "/EthernetInterfaces/ToHost")) assert eth["interface"]["is_up"] is True assert eth["ipv4"] == {"192.168.20.55": {"prefix_length": 24}} assert eth["link_status"] is None assert eth["vlan"] is None @pytest.mark.parametrize( "props, is_up, is_enabled", [ ({"LinkStatus": "LinkDown", "InterfaceEnabled": True}, False, True), ({"LinkStatus": "NoLink", "InterfaceEnabled": True}, False, True), ({"LinkStatus": "LinkUp", "InterfaceEnabled": False}, False, False), ({"Status": {"State": "Disabled"}}, False, False), ({"Status": {"State": "Enabled"}}, True, True), ({}, False, False), ], ) def test_ethernet_link_state(props, is_up, is_enabled): eth = parse_ethernet_interface({"Id": "1", **props}) assert eth["interface"]["is_up"] is is_up assert eth["interface"]["is_enabled"] is is_enabled def test_ethernet_unset_addresses_and_formats(): # Supermicro and others report unset addresses as 0.0.0.0 or "::" and MACs in lower case. eth = parse_ethernet_interface({ "Id": "1", "MACAddress": "0c:c4:7a:aa:bb:cc", "SpeedMbps": None, "IPv4Addresses": [ {"Address": "0.0.0.0", "SubnetMask": "0.0.0.0"}, {"Address": "10.1.2.3", "SubnetMask": "255.255.255.0"}, {"Address": "10.1.2.4", "SubnetMask": "garbage"}, {"Address": None}, ], "IPv6Addresses": [ {"Address": "::", "PrefixLength": 0}, {"Address": "2001:DB8::5", "PrefixLength": 64}, {"Address": "2001:db8::6"}, ], }) assert eth["interface"]["mac_address"] == "0C:C4:7A:AA:BB:CC" assert eth["interface"]["speed"] == -1.0 assert eth["interface"]["mtu"] == 0 assert eth["interface"]["description"] == "" assert eth["ipv4"] == {"10.1.2.3": {"prefix_length": 24}} assert eth["ipv6"] == {"2001:db8::5": {"prefix_length": 64}, "2001:db8::6": {"prefix_length": 128}} # --- NetworkProtocol ----------------------------------------------------------------------- def test_network_protocol(rackmount): np = parse_network_protocol(rackmount(MANAGER + "/NetworkProtocol")) assert np["hostname"] == "web483-bmc" assert np["fqdn"] == "web483-bmc.dmtf.org" assert np["protocols"] == { "HTTP": {"enabled": True, "port": 80}, "HTTPS": {"enabled": True, "port": 443}, "IPMI": {"enabled": True, "port": 623}, "SSH": {"enabled": True, "port": 22}, "SNMP": {"enabled": True, "port": 161}, "VirtualMedia": {"enabled": True, "port": 17988}, "SSDP": {"enabled": True, "port": 1900}, "Telnet": {"enabled": True, "port": 23}, "KVMIP": {"enabled": True, "port": 5288}, } assert np["ntp"] == {"enabled": None, "servers": []} assert np["snmp"] == { "enabled": True, "port": 161, "v1": True, "v2c": False, "v3": True, "communities": [ {"name": "Read-only community", "access": "Limited"}, {"name": "Full access community", "access": "Full"}, ], } def test_network_protocol_ntp(telemetry): np = parse_network_protocol(telemetry("/redfish/v1/Managers/1/NetworkProtocol")) assert np["ntp"] == { "enabled": True, "servers": ["0.pool.ntp.org", "1.pool.ntp.org", "time-a.nist.gov"], } assert np["protocols"]["NTP"] == {"enabled": True, "port": None} # Older SNMP schema: only ProtocolEnabled and Port. assert np["snmp"] == {"enabled": True, "port": 161, "v1": None, "v2c": None, "v3": None, "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(): servers = ["", None, " pool.ntp.org ", "pool.ntp.org"] np = parse_network_protocol({"NTP": {"ProtocolEnabled": True, "NTPServers": servers}}) assert np["ntp"]["servers"] == ["pool.ntp.org"] assert np["snmp"] == {"enabled": None, "port": None, "v1": None, "v2c": None, "v3": None, "communities": []}