1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/instances/tests/test_create_rollback.py
catborise 005fa59bf0 feat(instances): a new VM can have UEFI Secure Boot and a TPM 2.0
Windows 11 does not install without Secure Boot and a TPM 2.0, and the new
VM form offered neither: its firmware list was BIOS and one UEFI loader
guessed from file names, which on RHEL never matched the Secure Boot one.

The firmware choices are now BIOS, UEFI and UEFI Secure Boot, as the
host's libvirt reports them (its firmware features from libvirt 12.1,
before that its loaders), and libvirt picks the firmware itself: UEFI
without Secure Boot, or with Microsoft's keys enrolled. A TPM 2.0 switch,
shown when the host has swtpm, adds an emulated TPM. The create job
refuses a firmware or a TPM the host does not offer, and the API takes
both. The path-guessing helpers are gone.
2026-11-01 16:18:29 +03:00

58 lines
2.7 KiB
Python

from types import SimpleNamespace
from unittest.mock import patch
from appsettings.settings import get_settings
from computes.models import Compute
from django.contrib.auth import get_user_model
from django.test import TestCase
from libvirt import libvirtError
from instances.jobs import CreateInstance
from operations import jobs
from operations.jobs import Context
from operations.models import Operation, acquire
PARAMS = {
"name": "rb-vm", "firmware": "BIOS", "vcpu": 1, "vcpu_mode": "host-model", "memory": 128,
"hdd_size": 1, "storage": "default", "mac": "52:54:00:aa:04:01", "networks": "default",
"nwfilter": "", "net_model": "virtio", "cache_mode": "none", "video": "vga",
"listener_addr": "0.0.0.0", "add_cdrom": "None", "add_input": "None", "virtio": True, "qemu_ga": False,
"arch": "x86_64", "machine": "q35",
}
class CreateRollbackTestCase(TestCase):
"""Volumes are removed only while the VM is not defined yet."""
def setUp(self):
get_settings()
self.admin = get_user_model().objects.create_superuser("rb_admin", "r@example.com", "pw")
self.compute = Compute.objects.create(name="rb", hostname="192.0.2.41", login="", password="", type=4)
def run_job(self, **conn_setup):
with patch("instances.jobs.wvmCreate") as wvm:
conn = wvm.return_value
conn.get_cache_modes.return_value = {"none": "Disable cache"}
conn.get_firmwares.return_value = ["BIOS", "UEFI", "UEFI Secure Boot"]
conn.get_dom_capabilities.return_value = {"cpu_modes": ["host-model"]}
conn.get_instances.return_value = []
conn.create_volume.return_value = "/pool/rb-vm.qcow2"
op = jobs.submit("instance.create", self.admin, {**PARAMS, "compute": self.compute.pk}, "key-rollback1")
acquire("wvc-test:1:a", "wvc-test")
Operation.objects.filter(pk=op.pk).update(state=Operation.RUNNING, worker="wvc-test:1:a")
op.refresh_from_db()
for attr, value in conn_setup.items():
getattr(conn, attr).side_effect = value
with self.assertRaises(Exception):
CreateInstance().run(op, Context(op, SimpleNamespace(identity="wvc-test:1:a")))
return conn
def test_failed_definition_removes_the_new_volume(self):
conn = self.run_job(create_instance=libvirtError("rejected"))
conn.delete_volume.assert_called_once_with("/pool/rb-vm.qcow2")
def test_failure_after_the_definition_keeps_the_volume(self):
with patch("instances.jobs.Instance.objects.get_or_create", side_effect=RuntimeError("db down")):
conn = self.run_job()
conn.create_instance.assert_called_once()
conn.delete_volume.assert_not_called()