Files
napalm-proxmox/tests/test_sdn.py
T
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

104 lines
3.9 KiB
Python

"""Tests for SDN-related methods: get_vlans, get_network_instances."""
from __future__ import annotations
import pytest
from tests.conftest import _build_mock_api, SDN_ZONES, SDN_VNETS
class TestGetVlans:
def test_sdn_vnets_appear_as_vlans(self, driver):
result = driver.get_vlans()
# vnet0 tag=10, vnet1 tag=20
assert "10" in result
assert "20" in result
def test_vlan_name_is_vnet_id(self, driver):
result = driver.get_vlans()
assert result["10"]["name"] == "vnet0"
assert result["20"]["name"] == "vnet1"
def test_vlan_100000_for_vxlan(self, driver):
result = driver.get_vlans()
assert "100000" in result
def test_membership_derived_from_vm_configs(self, driver):
"""Without OVS ports, VLAN membership comes from each VM's netN config.
This replaces a test for a `bridge vlan show` fallback that no longer
exists — it also asserted an "interfaces" key this method has never
produced, so it could not have passed against any version of the code.
"""
node = driver._node_api()
node.qemu.get.return_value = [{"vmid": 100}]
node.lxc.get.return_value = []
node.qemu.return_value.config.get.return_value = {
"net0": "virtio=AA:BB:CC:DD:EE:FF,bridge=vmbr0,tag=10",
}
result = driver.get_vlans()
assert "vmbr0" in result["10"]["untagged"]
def test_configured_vnets_appear_even_without_members(self, driver):
"""An SDN VNet exists on the node whether or not anything is attached.
Entries with no member ports used to be filtered out of this one return
path while the OVS path returned them, so a configured VLAN was visible
or invisible depending on which branch ran.
"""
result = driver.get_vlans()
assert result["20"]["name"] == "vnet1"
assert result["20"]["untagged"] == []
def test_empty_sdn_returns_dict(self):
from unittest.mock import patch
from napalm_proxmox.driver import ProxmoxDriver
from tests.conftest import _build_mock_api
mock_api = _build_mock_api(sdn_vnets=[], sdn_zones=[])
drv = ProxmoxDriver("pve1", "root", "secret", optional_args={"verify_ssl": False})
with patch("napalm_proxmox.driver.ProxmoxAPI", return_value=mock_api):
drv.open()
result = drv.get_vlans()
assert isinstance(result, dict)
class TestGetNetworkInstances:
def test_default_instance_always_present(self, driver):
result = driver.get_network_instances()
assert "default" in result
assert result["default"]["type"] == "DEFAULT_INSTANCE"
def test_sdn_zones_as_instances(self, driver):
result = driver.get_network_instances()
assert "zone-vlan" in result
assert "zone-vxlan" in result
assert "zone-evpn" in result
def test_zone_type_mapping(self, driver):
result = driver.get_network_instances()
assert result["zone-vlan"]["type"] == "L2VPN"
assert result["zone-evpn"]["type"] == "L3VRF"
def test_vnet_appears_in_zone_interfaces(self, driver):
result = driver.get_network_instances()
zone_ifaces = result["zone-vlan"]["interfaces"]["interface"]
assert "vnet0" in zone_ifaces
assert "vnet1" in zone_ifaces
def test_filter_by_name(self, driver):
result = driver.get_network_instances(name="zone-vlan")
assert "zone-vlan" in result
assert "zone-vxlan" not in result
def test_evpn_route_distinguisher(self, driver):
result = driver.get_network_instances()
rd = result["zone-evpn"]["state"]["route_distinguisher"]
assert rd == 10001
def test_default_interfaces_include_node_ifaces(self, driver):
result = driver.get_network_instances()
default_ifaces = result["default"]["interfaces"]["interface"]
assert "eth0" in default_ifaces
assert "vmbr0" in default_ifaces