CI / test (3.10) (push) Successful in 24s
CI / test (3.11) (push) Successful in 24s
CI / test (3.12) (push) Successful in 24s
CI / test (3.10) (pull_request) Successful in 24s
CI / test (3.11) (pull_request) Successful in 23s
CI / test (3.12) (pull_request) Successful in 24s
fix_snmp hard-coded community "public". The driver implements napalm-device-types 4.13's configure_snmp_agent as a whole, because over REST a temporary SSH session has to run the config-mode CLI: community (read-only), contact and location from the caller, saved and verified in show snmp-server. The agent is built in and the switch filters nothing for its management plane; the steps say so instead of pretending. A value that would break the CLI is refused. The unused _detect_management_vlan goes with it. BREAKING CHANGE: run_device_action is removed. Part of #12 and #6 (the dead helper).
94 lines
3.0 KiB
Python
94 lines
3.0 KiB
Python
"""The SNMP agent through napalm-device-types' configure_snmp_agent (netOrk #1105).
|
|
|
|
fix_snmp hard-coded community "public". The switch's agent is built in and the
|
|
switch filters nothing for its own management plane, so of the template's steps
|
|
only "configure" (community, contact, location) and "start" (save, verify) do
|
|
work here; the caller's values are used as given.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
|
|
from napalm_procurve.procurve import ProcurveDriver
|
|
|
|
SETTINGS = {
|
|
"community": "c0mm",
|
|
"allowed_sources": ["10.7.224.20"],
|
|
"contact": "ops",
|
|
"location": "rack 1",
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def driver():
|
|
d = ProcurveDriver("10.0.0.40", "admin", "pw")
|
|
d._transport = "ssh"
|
|
d._device = MagicMock()
|
|
d.applied: list[str] = []
|
|
d._enter_config_mode = MagicMock()
|
|
d._exit_config_mode = MagicMock()
|
|
d._save_config = MagicMock()
|
|
d._apply_config_lines = lambda text: d.applied.append(text) or []
|
|
d._send_command = MagicMock(
|
|
return_value=" Community Name MIB View Write Access\n c0mm Manager Restricted\n"
|
|
)
|
|
return d
|
|
|
|
|
|
def test_community_contact_and_location_are_the_callers(driver):
|
|
result = driver.configure_snmp_agent(SETTINGS)
|
|
|
|
assert result["success"] is True
|
|
config = "\n".join(driver.applied)
|
|
assert 'snmp-server community "c0mm" manager restricted' in config
|
|
assert 'snmp-server contact "ops"' in config
|
|
assert 'snmp-server location "rack 1"' in config
|
|
assert "public" not in config
|
|
driver._save_config.assert_called_once()
|
|
|
|
|
|
def test_the_steps_say_what_the_switch_does_not_do(driver):
|
|
result = driver.configure_snmp_agent(SETTINGS)
|
|
|
|
steps = {s["step"]: s for s in result["steps"]}
|
|
assert list(steps) == ["install", "configure", "firewall", "start"]
|
|
assert "built in" in steps["install"]["output"]
|
|
assert "10.7.224.20" in steps["firewall"]["output"] # not enforced, and said so
|
|
|
|
|
|
def test_a_community_the_switch_does_not_show_afterwards_fails(driver):
|
|
driver._send_command.return_value = " Community Name MIB View\n public Manager\n"
|
|
|
|
assert driver.configure_snmp_agent(SETTINGS)["success"] is False
|
|
|
|
|
|
def test_a_rejected_line_fails_and_nothing_is_saved(driver):
|
|
driver._apply_config_lines = lambda text: ["Invalid input: community"]
|
|
|
|
result = driver.configure_snmp_agent(SETTINGS)
|
|
|
|
assert result["success"] is False
|
|
driver._save_config.assert_not_called()
|
|
|
|
|
|
@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.applied == []
|
|
|
|
|
|
def test_the_old_action_and_its_dead_helper_are_gone():
|
|
gone = (
|
|
"run_device_action",
|
|
"_action_fix_snmp",
|
|
"_action_fix_snmp_cli",
|
|
"_detect_management_vlan",
|
|
)
|
|
for name in gone:
|
|
assert not hasattr(ProcurveDriver, name), name
|