Compare commits

...

2 commits

Author SHA1 Message Date
2b7e20493a [FIX] script qemu: boot VMs via UEFI (Debian 13 boot loop)
Debian 13 (trixie) genericcloud dropped the BIOS/GRUB-pc bootloader, so
SeaBIOS looped forever on "Booting Debian GNU/Linux" and the install
never completed. Boot via UEFI (OVMF) by default: trixie boots, and
Ubuntu/Debian 12/Fedora keep working (verified Debian 13 and Ubuntu
24.04 end to end). Add a --bios opt-out for hosts without OVMF, and pull
the UEFI firmware (ovmf / edk2-ovmf) with the libvirt/QEMU stack. VM
deletion already removes the nvram (undefine --nvram).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 09:53:21 +00:00
79c69fb6d5 [FIX] script qemu: avoid --osinfo generic for versions newer than osinfo-db
When the exact osinfo id is missing from the local osinfo-db (e.g.
ubuntu26.04, fedora43/44), the fallback was detect=on,require=off, which
made virt-install fall back to "generic" and warn "VM performance may
suffer". Fall back instead to the latest KNOWN osinfo of the same distro
(ubuntu26.04 -> ubuntu25.10, fedora44 -> fedora42): proper virtio/OS
defaults, no warning. detect=on,require=off remains only if nothing of
the family is known.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 09:41:21 +00:00

View file

@ -219,15 +219,28 @@ def osinfo_known(short_id: str) -> bool:
return False
def osinfo_arg(osinfo: str) -> str:
"""Valeur --osinfo résiliente à un osinfo-db périmé : si l'id est connu on
l'utilise ; sinon on bascule en détection best-effort au lieu d'échouer
(utile pour une distro plus récente que la base locale, ex. ubuntu26.04,
fedora43+)."""
def osinfo_arg(osinfo: str, distro: str = "") -> str:
"""Valeur --osinfo résiliente à un osinfo-db périmé. Si l'id est connu on
l'utilise ; sinon on retombe sur le DERNIER osinfo connu de la même distro
(meilleures perfs que « generic », pas d'avertissement) ; en dernier
recours, détection best-effort. Utile pour une version plus récente que la
base locale (ex. ubuntu26.04, fedora43+)."""
if "=" in osinfo or "," in osinfo:
return osinfo # forme avancée déjà fournie par l'utilisateur
if osinfo_known(osinfo):
return osinfo
# Repli 1 : dernier osinfo connu de la même distro (ordre de la table).
versions = DISTROS.get(distro, ({}, ""))[0]
known = [v[1] for v in versions.values() if osinfo_known(v[1])]
if known:
fallback = known[-1]
print(
f" osinfo « {osinfo} » inconnu (osinfo-db) — repli sur "
f"« {fallback} » (proche). « sudo apt upgrade osinfo-db » pour "
"l'entrée exacte."
)
return fallback
# Repli 2 : détection best-effort (évite l'échec, peut donner generic).
print(
f" osinfo « {osinfo} » inconnu de la base locale (osinfo-db) — repli "
"sur la détection auto (detect=on,require=off).\n"
@ -347,11 +360,18 @@ TOOL_PACKAGES: dict[str, dict[str, str]] = {
# Paquets fournissant le démon libvirt + l'émulateur QEMU système. Ils sont
# INDISPENSABLES pour exécuter la VM : virsh/virt-install (clients) seuls ne
# créent pas le socket /var/run/libvirt/libvirt-sock.
# On inclut le firmware UEFI (OVMF/edk2) : le boot par défaut est UEFI
# (indispensable pour Debian 13+ ; les images récentes n'ont plus de BIOS).
DAEMON_PACKAGES: dict[str, list[str]] = {
"apt": ["libvirt-daemon-system", "qemu-system-x86"],
"dnf": ["libvirt-daemon-kvm", "qemu-kvm"],
"pacman": ["libvirt", "qemu-desktop", "dnsmasq"],
"zypper": ["libvirt-daemon", "libvirt-daemon-qemu", "qemu-kvm"],
"apt": ["libvirt-daemon-system", "qemu-system-x86", "ovmf"],
"dnf": ["libvirt-daemon-kvm", "qemu-kvm", "edk2-ovmf"],
"pacman": ["libvirt", "qemu-desktop", "dnsmasq", "edk2-ovmf"],
"zypper": [
"libvirt-daemon",
"libvirt-daemon-qemu",
"qemu-kvm",
"qemu-ovmf-x86_64",
],
"brew": [],
}
@ -964,6 +984,12 @@ def virt_install(
"--console",
"pty,target_type=serial",
]
# Boot UEFI par défaut : Debian 13 (trixie) et les images cloud récentes
# n'embarquent plus le chargeur BIOS/GRUB-pc et partent en boucle
# « Booting... » en SeaBIOS. UEFI (OVMF) fonctionne pour Ubuntu/Debian/
# Fedora. --bios force l'ancien BIOS si OVMF est indisponible.
if not args.bios:
cmd += ["--boot", "uefi"]
if not args.attach_console:
cmd.append("--noautoconsole")
runner.run(cmd, privileged=True)
@ -1114,6 +1140,12 @@ def build_parser() -> argparse.ArgumentParser:
action="store_true",
help="Attache la console série (sinon --noautoconsole).",
)
g_vm.add_argument(
"--bios",
action="store_true",
help="Force l'amorçage BIOS hérité au lieu d'UEFI (par défaut UEFI ; "
"n'utiliser que si le firmware OVMF est absent).",
)
g_cloud = p.add_argument_group("cloud-init")
g_cloud.add_argument(
@ -1354,7 +1386,7 @@ def main() -> None:
cloud_cfg = build_cloud_config(args, pw_hash, ssh_keys)
build_seed(cloud_cfg, args.hostname, seed, runner)
resolved_osinfo = osinfo_arg(osinfo)
resolved_osinfo = osinfo_arg(osinfo, args.distro)
print(f"\n== 5/5 virt-install (--osinfo {resolved_osinfo}) ==")
ensure_network(network_name(args.network), runner)
virt_install(args, disk, seed, resolved_osinfo, runner)