[FIX] qemu: reboot after the install upgrades the kernel, and fix virtinst cache
On a rolling distro every fresh development VM was born unable to create VMs. « make install_os » runs a full system upgrade, the kernel package is replaced and /lib/modules/<running kernel> disappears. modprobe bridge then fails and libvirt cannot create virbr0, so the « default » network stays inactive and virt-install dies on « network 'default' is not active » -- with every package correctly installed. Measured twice on a freshly created Arch VM: booted on 7.1.3-arch1-3 at 05:44, upgraded to 7.1.5.arch1-2 at 05:46. Only a reboot fixes it, and one is enough: the default network is already flagged autostart, so libvirt brings it up by itself once the modules match. --setup-host therefore gains --reboot-if-needed, used by the deployment profile. The reboot is scheduled through systemd-run --on-active=5 rather than issued immediately, otherwise it would kill the installer's SSH session and the orchestrator would report a failure for a VM that actually succeeded. Without the flag the behaviour is unchanged: explain and exit 1, which is what a workstation wants. Also fix « Error setting up logfile: No write access to /var/tmp/erplibre-virtinst/virt-manager »: that path was shared, so a first run under sudo created it as root and later non-root runs could not write. It is now per-UID. Verified on the Arch VM that failed: without the flag it exits 1 with the diagnosis; with it, the reboot is scheduled and the command still returns 0; after the reboot the kernel and modules match, « default » is active on its own and virbr0 exists. The cache directory is created as erplibre:erplibre 0700. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fba3b8aed1
commit
74ee584ffa
2 changed files with 60 additions and 4 deletions
|
|
@ -689,7 +689,30 @@ def kernel_modules_stale() -> str:
|
|||
)
|
||||
|
||||
|
||||
def setup_host(runner: Runner, assume_yes: bool, no_install: bool) -> None:
|
||||
def schedule_reboot(runner: Runner) -> None:
|
||||
"""Programme un redémarrage DIFFÉRÉ et détaché de la session courante.
|
||||
|
||||
Un « systemctl reboot » immédiat tuerait le SSH de l'installation, et
|
||||
l'orchestrateur compterait la VM en échec alors que tout s'est bien passé.
|
||||
On laisse donc quelques secondes pour que la commande distante rende la
|
||||
main proprement.
|
||||
"""
|
||||
if shutil.which("systemd-run"):
|
||||
runner.run(
|
||||
["systemd-run", "--on-active=5", "systemctl", "reboot"],
|
||||
privileged=True,
|
||||
check=False,
|
||||
)
|
||||
return
|
||||
runner.run(["shutdown", "-r", "+1"], privileged=True, check=False)
|
||||
|
||||
|
||||
def setup_host(
|
||||
runner: Runner,
|
||||
assume_yes: bool,
|
||||
no_install: bool,
|
||||
reboot_if_needed: bool = False,
|
||||
) -> None:
|
||||
"""Prépare l'hôte à faire tourner des VM : paquets, démon, groupe, réseau.
|
||||
|
||||
Point d'entrée unique du profil d'installation « ERPLibre Déploiement ».
|
||||
|
|
@ -725,6 +748,21 @@ def setup_host(runner: Runner, assume_yes: bool, no_install: bool) -> None:
|
|||
f"{'actif' if active else 'INACTIF'}"
|
||||
f" / {'autostart' if autostart else 'PAS autostart'}"
|
||||
)
|
||||
if not active and stale:
|
||||
# Le réseau est déjà « autostart » : après le redémarrage, libvirt le
|
||||
# monte tout seul avec les modules du nouveau noyau. Un seul reboot
|
||||
# suffit donc à rendre l'hôte utilisable, sans repasser par ici.
|
||||
if reboot_if_needed:
|
||||
print(
|
||||
"\n↻ Redémarrage programmé (dans quelques secondes) : c'est la"
|
||||
" SEULE façon de retrouver les modules du noyau.\n"
|
||||
" Au retour, le réseau « default » démarrera seul"
|
||||
" (autostart déjà actif)."
|
||||
)
|
||||
schedule_reboot(runner)
|
||||
return
|
||||
sys.exit(f"Erreur : l'hôte n'est pas prêt.\n {stale}")
|
||||
|
||||
if not (ok and active):
|
||||
sys.exit(
|
||||
"Erreur : l'hôte n'est pas prêt.\n"
|
||||
|
|
@ -1428,10 +1466,18 @@ def virt_install(
|
|||
# déverse un « Logging error » (le pavé « Fetched capabilities … »). On
|
||||
# force un cache/HOME ÉCRIVABLE via « env VAR=… » (traverse sudo) pour
|
||||
# que le journal s'écrive silencieusement.
|
||||
# Chemin propre à l'UID : un répertoire partagé finit créé par root lors
|
||||
# d'un premier passage sous sudo, puis devient illisible pour l'utilisateur
|
||||
# (« Error setting up logfile: No write access to … /virt-manager »).
|
||||
cache_dir = f"/var/tmp/erplibre-virtinst-{os.getuid()}"
|
||||
try:
|
||||
os.makedirs(cache_dir, mode=0o700, exist_ok=True)
|
||||
except OSError:
|
||||
pass
|
||||
log_env = [
|
||||
"env",
|
||||
"XDG_CACHE_HOME=/var/tmp/erplibre-virtinst",
|
||||
"HOME=/var/tmp/erplibre-virtinst",
|
||||
f"XDG_CACHE_HOME={cache_dir}",
|
||||
f"HOME={cache_dir}",
|
||||
]
|
||||
runner.run(log_env + cmd, privileged=True)
|
||||
|
||||
|
|
@ -1717,6 +1763,12 @@ def build_parser() -> argparse.ArgumentParser:
|
|||
help="Prépare l'hôte (paquets QEMU/libvirt, démon, groupe libvirt, "
|
||||
"réseau default) puis quitte. Ne déploie aucune VM.",
|
||||
)
|
||||
g_run.add_argument(
|
||||
"--reboot-if-needed",
|
||||
action="store_true",
|
||||
help="Avec --setup-host : redémarre si le noyau a été mis à jour "
|
||||
"depuis le démarrage (sinon libvirt ne peut pas créer virbr0).",
|
||||
)
|
||||
g_run.add_argument(
|
||||
"--list-images",
|
||||
action="store_true",
|
||||
|
|
@ -1773,6 +1825,7 @@ def main() -> None:
|
|||
),
|
||||
args.assume_yes,
|
||||
args.no_install_deps,
|
||||
args.reboot_if_needed,
|
||||
)
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -3078,7 +3078,10 @@ class TODO:
|
|||
# Sans le groupe, virt-install retombe sur qemu:///session où « default »
|
||||
# n'existe pas : la VM échoue alors que tous les paquets sont installés.
|
||||
# L'ancien one-liner finissait par « || true » et masquait ses erreurs.
|
||||
_QEMU_QEMU_PKGS = "./script/qemu/deploy_qemu.py --setup-host --assume-yes"
|
||||
_QEMU_QEMU_PKGS = (
|
||||
"./script/qemu/deploy_qemu.py --setup-host --assume-yes"
|
||||
" --reboot-if-needed"
|
||||
)
|
||||
|
||||
def _qemu_ask_prod(self):
|
||||
"""Environnement cible : dev (défaut) ou prod. En PROD : ERPLibre est
|
||||
|
|
|
|||
Loading…
Reference in a new issue