mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
Tests that build vrtManager objects and touch no view, form or model of an app lived in that app; vrtManager/tests already holds such tests, so the convention was split. They move to vrtManager/tests: the firmware, CPU mode and PCIe port definitions of a new VM (test_create), USB and PCI host devices, the console listener, host CPU reads, interface reads, deletes and XML, network filters, PCI passthrough rules, node devices, network changes, addresses and leases, pool XML, secrets, and the live tests that use vrtManager only (disk resize, ISO, snapshots, XML, live clone). livetest.py, the live-test helper six apps import, and the network test driver move with them. Others go to their app: the quota with a host down to instances, the 401/403 Logs rows (webvirtcloud's middleware) to webvirtcloud, the VM page's tab script test to instances, novncd's own tests out of the console views tests, the compute lock and input validation tests out of the computes views tests, the interface views out of the forms tests. instances/tests/test_views.py, entirely live, is test_live_views.py. Test modules imported fixtures from each other; shared ones are now in vrtManager/tests/fakes.py (migration fakes, node devices, IOMMU groups, leases, a NAT network, a Ceph secret), interfaces/tests/fakes.py, console/tests/daemons.py (novncd loaded once), livetest.wait_for and instances/tests/create_page.BODY. Every live test checks livetest.enabled(). The suite runs the same 2097 tests.
119 lines
7.4 KiB
Python
119 lines
7.4 KiB
Python
"""What the panel reads of the host's interfaces: each one's XML once, its
|
|
link as reported (an unknown speed is none), its members; which devices a new
|
|
bridge can take; how each family is addressed."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import libvirt
|
|
from django.test import SimpleTestCase
|
|
from vrtManager.interface import wvmInterface, wvmInterfaces
|
|
|
|
BRIDGE = ("<interface type='bridge' name='br0'><mtu size='1500'/><link speed='4294967295' state='up'/>"
|
|
"<mac address='52:54:00:aa:01:02'/><bridge stp='on' delay='0'>"
|
|
"<interface type='ethernet' name='eno1'><link speed='1000' state='up'/><mac address='52:54:00:aa:01:03'/></interface>"
|
|
"</bridge></interface>")
|
|
ETHERNET = "<interface type='ethernet' name='eno2'><link state='down'/><mac address='52:54:00:aa:01:04'/></interface>"
|
|
|
|
|
|
def iface(xml, active=1):
|
|
name = xml.split("name='")[1].split("'")[0]
|
|
mac = xml.split("mac address='")[1].split("'")[0]
|
|
return MagicMock(**{"name.return_value": name, "MACString.return_value": mac, "XMLDesc.return_value": xml,
|
|
"isActive.return_value": active})
|
|
|
|
|
|
def error(code):
|
|
err = libvirt.libvirtError("refused")
|
|
err.get_error_code = lambda: code
|
|
return err
|
|
|
|
|
|
class ReadTests(SimpleTestCase):
|
|
def interfaces(self, *xmls, networks=()):
|
|
conn = wvmInterfaces.__new__(wvmInterfaces)
|
|
conn.wvm = MagicMock(**{"listAllInterfaces.return_value": [iface(x) for x in xmls],
|
|
"listAllNetworks.return_value": [MagicMock(**{"XMLDesc.return_value": n}) for n in networks]})
|
|
return conn
|
|
|
|
def test_each_interface_is_read_once(self):
|
|
conn = self.interfaces(BRIDGE, ETHERNET)
|
|
br0, eno2 = conn.get_ifaces_info()
|
|
self.assertEqual((br0["type"], br0["link"], br0["speed"], br0["mtu"], br0["mac"]),
|
|
("bridge", "up", None, "1500", "52:54:00:aa:01:02"))
|
|
self.assertEqual(br0["members"], [{"name": "eno1", "type": "ethernet", "mac": "52:54:00:aa:01:03",
|
|
"link": "up", "speed": "1000"}])
|
|
self.assertEqual((eno2["link"], eno2["members"]), ("down", []))
|
|
for listed in conn.wvm.listAllInterfaces.return_value:
|
|
# name and MAC are held by libvirt's object: no call to the host
|
|
self.assertEqual([c[0] for c in listed.mock_calls], ["XMLDesc", "name", "MACString", "isActive"])
|
|
|
|
def test_an_interface_libvirt_cannot_write_is_read_as_saved(self):
|
|
# netcf writes a link speed of -1 for a virtio card, then refuses that XML
|
|
listed = iface(ETHERNET)
|
|
listed.XMLDesc.side_effect = lambda flags=0: ETHERNET if flags else (_ for _ in ()).throw(error(libvirt.VIR_ERR_XML_ERROR))
|
|
conn = self.interfaces()
|
|
conn.wvm.listAllInterfaces.return_value = [listed]
|
|
(eno2,) = conn.get_ifaces_info()
|
|
self.assertEqual(eno2["name"], "eno2")
|
|
|
|
def test_a_bridge_takes_no_bridge_member_network_bridge_or_tap(self):
|
|
# as configured: a member the running bridge does not have yet is taken too
|
|
conn = self.interfaces(BRIDGE, ETHERNET, networks=["<network><bridge name='virbr0'/></network>"])
|
|
self.assertEqual(conn.get_member_candidates(["br0", "eno1", "eno2", "lo", "virbr0", "vnet3", "macvtap0"]), ["eno2"])
|
|
for listed in conn.wvm.listAllInterfaces.return_value:
|
|
listed.XMLDesc.assert_called_with(libvirt.VIR_INTERFACE_XML_INACTIVE)
|
|
|
|
def test_a_device_in_a_bond_of_a_bridge_is_taken(self):
|
|
nested = ("<interface type='bridge' name='br1'><mac address='52:54:00:aa:01:05'/><bridge><interface type='bond' name='bond0'><bond>"
|
|
"<interface type='ethernet' name='eno3'/><interface type='ethernet' name='eno4'/></bond></interface>"
|
|
"</bridge></interface>")
|
|
conn = self.interfaces(nested)
|
|
self.assertEqual(conn.get_member_candidates(["br1", "bond0", "eno3", "eno4", "eno5"]), ["eno5"])
|
|
|
|
def test_each_family_says_how_it_is_addressed(self):
|
|
conn = wvmInterface.__new__(wvmInterface)
|
|
saved = ("<interface type='ethernet' name='eth0'><start mode='onboot'/>"
|
|
"<protocol family='ipv4'><ip address='198.51.100.10' prefix='24'/></protocol>"
|
|
"<protocol family='ipv6'><autoconf/></protocol></interface>")
|
|
running = ("<interface type='ethernet' name='eth0'><protocol family='ipv4'><ip address='198.51.100.10' prefix='24'/></protocol>"
|
|
"<protocol family='ipv6'><ip address='2001:db8::5' prefix='64'/><ip address='2001:db8::6' prefix='64'/></protocol></interface>")
|
|
conn.iface = MagicMock(**{"name.return_value": "eth0", "MACString.return_value": "52:54:00:00:00:01",
|
|
"XMLDesc.side_effect": lambda flags=0: saved if flags else running})
|
|
info = conn.get_info()
|
|
self.assertEqual(info["start_mode"], "onboot")
|
|
self.assertEqual(info["ipv4"], {"method": "static", "addresses": ["198.51.100.10/24"]})
|
|
self.assertEqual(info["ipv6"], {"method": "autoconf", "addresses": ["2001:db8::5/64", "2001:db8::6/64"]})
|
|
self.assertEqual(conn.iface.XMLDesc.call_count, 2) # the running and the saved definition, once each
|
|
|
|
def test_an_address_without_a_prefix_is_shown_without_one(self):
|
|
conn = wvmInterface.__new__(wvmInterface)
|
|
xml = "<interface type='ethernet' name='eth0'><protocol family='ipv4'><ip address='192.0.2.10'/></protocol></interface>"
|
|
conn.iface = MagicMock(**{"name.return_value": "eth0", "MACString.return_value": "", "XMLDesc.return_value": xml})
|
|
self.assertEqual(conn.get_info()["ipv4"]["addresses"], ["192.0.2.10"])
|
|
|
|
|
|
class BridgeUseTests(SimpleTestCase):
|
|
def test_networks_and_running_vms_on_a_bridge(self):
|
|
from vrtManager.interface import networks_by_device
|
|
|
|
nets = [MagicMock(**{"name.return_value": name, "XMLDesc.return_value": xml}) for name, xml in (
|
|
("default", "<network><bridge name='virbr0'/></network>"),
|
|
("lan", "<network><forward mode='bridge'/><bridge name='br0'/></network>"),
|
|
("direct", "<network><forward mode='bridge'><interface dev='eth0'/><interface dev='eth1'/></forward></network>"),
|
|
("sriov", "<network><forward mode='hostdev'><pf dev='eth2'/></forward></network>"))]
|
|
self.assertEqual(networks_by_device(MagicMock(**{"listAllNetworks.return_value": nets})),
|
|
{"virbr0": ["default"], "br0": ["lan"], "eth0": ["direct"], "eth1": ["direct"], "eth2": ["sriov"]})
|
|
doms = [MagicMock(**{"name.return_value": name, "XMLDesc.return_value": xml}) for name, xml in (
|
|
("web", "<domain><devices><interface type='bridge'><mac address='52:54:00:00:00:01'/><source bridge='br0'/>"
|
|
"<target dev='vnet3'/></interface></devices></domain>"),
|
|
("db", "<domain><devices><interface type='network'><mac address='52:54:00:00:00:02'/><source network='lan'/>"
|
|
"<target dev='vnet7'/></interface></devices></domain>"),
|
|
("other", "<domain><devices><interface type='network'><source network='default'/><target dev='vnet9'/>"
|
|
"</interface></devices></domain>"))]
|
|
conn = wvmInterface.__new__(wvmInterface)
|
|
conn.iface = MagicMock(**{"name.return_value": "br0"})
|
|
conn.wvm = MagicMock(**{"listAllDomains.return_value": doms})
|
|
self.assertEqual(conn.get_vms(["lan"]), [
|
|
{"vm": "db", "tap": "vnet7", "mac": "52:54:00:00:00:02"},
|
|
{"vm": "web", "tap": "vnet3", "mac": "52:54:00:00:00:01"},
|
|
])
|