Files
napalm-proxmox/tests/test_connection.py
Christian Manivong 20fcf2ebc3 fix: four real defects the fourteen failing tests were pointing at
Closes netork#115.

The suite had been red long enough that it stopped being read. Four of the
fourteen failures were the tests being right.

`interfaces_mixin.py` used `re.match` without importing `re`, so
`get_mac_address_table` raised NameError against any node with a Linux bridge.
The tests never reached that line: they mocked the API call underneath
`_exec_ssh_command`, which takes two positional arguments where the doubles
accepted one, and which base64-wraps the command — so a fixture keyed on
"bridge fdb" appearing in the text matched nothing and the helper returned "".
They mock `_exec_ssh_command` itself now, which is the driver's own seam.

`is_alive` called `_resolve_node()`, which returns early without touching the
API whenever a node was configured through optional_args. A dead connection
reported itself alive. It probes `GET /version` now.

The documented `realm` optional_arg was read into `self._realm` in `__init__`
and then never used. Proxmox authenticates against "<user>@<realm>" and rejects
a bare username, so the option had no effect and callers had to know to type the
realm themselves.

`get_vlans` filtered out entries with no member ports on one return path while
the OVS path returned them, so a configured SDN VNet was visible or invisible
depending on which branch ran. A VNet exists on the node whether or not anything
is attached to it, and netOrk's VLAN discovery reads this.

`get_ipv6_neighbors_table` was simply missing and fell through to NAPALM's stub;
it is implemented against `ip -6 neigh show`, dropping FAILED entries.

The rest were stale tests. The DNS fixture put an FQDN where a search domain
belongs, which made `get_facts` build "pve1.pve1.example.com" and look like a
driver bug. The LLDP fixture was a simplified shape that real `lldpcli show
neighbors summary` does not produce — the parser matches on the ", via: LLDP"
that follows the interface name. And `test_bridge_vlan_show_parsing` covered a
fallback that was replaced by VM-config scanning, asserting an "interfaces" key
this method has never returned; it is now a test of the fallback that exists.
2026-08-21 13:22:03 +07:00

79 lines
2.6 KiB
Python

"""Tests for ProxmoxDriver connection management."""
from __future__ import annotations
import pytest
from unittest.mock import MagicMock, patch
from napalm.base.exceptions import ConnectionException
from napalm_proxmox.driver import ProxmoxDriver
from tests.conftest import _build_mock_api, NODES_LIST
class TestOpen:
def test_open_password_auth(self):
drv = ProxmoxDriver("pve1", "root", "secret")
mock_api = _build_mock_api()
with patch("napalm_proxmox.driver.ProxmoxAPI", return_value=mock_api) as mock_cls:
drv.open()
call_kwargs = mock_cls.call_args.kwargs
assert call_kwargs["user"] == "root@pam"
assert call_kwargs["password"] == "secret"
def test_open_token_auth(self):
drv = ProxmoxDriver(
"pve1",
"root",
"",
optional_args={
"token_name": "napalm@pam!mytoken",
"token_value": "super-secret",
},
)
mock_api = _build_mock_api()
with patch("napalm_proxmox.driver.ProxmoxAPI", return_value=mock_api) as mock_cls:
drv.open()
call_kwargs = mock_cls.call_args.kwargs
# proxmoxer wants the two halves separately, not the combined
# "<user>!<tokenid>" string that Proxmox's UI displays.
assert call_kwargs["user"] == "napalm@pam"
assert call_kwargs["token_name"] == "mytoken"
assert call_kwargs["token_value"] == "super-secret"
def test_open_connection_error(self):
drv = ProxmoxDriver("badhost", "root", "bad")
with patch(
"napalm_proxmox.driver.ProxmoxAPI",
side_effect=Exception("Connection refused"),
):
with pytest.raises(ConnectionException):
drv.open()
def test_node_resolution_by_hostname(self, driver):
assert driver._node_name == "pve1"
def test_node_override_via_optional_args(self):
drv = ProxmoxDriver(
"pve1.example.com",
"root",
"secret",
optional_args={"node": "custom-node"},
)
mock_api = _build_mock_api()
with patch("napalm_proxmox.driver.ProxmoxAPI", return_value=mock_api):
drv.open()
assert drv._node_name == "custom-node"
def test_close(self, driver):
driver.close()
assert driver._api is None
class TestIsAlive:
def test_alive_when_api_responds(self, driver):
assert driver.is_alive() == {"is_alive": True}
def test_not_alive_when_api_fails(self, driver):
driver._api.version.get.side_effect = Exception("timeout")
assert driver.is_alive() == {"is_alive": False}