fix_snmp hard-coded community "public" and found the management VLAN for the source interface with a substring match, so 10.0.0.1 matched 10.0.0.10 and a DNS name never matched (#3). The driver implements napalm-device-types 4.13's configure_snmp_agent steps: the caller's community (read-only, viewDefault), the source interface set to the VLAN whose address is exactly the listen address or the management address, configuration saved, and the community checked in show snmp community. Contact and location are reported as not set; there is no verified CLI for them on this switch. A value that would break the CLI is refused. The requirements now name napalm-device-types 4.13 in both files. BREAKING CHANGE: run_device_action is removed. Part of #3 and #4.
85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
"""The SNMP agent through napalm-device-types' configure_snmp_agent (netOrk #1105).
|
|
|
|
fix_snmp hard-coded community "public" and found the management VLAN by a
|
|
substring match (10.0.0.1 matched 10.0.0.10, #3). The community is the caller's
|
|
now, and the source interface is the VLAN that carries exactly the management
|
|
address.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
from napalm_tplink_jetstream.tplink_jetstream import TPLinkJetstreamDriver
|
|
|
|
SETTINGS = {"community": "c0mm", "allowed_sources": ["10.7.224.20"], "contact": "ops"}
|
|
|
|
SHOW_IP_INTERFACE = """\
|
|
VLAN1 is up, line protocol is up
|
|
Primary IP address: 10.0.0.10/24
|
|
VLAN8 is up, line protocol is up
|
|
Primary IP address: 10.0.0.1/24
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def driver():
|
|
d = TPLinkJetstreamDriver("10.0.0.1", "admin", "pw")
|
|
d.device = MagicMock()
|
|
d.sent: list[str] = []
|
|
d.device.send_command.side_effect = lambda cmd, **kw: d.sent.append(cmd) or ""
|
|
d._conf_prompt = lambda: r"\(config\)#"
|
|
d._enter_config_mode = MagicMock()
|
|
d._exit_config_mode = MagicMock()
|
|
d._save_config = MagicMock()
|
|
d._send_command = MagicMock(
|
|
side_effect=lambda cmd: SHOW_IP_INTERFACE
|
|
if cmd == "show ip interface"
|
|
else "Index Community-Name Access\n1 c0mm read-only\n"
|
|
)
|
|
return d
|
|
|
|
|
|
def test_the_callers_community(driver):
|
|
result = driver.configure_snmp_agent(SETTINGS)
|
|
|
|
assert result["success"] is True
|
|
assert 'snmp-server community "c0mm" read-only "viewDefault"' in driver.sent
|
|
assert not any("public" in c for c in driver.sent)
|
|
driver._save_config.assert_called_once()
|
|
|
|
|
|
def test_the_source_interface_is_the_vlan_of_exactly_the_management_address(driver):
|
|
driver.configure_snmp_agent(SETTINGS)
|
|
|
|
assert "snmp-server source-interface vlan 8" in driver.sent
|
|
|
|
|
|
def test_contact_and_location_are_reported_as_not_set(driver):
|
|
steps = {s["step"]: s for s in driver.configure_snmp_agent(SETTINGS)["steps"]}
|
|
|
|
assert "contact" in steps["configure"]["output"]
|
|
|
|
|
|
def test_a_community_the_switch_does_not_list_fails(driver):
|
|
driver._send_command.side_effect = lambda cmd: (
|
|
SHOW_IP_INTERFACE if cmd == "show ip interface" else "1 public read-only\n"
|
|
)
|
|
|
|
assert driver.configure_snmp_agent(SETTINGS)["success"] is False
|
|
|
|
|
|
@pytest.mark.parametrize("community", ["two words", 'q"uote', ""])
|
|
def test_a_community_that_would_break_the_cli_is_refused(driver, community):
|
|
result = driver.configure_snmp_agent({"community": community, "allowed_sources": []})
|
|
|
|
assert result["success"] is False
|
|
assert driver.sent == []
|
|
|
|
|
|
def test_the_old_action_is_gone():
|
|
for name in ("run_device_action", "_action_fix_snmp", "_detect_management_vlan"):
|
|
assert not hasattr(TPLinkJetstreamDriver, name), name
|