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

fix(instances): a new VM's CPU is a mode or a model the host offers, checked by libvirt

- A named CPU model is written without check='none' and with
  fallback='forbid': libvirt checks before the start that the host runs
  it, and it is not swapped for another model.
- Mode maximum is written as that mode; it was written as a model named
  maximum.
- Model names up to 64 characters: the -noTSX and -IBRS models, the ones a
  mixed set of hosts needs, were refused at 20.
- The mode or model is checked against the host's capabilities when the VM
  is defined, from the page and the API alike; no CPU element (QEMU's
  oldest default CPU) is no longer offered.
- The default CPU mode setting offers the modes the new VM dialog has;
  no-model and custom, which matched none of them, become host-model.
This commit is contained in:
catborise 2026-10-29 10:50:20 +03:00
parent 2a773f6ec0
commit 2e1f29961c
15 changed files with 139 additions and 19 deletions

View file

@ -0,0 +1,25 @@
from django.db import migrations
CHOICES = "host-model,host-passthrough,maximum"
def fix_cpu_mode(apps, schema_editor):
"""The CPU modes a new VM can have: no-model and custom matched no choice
of the new VM dialog, which then showed another one. Not undone on the way
back, as nothing needs the old choices."""
AppSettings = apps.get_model("appsettings", "AppSettings")
for setting in AppSettings.objects.using(schema_editor.connection.alias).filter(key="INSTANCE_CPU_DEFAULT_MODE"):
setting.choices = CHOICES
if setting.value not in CHOICES.split(","):
setting.value = "host-model"
setting.save()
class Migration(migrations.Migration):
dependencies = [
("appsettings", "0021_setting_descriptions"),
]
operations = [
migrations.RunPython(fix_cpu_mode, migrations.RunPython.noop),
]

View file

@ -99,3 +99,17 @@ class DescriptionsTestCase(TestCase):
with self.subTest(key=key):
self.assertLessEqual(len(text), limit)
self.assertEqual(AppSettings.objects.get(key=key).description, text)
cpu_mode = importlib.import_module("appsettings.migrations.0022_cpu_mode_choices")
class CpuModeChoicesTestCase(TestCase):
def test_the_default_cpu_mode_is_one_the_new_vm_dialog_offers(self):
for old, new in (("no-model", "host-model"), ("custom", "host-model"), ("host-passthrough", "host-passthrough")):
with self.subTest(old=old):
AppSettings.objects.filter(key="INSTANCE_CPU_DEFAULT_MODE").update(
value=old, choices="no-model,host-model,host-passthrough,custom")
cpu_mode.fix_cpu_mode(apps, SimpleNamespace(connection=connection))
setting = AppSettings.objects.get(key="INSTANCE_CPU_DEFAULT_MODE")
self.assertEqual((setting.value, setting.choices), (new, "host-model,host-passthrough,maximum"))