feat(interfaces): report the assigned interface name alongside the physical one
get_interfaces() keys entries by the physical device ("em0"), which is what
every other call in this driver speaks. Wake-on-LAN is the exception: it needs
the name OPNsense assigned ("lan", "opt1") and silently rejects anything else
with an empty {} at HTTP 200.
The overview export already carries it, so pass it through as "identifier".
Empty for interfaces OPNsense has not assigned.
This commit is contained in:
@@ -220,6 +220,11 @@ class OPNsenseDriver(OPNsensePingMixin, FirewallDriver):
|
||||
Each entry contains NAPALM standard keys:
|
||||
``is_up``, ``is_enabled``, ``description``, ``last_flapped``,
|
||||
``mac_address``, ``speed``, ``mtu``.
|
||||
|
||||
Plus one non-standard key, ``identifier``: OPNsense's *assigned*
|
||||
interface name ("lan", "opt1"), as opposed to the physical device the
|
||||
dict is keyed by ("em0"). Empty for unassigned interfaces. This is the
|
||||
name :meth:`send_wake_on_lan` requires — see the note there.
|
||||
"""
|
||||
data = self._get("/api/interfaces/overview/export")
|
||||
interfaces: dict[str, dict[str, Any]] = {}
|
||||
@@ -240,6 +245,7 @@ class OPNsenseDriver(OPNsensePingMixin, FirewallDriver):
|
||||
"mac_address": (iface.get("macaddr") or iface.get("mac") or "").lower(),
|
||||
"speed": float(iface["speed_mbps"]) if iface.get("speed_mbps") else 0.0,
|
||||
"mtu": int(iface["mtu"]) if iface.get("mtu") else 0,
|
||||
"identifier": iface.get("identifier") or "",
|
||||
}
|
||||
|
||||
return interfaces
|
||||
|
||||
@@ -61,6 +61,31 @@ INTERFACES_RESPONSE = {
|
||||
]
|
||||
}
|
||||
|
||||
# Bare-list shape with the "identifier" field: OPNsense's assigned interface
|
||||
# name, distinct from the physical "device" the dict is keyed by. Wake-on-LAN
|
||||
# is addressed by the former, everything else in this driver by the latter.
|
||||
IDENTIFIED_INTERFACES_RESPONSE = [
|
||||
{
|
||||
"device": "em0",
|
||||
"identifier": "lan",
|
||||
"description": "LAN",
|
||||
"status": "up",
|
||||
"enabled": True,
|
||||
"macaddr": "AA:BB:CC:DD:EE:FF",
|
||||
"speed_mbps": 1000,
|
||||
"mtu": 1500,
|
||||
},
|
||||
{
|
||||
"device": "em1",
|
||||
"identifier": "opt1",
|
||||
"description": "GUEST",
|
||||
"status": "down",
|
||||
"enabled": True,
|
||||
"macaddr": "AA:BB:CC:DD:EE:00",
|
||||
"mtu": 1500,
|
||||
},
|
||||
]
|
||||
|
||||
# Real shape confirmed against a live OPNsense 24.7 instance's
|
||||
# GET /api/interfaces/overview/export (see issue #14): a bare top-level list
|
||||
# of interface dicts, addressed via "device" and CIDR "addr4"/"addr6"
|
||||
@@ -262,6 +287,20 @@ class TestGetInterfaces:
|
||||
ifaces = driver.get_interfaces()
|
||||
assert ifaces["em0"]["last_flapped"] == -1.0
|
||||
|
||||
def test_identifier_passed_through(self, driver):
|
||||
# OPNsense's *assigned* name, which is what send_wake_on_lan() needs —
|
||||
# the dict key is the physical device ("em0"), which it rejects.
|
||||
driver._get = lambda path: IDENTIFIED_INTERFACES_RESPONSE
|
||||
ifaces = driver.get_interfaces()
|
||||
assert ifaces["em0"]["identifier"] == "lan"
|
||||
assert ifaces["em1"]["identifier"] == "opt1"
|
||||
|
||||
def test_identifier_empty_when_unassigned(self, driver):
|
||||
# An interface OPNsense has not assigned carries no identifier.
|
||||
driver._get = lambda path: INTERFACES_RESPONSE
|
||||
ifaces = driver.get_interfaces()
|
||||
assert ifaces["em0"]["identifier"] == ""
|
||||
|
||||
def test_empty_response(self, driver):
|
||||
driver._get = lambda path: {"interfaces": []}
|
||||
assert driver.get_interfaces() == {}
|
||||
|
||||
Reference in New Issue
Block a user