mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-10 12:16:49 +00:00
fix(interfaces): deleting a bridge keeps the devices it held
With the netcf backend (RHEL/AlmaLinux 8), undefining a bridge also removes its members' configuration: the device came back without any after a reboot. Like virsh iface-unbridge, each member is now defined again on its own after the bridge is undefined, with the bridge's start mode and, when it is the only member, its addresses. A bond keeps its mode and devices. Checked on AlmaLinux 8 (libvirt 8.0, netcf): an ethernet and a bond member get their ifcfg back, and the bond comes up with the address after a reboot.
This commit is contained in:
parent
7526e9ab32
commit
28a73519d7
3 changed files with 53 additions and 0 deletions
44
interfaces/tests/test_delete.py
Normal file
44
interfaces/tests/test_delete.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"""Deleting a host interface: netcf removes a bridge's members with the
|
||||
bridge, so they are defined again on their own (as virsh iface-unbridge)."""
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from lxml import etree
|
||||
from vrtManager.interface import wvmInterface
|
||||
|
||||
ADDRESS = "<protocol family='ipv4'><ip address='192.0.2.10' prefix='24'/></protocol>"
|
||||
BOND = "<interface type='bond' name='bond0'><bond mode='active-backup'><interface type='ethernet' name='eth1'/></bond></interface>"
|
||||
|
||||
|
||||
def delete(xml):
|
||||
conn = wvmInterface.__new__(wvmInterface)
|
||||
conn.iface = MagicMock()
|
||||
conn.iface.XMLDesc.return_value = xml
|
||||
conn.wvm = MagicMock()
|
||||
conn.delete_iface()
|
||||
conn.iface.undefine.assert_called_once_with()
|
||||
return [etree.fromstring(call.args[0]) for call in conn.wvm.interfaceDefineXML.call_args_list]
|
||||
|
||||
|
||||
class DeleteInterfaceTestCase(SimpleTestCase):
|
||||
def test_the_only_member_takes_the_bridge_start_mode_and_addresses(self):
|
||||
(bond,) = delete(f"<interface type='bridge' name='br1'><start mode='onboot'/>{ADDRESS}<bridge>{BOND}</bridge></interface>")
|
||||
self.assertEqual(bond.get("name"), "bond0")
|
||||
self.assertEqual(bond.xpath("bond/@mode"), ["active-backup"])
|
||||
self.assertEqual(bond.xpath("bond/interface/@name"), ["eth1"])
|
||||
self.assertEqual(bond.xpath("start/@mode"), ["onboot"])
|
||||
self.assertEqual(bond.xpath("protocol/ip/@address"), ["192.0.2.10"])
|
||||
|
||||
def test_several_members_take_the_start_mode_but_no_address(self):
|
||||
members = delete(
|
||||
f"<interface type='bridge' name='br1'><start mode='onboot'/>{ADDRESS}<bridge>"
|
||||
"<interface type='ethernet' name='eth1'/><interface type='ethernet' name='eth2'/></bridge></interface>"
|
||||
)
|
||||
self.assertEqual([m.get("name") for m in members], ["eth1", "eth2"])
|
||||
for member in members:
|
||||
self.assertEqual(member.xpath("start/@mode"), ["onboot"])
|
||||
self.assertEqual(member.xpath("protocol"), [])
|
||||
|
||||
def test_an_interface_that_is_not_a_bridge_is_only_undefined(self):
|
||||
self.assertEqual(delete(f"<interface type='ethernet' name='eth1'><start mode='onboot'/>{ADDRESS}</interface>"), [])
|
||||
Loading…
Add table
Add a link
Reference in a new issue