1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00

fix(instances): a running VM's QoS edit keeps the pending QoS changes

The QoS table showed the running VM's bandwidth while an edit changes the
definition for the next start. Each row posts average, peak and burst,
so an edit wrote the running values back over a pending change, and a
direction added while the VM ran had no row. The table shows the
persistent definition now. An edit also kept only the posted values and
dropped an inbound floor; it now updates them and keeps the rest.
This commit is contained in:
catborise 2026-10-10 22:59:14 +03:00
parent 8d2c9b1217
commit ea9424ee1f
8 changed files with 62 additions and 22 deletions

View file

@ -1979,9 +1979,9 @@ class wvmInstance(wvmConnect):
def set_memory(self, size, flags=0):
self.instance.setMemoryFlags(size, flags)
def get_all_qos(self):
def get_all_qos(self, config=False):
qos_values = dict()
tree = etree.fromstring(self._XMLDesc(0))
tree = etree.fromstring(self._XMLDesc(PERSISTENT_XML if config else 0))
qos = tree.xpath("/domain/devices/interface")
for q in qos:
@ -2029,10 +2029,7 @@ class wvmInstance(wvmConnect):
peak = int(peak)
burst = int(burst)
if direction == "inbound":
xml = f"<inbound average='{average}' peak='{peak}' burst='{burst}'/>"
else:
xml = f"<outbound average='{average}' peak='{peak}' burst='{burst}'/>"
xml = f"<{direction} average='{average}' peak='{peak}' burst='{burst}'/>"
tree = etree.fromstring(self._XMLDesc(PERSISTENT_XML))
@ -2048,9 +2045,8 @@ class wvmInstance(wvmConnect):
else:
direct = band.find(direction)
if direct is not None:
parent = direct.getparent()
parent.remove(direct)
parent.append(etree.fromstring(xml))
# keep what the form does not post (an inbound floor)
direct.attrib.update(etree.fromstring(xml).attrib)
else:
band.append(etree.fromstring(xml))
new_xml = etree.tostring(tree).decode()

View file

@ -1,6 +1,6 @@
"""Device edits of a VM: each definition is changed as it describes the
device, every NIC type can be a boot device, posted values stay values, and
definition changes go through _defineXML. An active VM's memory is resized
definition changes go through _defineXML, a QoS edit keeps the floor. An active VM's memory is resized
by balloon, a stopped one's in its definition. Enabling vCPU hot plug keeps
the vCPUs enabled at boot."""
@ -23,7 +23,7 @@ PERSISTENT = """<domain><os><type>hvm</type></os><devices>
<disk type='file' device='disk'><source file='/pool/b.qcow2'/><target dev='vdb' bus='virtio'/></disk>
<interface type='bridge'><mac address='52:54:10:00:00:02'/><source bridge='br0'/></interface>
<interface type='network'><mac address='52:54:10:00:00:01'/><source network='default'/>
<bandwidth><inbound average='1' peak='2' burst='3'/></bandwidth></interface>
<bandwidth><inbound average='1' peak='2' burst='3' floor='4'/></bandwidth></interface>
<video><model type='vga'/></video>
</devices></domain>"""
LIVE = """<domain><devices>
@ -107,6 +107,14 @@ class DeviceEditsTestCase(unittest.TestCase):
p._defineXML.assert_called_once()
p.wvm.defineXML.assert_not_called()
def test_qos_is_read_from_either_definition_and_an_edit_keeps_the_floor(self):
p = proxy()
self.assertEqual(p.get_all_qos(config=True)["52:54:10:00:00:01"][0]["floor"], "4")
self.assertEqual(p.get_all_qos(), {}) # the running VM has none
p.set_qos("52:54:10:00:00:01", "inbound", 10, 20, 30)
inbound = defined(p).find("devices/interface[@type='network']/bandwidth/inbound")
self.assertEqual(inbound.attrib, {"average": "10", "peak": "20", "burst": "30", "floor": "4"})
def test_the_default_nic_model_leaves_the_choice_to_libvirt(self):
p = proxy()
p.change_network("52:54:10:00:00:01", "52:54:10:00:00:01", "default", "net", "default", "")