[FIX] qemu: Fedora image robuste (miroirs) + silence du bruit virtinst
Déploiement PARALLÈLE de 13 VM -> 2 problèmes observés : 1. « Aucune image Fedora-Cloud-Base-Generic pour Fedora 42 » alors que l'image EXISTE. download.fedoraproject.org est un redirecteur (MirrorManager) : sous requêtes parallèles, une VM tombait sur un miroir incomplet -> index HTML sans correspondance -> sys.exit. resolve_fedora_url réessaie (2× le redirecteur) puis se replie sur le serveur MAÎTRE dl.fedoraproject.org (toujours complet). Validé : F41/F42 résolus. 2. Pavé « Fetched capabilities … » (énorme XML) dans la sortie : erreur de LOGGING de virtinst — sous sudo, HOME/cache inaccessible -> échec d'écriture du journal debug -> Python déverse l'enregistrement raté. On préfixe virt-install de « env XDG_CACHE_HOME=… HOME=… » (traverse sudo) vers un cache écrivable -> journal silencieux. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b99db0ea66
commit
1ebf2b353f
1 changed files with 41 additions and 15 deletions
|
|
@ -161,6 +161,10 @@ DEBIAN_CLOUD_BASES: tuple[str, ...] = (
|
||||||
"https://laotzu.ftp.acc.umu.se/cdimage/cloud",
|
"https://laotzu.ftp.acc.umu.se/cdimage/cloud",
|
||||||
)
|
)
|
||||||
FEDORA_BASE = "https://download.fedoraproject.org/pub/fedora/linux/releases"
|
FEDORA_BASE = "https://download.fedoraproject.org/pub/fedora/linux/releases"
|
||||||
|
# Serveur MAÎTRE (pas de redirection MirrorManager) : repli fiable quand le
|
||||||
|
# redirecteur envoie sur un miroir incomplet (fréquent en déploiement
|
||||||
|
# PARALLÈLE : chaque requête peut tomber sur un miroir différent/désynchronisé).
|
||||||
|
FEDORA_BASE_MASTER = "https://dl.fedoraproject.org/pub/fedora/linux/releases"
|
||||||
|
|
||||||
# Répertoire de cache par défaut des images cloud (cohérent avec --disk-dir /
|
# Répertoire de cache par défaut des images cloud (cohérent avec --disk-dir /
|
||||||
# --seed-dir). L'écriture y nécessite root : le déploiement tourne de toute
|
# --seed-dir). L'écriture y nécessite root : le déploiement tourne de toute
|
||||||
|
|
@ -214,26 +218,38 @@ def image_candidates(
|
||||||
|
|
||||||
def resolve_fedora_url(version: str, arch: str, dry_run: bool) -> str:
|
def resolve_fedora_url(version: str, arch: str, dry_run: bool) -> str:
|
||||||
"""Résout l'URL du qcow2 « Fedora Cloud Base Generic » depuis l'index
|
"""Résout l'URL du qcow2 « Fedora Cloud Base Generic » depuis l'index
|
||||||
HTML des releases (Fedora ne publie pas de lien « latest »)."""
|
HTML des releases (Fedora ne publie pas de lien « latest »). ROBUSTE :
|
||||||
|
plusieurs tentatives sur le redirecteur puis repli sur le serveur maître
|
||||||
|
(dl.fedoraproject.org) — sinon, en déploiement parallèle, une requête
|
||||||
|
tombée sur un miroir incomplet faisait échouer la VM (« image introuvable »)
|
||||||
|
alors que l'image existe bel et bien."""
|
||||||
a = distro_arch("fedora", arch)
|
a = distro_arch("fedora", arch)
|
||||||
index = f"{FEDORA_BASE}/{version}/Cloud/{a}/images/"
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
rf"Fedora-Cloud-Base-Generic-{version}-[0-9.]+\.{a}\.qcow2"
|
rf"Fedora-Cloud-Base-Generic-{version}-[0-9.]+\.{a}\.qcow2"
|
||||||
)
|
)
|
||||||
if dry_run:
|
if dry_run:
|
||||||
|
index = f"{FEDORA_BASE}/{version}/Cloud/{a}/images/"
|
||||||
return index + f"Fedora-Cloud-Base-Generic-{version}-<build>.{a}.qcow2"
|
return index + f"Fedora-Cloud-Base-Generic-{version}-<build>.{a}.qcow2"
|
||||||
try:
|
# On essaie le redirecteur (2 fois : chaque requête peut viser un miroir
|
||||||
with urllib.request.urlopen(index, timeout=30) as resp: # noqa: S310
|
# différent) puis le serveur maître (toujours complet).
|
||||||
html = resp.read().decode(errors="replace")
|
bases = [FEDORA_BASE, FEDORA_BASE, FEDORA_BASE_MASTER]
|
||||||
except Exception as exc: # pragma: no cover - dépend du réseau
|
last_err = ""
|
||||||
sys.exit(f"Impossible de lister les images Fedora {version} : {exc}")
|
for base in bases:
|
||||||
names = sorted(set(pattern.findall(html)))
|
index = f"{base}/{version}/Cloud/{a}/images/"
|
||||||
if not names:
|
try:
|
||||||
sys.exit(
|
with urllib.request.urlopen(index, timeout=30) as resp: # noqa: S310
|
||||||
"Aucune image « Fedora-Cloud-Base-Generic » trouvée pour "
|
html = resp.read().decode(errors="replace")
|
||||||
f"Fedora {version} ({a}) dans {index}"
|
except Exception as exc: # pragma: no cover - dépend du réseau
|
||||||
)
|
last_err = str(exc)
|
||||||
return index + names[-1]
|
continue
|
||||||
|
names = sorted(set(pattern.findall(html)))
|
||||||
|
if names:
|
||||||
|
return index + names[-1]
|
||||||
|
sys.exit(
|
||||||
|
"Aucune image « Fedora-Cloud-Base-Generic » trouvée pour "
|
||||||
|
f"Fedora {version} ({a}) après plusieurs miroirs"
|
||||||
|
+ (f" (dernière erreur : {last_err})" if last_err else "")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def default_image_name(distro: str, code: str, arch: str, version: str) -> str:
|
def default_image_name(distro: str, code: str, arch: str, version: str) -> str:
|
||||||
|
|
@ -1241,7 +1257,17 @@ def virt_install(
|
||||||
cmd += ["--virt-type", "qemu"]
|
cmd += ["--virt-type", "qemu"]
|
||||||
if not args.attach_console:
|
if not args.attach_console:
|
||||||
cmd.append("--noautoconsole")
|
cmd.append("--noautoconsole")
|
||||||
runner.run(cmd, privileged=True)
|
# virtinst écrit un journal de debug dans ~/.cache/virt-manager ; sous
|
||||||
|
# sudo, HOME/cache peut être inaccessible -> l'écriture échoue et Python
|
||||||
|
# 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.
|
||||||
|
log_env = [
|
||||||
|
"env",
|
||||||
|
"XDG_CACHE_HOME=/var/tmp/erplibre-virtinst",
|
||||||
|
"HOME=/var/tmp/erplibre-virtinst",
|
||||||
|
]
|
||||||
|
runner.run(log_env + cmd, privileged=True)
|
||||||
|
|
||||||
|
|
||||||
def _ip_reachable(ip: str, port: int = 22, timeout: float = 3) -> bool:
|
def _ip_reachable(ip: str, port: int = 22, timeout: float = 3) -> bool:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue