1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
webvirtcloud/vrtManager/test_util.py
catborise 03ac93ea53 fix(instances): CD-ROM bus, USB controller and MACs of a new VM
Creating each option on a RHEL qemu-kvm host showed:

- CD-ROM: the create page offered every disk bus, but the empty CD-ROM
  of a new VM works only on ide, sata and scsi. fdc and virtio failed
  ("Invalid bus type", "does not support ejectable media"), usb failed
  with a device named 'Nonea' because vol_dev_type() had no prefix for
  usb, and after that libvirt refuses an empty usb disk. Only ide, sata
  and scsi are offered now, and another value is refused before any
  storage is allocated. vol_dev_type() names usb disks sdX, which also
  fixes data volumes on the usb bus.
- USB controller: any input device added a bare <controller
  type='usb'/>, which libvirt turns into piix3-uhci (USB 1.1) on q35
  instead of its default qemu-xhci. The bare controller is gone; libvirt
  adds the machine's default for USB inputs.
- MACs: with more networks than MAC addresses, create_instance indexed
  past the list and the request failed with a 500. NICs without a given
  MAC now get one from libvirt. MAC addresses are validated (format, not
  more than networks) by the page and the API before anything is
  created; they went into the XML unchecked.

Unit tests cover the refused values, the MAC rule and the usb prefix.
Live tests create a VM with every offered CD-ROM bus and start it,
check the USB controller with a USB input device and create a VM with
two networks and one MAC.
2026-10-04 18:33:28 +03:00

149 lines
5.3 KiB
Python

import unittest
from django.conf import settings
if not settings.configured:
settings.configure(MAC_OUI="52:54:10")
from vrtManager.util import (
compareMAC,
get_xml_path,
is_kvm_available,
pretty_bytes,
pretty_mem,
randomMAC,
randomPasswd,
randomUUID,
validate_macaddr,
validate_uuid,
vol_dev_type,
xml_escape,
)
class TestVrtManagerUtil(unittest.TestCase):
def test_random_uuid_format(self):
uuid_str = randomUUID()
# UUIDv4 format check
pattern = r"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
self.assertRegex(uuid_str, pattern)
# Ensure successive UUIDs are distinct
self.assertNotEqual(uuid_str, randomUUID())
def test_validate_uuid(self):
valid_dashed = "c9a646d3-9c61-4cd8-8024-f6b72a6642d9"
self.assertEqual(validate_uuid(valid_dashed), valid_dashed)
valid_no_dash = "c9a646d39c614cd88024f6b72a6642d9"
self.assertEqual(validate_uuid(valid_no_dash), valid_dashed)
with self.assertRaises(ValueError):
validate_uuid("invalid-uuid-too-short")
with self.assertRaises(ValueError):
validate_uuid(12345)
def test_random_mac(self):
mac = randomMAC()
self.assertTrue(mac.startswith("52:54:10:"))
parts = mac.split(":")
self.assertEqual(len(parts), 6)
for part in parts:
self.assertEqual(len(part), 2)
int(part, 16) # valid hex
def test_compare_mac(self):
mac1 = "52:54:10:00:00:01"
mac2 = "52:54:10:00:00:02"
self.assertEqual(compareMAC(mac1, mac1), 0)
self.assertEqual(compareMAC(mac1, mac2), -1)
self.assertEqual(compareMAC(mac2, mac1), 1)
# Different lengths
self.assertEqual(compareMAC("52:54", "52:54:10"), -1)
self.assertEqual(compareMAC("52:54:10", "52:54"), 1)
def test_validate_macaddr(self):
self.assertIsNone(validate_macaddr(None))
self.assertIsNone(validate_macaddr("52:54:10:aa:bb:cc"))
self.assertIsNone(validate_macaddr("0:1:2:3:4:5"))
with self.assertRaises(ValueError):
validate_macaddr("invalid_mac")
with self.assertRaises(ValueError):
validate_macaddr(12345)
def test_random_passwd(self):
pwd = randomPasswd(16)
self.assertEqual(len(pwd), 16)
# Custom alphabet
numeric_pwd = randomPasswd(10, alphabet="0123456789")
self.assertEqual(len(numeric_pwd), 10)
self.assertTrue(numeric_pwd.isdigit())
def test_xml_escape(self):
self.assertIsNone(xml_escape(None))
escaped = xml_escape('<foo name="bar" test=\'baz\' &/>')
self.assertEqual(escaped, "&lt;foo name=&quot;bar&quot; test=&apos;baz&apos; &amp;/&gt;")
def test_get_xml_path(self):
xml = "<domain type='kvm'><name>testvm</name><memory unit='KiB'>1048576</memory></domain>"
self.assertEqual(get_xml_path(xml, "/domain/name"), "testvm")
self.assertEqual(get_xml_path(xml, "/domain/memory"), "1048576")
self.assertEqual(get_xml_path(xml, "/domain/@type"), "kvm")
# Function callback mode
def extract_name(doc):
return doc.xpath("/domain/name")[0].text
self.assertEqual(get_xml_path(xml, func=extract_name), "testvm")
# Missing both path and func
with self.assertRaises(ValueError):
get_xml_path(xml)
def test_is_kvm_available(self):
kvm_xml = "<capabilities><guest><arch name='x86_64'><domain type='kvm'/></arch></guest></capabilities>"
qemu_xml = "<capabilities><guest><arch name='x86_64'><domain type='qemu'/></arch></guest></capabilities>"
self.assertTrue(is_kvm_available(kvm_xml))
self.assertFalse(is_kvm_available(qemu_xml))
def test_pretty_mem(self):
# Value in KB
self.assertEqual(pretty_mem(1024), " 1 MB")
self.assertEqual(pretty_mem(1024 * 1024), "1024 MB")
self.assertEqual(pretty_mem(16 * 1024 * 1024), "16.00 GB")
def test_pretty_bytes(self):
# Value in Bytes
self.assertEqual(pretty_bytes(10 * 1024 * 1024), "10.00 MB")
self.assertEqual(pretty_bytes(2 * 1024 * 1024 * 1024), "2.00 GB")
def test_vol_dev_type(self):
self.assertEqual(vol_dev_type("ide"), "hd")
self.assertEqual(vol_dev_type("fdc"), "fd")
self.assertEqual(vol_dev_type("virtio"), "vd")
self.assertEqual(vol_dev_type("usb"), "sd")
self.assertEqual(vol_dev_type("scsi"), "sd")
self.assertEqual(vol_dev_type("sata"), "sd")
self.assertIsNone(vol_dev_type("unknown_bus"))
class OperationErrorTestCase(unittest.TestCase):
def test_keeps_its_own_message_after_a_libvirt_failure(self):
import libvirt
from vrtManager.util import OperationError
conn = libvirt.open("test:///default")
self.addCleanup(conn.close)
with self.assertRaises(libvirt.libvirtError):
conn.lookupByName("no-such-domain") # leaves a thread-local last error
self.assertNotEqual(str(libvirt.libvirtError("own message")), "own message")
error = OperationError("own message")
self.assertEqual(str(error), "own message")
self.assertIsInstance(error, libvirt.libvirtError)
if __name__ == "__main__":
unittest.main()