[IMP] script todo: infra — architecture [all] (matrice distro×version×arch)
Menu « Déployer l'infra ERPLibre » : la sélection d'architecture propose désormais [all] = toutes les architectures supportées. L'architecture devient une dimension à part entière de la matrice de déploiement. - [all] archis + [all] catalogue : une VM par (distro, version, archi publiée par cette distro). Ex. ubuntu -> amd64/arm64/s390x, debian/fedora -> amd64/arm64, arch -> amd64 (30 VM au total avec le catalogue courant). - [all] archis + [granulaire] : la liste à plat inclut l'archi ([amd64]/ [arm64]/[s390x]) ; on choisit des combinaisons précises par virgules. - [all] archis + [principal] : version par défaut de chaque distro × chaque archi supportée. - Une archi précise (arm64/s390x) restreint le catalogue aux distros qui la publient (inchangé). selected porte l'archi par élément ; les noms sont suffixés par archi pour les non-natives (erplibre-ubuntu-2604-s390x) -> pas de collision. --arch transmis par VM. Chaque distro ne reçoit que les archis QU'ELLE publie. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bd94c277d3
commit
50617e3909
2 changed files with 86 additions and 51 deletions
|
|
@ -885,9 +885,10 @@ class TODO:
|
||||||
return self._QEMU_ARM64_DISTROS
|
return self._QEMU_ARM64_DISTROS
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _qemu_ask_arch(self, opts, native):
|
def _qemu_ask_arch(self, opts, native, allow_all=False):
|
||||||
"""Affiche les architectures `opts` (natif marqué d'un *) et renvoie le
|
"""Affiche les architectures `opts` (natif marqué d'un *) et renvoie le
|
||||||
choix. Toute arch non native est ÉMULÉE (TCG, lente)."""
|
choix. Si `allow_all`, propose aussi [all] = toutes les archis (renvoie
|
||||||
|
« all »). Toute arch non native est ÉMULÉE (TCG, lente)."""
|
||||||
print(f"\n{t('Architecture:')}")
|
print(f"\n{t('Architecture:')}")
|
||||||
for i, a in enumerate(opts, 1):
|
for i, a in enumerate(opts, 1):
|
||||||
alias = self._QEMU_ARCH_ALIAS.get(a)
|
alias = self._QEMU_ARCH_ALIAS.get(a)
|
||||||
|
|
@ -901,21 +902,27 @@ class TODO:
|
||||||
else:
|
else:
|
||||||
label += f" ({t('emulated, slow')})"
|
label += f" ({t('emulated, slow')})"
|
||||||
print(f" [{i}] {label}")
|
print(f" [{i}] {label}")
|
||||||
|
if allow_all:
|
||||||
|
print(f" [all] {t('All supported architectures')}")
|
||||||
sel = (
|
sel = (
|
||||||
input(f"{t('Choice (number or name, blank = native):')} ")
|
input(f"{t('Choice (number or name, blank = native):')} ")
|
||||||
.strip()
|
.strip()
|
||||||
.lower()
|
.lower()
|
||||||
)
|
)
|
||||||
chosen = native
|
if not sel:
|
||||||
if sel:
|
return native
|
||||||
chosen = None
|
if allow_all and sel in ("all", "*"):
|
||||||
for i, a in enumerate(opts, 1):
|
note = t("(includes emulated architectures — some VMs are slow)")
|
||||||
if sel in (str(i), a, self._QEMU_ARCH_ALIAS.get(a)):
|
print(f"⚠ {note}")
|
||||||
chosen = a
|
return "all"
|
||||||
break
|
chosen = None
|
||||||
if chosen is None:
|
for i, a in enumerate(opts, 1):
|
||||||
print(f"{t('Invalid selection, using')} {native}")
|
if sel in (str(i), a, self._QEMU_ARCH_ALIAS.get(a)):
|
||||||
chosen = native
|
chosen = a
|
||||||
|
break
|
||||||
|
if chosen is None:
|
||||||
|
print(f"{t('Invalid selection, using')} {native}")
|
||||||
|
return native
|
||||||
if chosen != native:
|
if chosen != native:
|
||||||
warn = t(
|
warn = t(
|
||||||
"This architecture is emulated (TCG): boot and install are"
|
"This architecture is emulated (TCG): boot and install are"
|
||||||
|
|
@ -944,7 +951,7 @@ class TODO:
|
||||||
opts = ["amd64", "arm64", "s390x"]
|
opts = ["amd64", "arm64", "s390x"]
|
||||||
if native not in opts: # hôte exotique : garder le natif en tête
|
if native not in opts: # hôte exotique : garder le natif en tête
|
||||||
opts.insert(0, native)
|
opts.insert(0, native)
|
||||||
return self._qemu_ask_arch(opts, native)
|
return self._qemu_ask_arch(opts, native, allow_all=True)
|
||||||
|
|
||||||
def _qemu_list_images(self):
|
def _qemu_list_images(self):
|
||||||
"""Affiche la liste des distros/versions et leurs specs."""
|
"""Affiche la liste des distros/versions et leurs specs."""
|
||||||
|
|
@ -1994,28 +2001,42 @@ class TODO:
|
||||||
return
|
return
|
||||||
distros = list(mod.DISTROS)
|
distros = list(mod.DISTROS)
|
||||||
|
|
||||||
# 0) Architecture du parc (défaut : native de l'hôte). arm64 et s390x
|
# 0) Architecture du parc (défaut : native ; [all] = TOUTES les archis
|
||||||
# n'ont pas d'images pour toutes les distros -> on restreint le
|
# supportées). Pour une arch précise non-amd64, on restreint le
|
||||||
# catalogue aux distros qui publient l'arch choisie.
|
# catalogue aux distros qui la publient ; pour [all], chaque distro
|
||||||
arch = self._qemu_prompt_infra_arch()
|
# reçoit uniquement les archis QU'ELLE publie.
|
||||||
allowed = self._qemu_arch_distros(arch)
|
arch = self._qemu_prompt_infra_arch() # amd64/arm64/s390x/all
|
||||||
if allowed is not None:
|
if arch != "all":
|
||||||
keep = [d for d in distros if d in allowed]
|
allowed = self._qemu_arch_distros(arch)
|
||||||
dropped = [d for d in distros if d not in keep]
|
if allowed is not None:
|
||||||
if dropped:
|
keep = [d for d in distros if d in allowed]
|
||||||
print(
|
dropped = [d for d in distros if d not in keep]
|
||||||
f" ⚠ {t('images for this arch only exist for:')} "
|
if dropped:
|
||||||
f"{', '.join(allowed)} "
|
print(
|
||||||
f"({t('ignored:')} {', '.join(dropped)})"
|
f" ⚠ {t('images for this arch only exist for:')} "
|
||||||
)
|
f"{', '.join(allowed)} "
|
||||||
distros = keep
|
f"({t('ignored:')} {', '.join(dropped)})"
|
||||||
if not distros:
|
)
|
||||||
print(t("Nothing selected."))
|
distros = keep
|
||||||
return
|
if not distros:
|
||||||
|
print(t("Nothing selected."))
|
||||||
|
return
|
||||||
|
|
||||||
|
def arches_for(distro):
|
||||||
|
"""Architectures à déployer pour cette distro selon le choix."""
|
||||||
|
if arch != "all":
|
||||||
|
return [arch]
|
||||||
|
out = ["amd64"]
|
||||||
|
if distro in self._QEMU_ARM64_DISTROS:
|
||||||
|
out.append("arm64")
|
||||||
|
if distro in self._QEMU_S390X_DISTROS:
|
||||||
|
out.append("s390x")
|
||||||
|
return out
|
||||||
|
|
||||||
# 1) Distributions : multi-sélection, catalogue complet, principal (la
|
# 1) Distributions : multi-sélection, catalogue complet, principal (la
|
||||||
# version par défaut de chaque distro, marquée d'un *), ou granulaire
|
# version par défaut de chaque distro, marquée d'un *), ou granulaire
|
||||||
# (liste à plat de TOUTES les versions, choix par virgules).
|
# (liste à plat de TOUTES les versions × archis, choix par virgules).
|
||||||
|
# Avec [all] archis, chaque version se décline en une VM par archi.
|
||||||
print(f"\n{t('Distributions:')}")
|
print(f"\n{t('Distributions:')}")
|
||||||
for i, d in enumerate(distros, 1):
|
for i, d in enumerate(distros, 1):
|
||||||
default_v = mod.DISTROS[d][1]
|
default_v = mod.DISTROS[d][1]
|
||||||
|
|
@ -2044,34 +2065,36 @@ class TODO:
|
||||||
principal = raw in ("principal", "each", "p")
|
principal = raw in ("principal", "each", "p")
|
||||||
granular = raw in ("granulaire", "granular", "g")
|
granular = raw in ("granulaire", "granular", "g")
|
||||||
|
|
||||||
selected = [] # (distro, version, ram_mb, disk_str)
|
selected = [] # (distro, version, ram_mb, disk_str, arch)
|
||||||
if granular:
|
if granular:
|
||||||
# Liste APLATIE de toutes les versions (distro + version) : on choisit
|
# Liste APLATIE distro + version + ARCHITECTURE : on choisit des
|
||||||
# des versions précises par leurs numéros, séparés par des virgules.
|
# combinaisons précises par numéros séparés de virgules.
|
||||||
flat = [] # (distro, version, ram, disk, is_default)
|
flat = [] # (distro, version, ram, disk, is_default, arch)
|
||||||
for d in distros:
|
for d in distros:
|
||||||
versions_map, default_v = mod.DISTROS[d]
|
versions_map, default_v = mod.DISTROS[d]
|
||||||
for v, (_c, _o, ram, disk) in versions_map.items():
|
for v, (_c, _o, ram, disk) in versions_map.items():
|
||||||
flat.append((d, v, ram, disk, v == default_v))
|
for a in arches_for(d):
|
||||||
|
flat.append((d, v, ram, disk, v == default_v, a))
|
||||||
print(f"\n{t('All versions:')}")
|
print(f"\n{t('All versions:')}")
|
||||||
for i, (d, v, ram, disk, isdef) in enumerate(flat, 1):
|
for i, (d, v, ram, disk, isdef, a) in enumerate(flat, 1):
|
||||||
star = " *" if isdef else ""
|
star = " *" if isdef else ""
|
||||||
print(f" [{i}] {d} {v}{star} (RAM≥{ram}Mo, {disk})")
|
print(f" [{i}] {d} {v}{star} [{a}] (RAM≥{ram}Mo, {disk})")
|
||||||
r = (
|
r = (
|
||||||
input(t("Selection (comma-separated numbers): "))
|
input(t("Selection (comma-separated numbers): "))
|
||||||
.strip()
|
.strip()
|
||||||
.lower()
|
.lower()
|
||||||
)
|
)
|
||||||
for d, v, ram, disk, _isdef in self._parse_index_selection(
|
for d, v, ram, disk, _isdef, a in self._parse_index_selection(
|
||||||
r, flat
|
r, flat
|
||||||
):
|
):
|
||||||
selected.append((d, v, ram, disk))
|
selected.append((d, v, ram, disk, a))
|
||||||
elif principal:
|
elif principal:
|
||||||
# Une VM par distro : sa version par défaut.
|
# Une VM par distro (version par défaut) × chaque archi supportée.
|
||||||
for d in distros:
|
for d in distros:
|
||||||
versions_map, default_v = mod.DISTROS[d]
|
versions_map, default_v = mod.DISTROS[d]
|
||||||
_c, _o, ram, disk = versions_map[default_v]
|
_c, _o, ram, disk = versions_map[default_v]
|
||||||
selected.append((d, default_v, ram, disk))
|
for a in arches_for(d):
|
||||||
|
selected.append((d, default_v, ram, disk, a))
|
||||||
else:
|
else:
|
||||||
sel_distros = (
|
sel_distros = (
|
||||||
distros
|
distros
|
||||||
|
|
@ -2103,7 +2126,8 @@ class TODO:
|
||||||
)
|
)
|
||||||
for v in chosen:
|
for v in chosen:
|
||||||
_c, _o, ram, disk = versions_map[v]
|
_c, _o, ram, disk = versions_map[v]
|
||||||
selected.append((d, v, ram, disk))
|
for a in arches_for(d):
|
||||||
|
selected.append((d, v, ram, disk, a))
|
||||||
if not selected:
|
if not selected:
|
||||||
print(t("Nothing selected."))
|
print(t("Nothing selected."))
|
||||||
return
|
return
|
||||||
|
|
@ -2113,9 +2137,12 @@ class TODO:
|
||||||
total_disk = sum(self._parse_disk_gb(s[3]) for s in selected)
|
total_disk = sum(self._parse_disk_gb(s[3]) for s in selected)
|
||||||
free_ram = self._host_free_ram_mb()
|
free_ram = self._host_free_ram_mb()
|
||||||
print(f"\n{t('Deployment plan')} ({len(selected)} VM) :")
|
print(f"\n{t('Deployment plan')} ({len(selected)} VM) :")
|
||||||
for d, v, ram, disk in selected:
|
for d, v, ram, disk, a in selected:
|
||||||
name = self._qemu_infra_name(d, v, arch)
|
name = self._qemu_infra_name(d, v, a)
|
||||||
print(f" - {name:<26} {d} {v:<7} RAM {ram}Mo {t('disk')} {disk}")
|
print(
|
||||||
|
f" - {name:<30} {d} {v:<7} [{a:<5}] "
|
||||||
|
f"RAM {ram}Mo {t('disk')} {disk}"
|
||||||
|
)
|
||||||
print(f"\n {t('Total RAM (all running):')} {total_ram} Mo")
|
print(f"\n {t('Total RAM (all running):')} {total_ram} Mo")
|
||||||
print(f" {t('Total virtual disk (thin qcow2):')} ~{total_disk} G")
|
print(f" {t('Total virtual disk (thin qcow2):')} ~{total_disk} G")
|
||||||
if free_ram:
|
if free_ram:
|
||||||
|
|
@ -2172,8 +2199,8 @@ class TODO:
|
||||||
script_path = self._qemu_script_path()
|
script_path = self._qemu_script_path()
|
||||||
deployed = []
|
deployed = []
|
||||||
jobs = [] # (name, parts) des VM à créer
|
jobs = [] # (name, parts) des VM à créer
|
||||||
for d, v, _ram, disk in selected:
|
for d, v, _ram, disk, a in selected:
|
||||||
name = self._qemu_infra_name(d, v, arch)
|
name = self._qemu_infra_name(d, v, a)
|
||||||
if self._qemu_domain_exists(name):
|
if self._qemu_domain_exists(name):
|
||||||
print(f"⏭ {name}: {t('already exists, skipped.')}")
|
print(f"⏭ {name}: {t('already exists, skipped.')}")
|
||||||
deployed.append(name)
|
deployed.append(name)
|
||||||
|
|
@ -2193,8 +2220,8 @@ class TODO:
|
||||||
"erplibre",
|
"erplibre",
|
||||||
"--no-wait-ip",
|
"--no-wait-ip",
|
||||||
]
|
]
|
||||||
if arch and arch != "amd64":
|
if a and a != "amd64":
|
||||||
parts += ["--arch", arch]
|
parts += ["--arch", a]
|
||||||
if ssh_key:
|
if ssh_key:
|
||||||
parts += ["--ssh-key", ssh_key]
|
parts += ["--ssh-key", ssh_key]
|
||||||
if install_branch:
|
if install_branch:
|
||||||
|
|
|
||||||
|
|
@ -1197,6 +1197,14 @@ TRANSLATIONS = {
|
||||||
"fr": "images pour cette architecture disponibles seulement pour :",
|
"fr": "images pour cette architecture disponibles seulement pour :",
|
||||||
"en": "images for this arch only exist for:",
|
"en": "images for this arch only exist for:",
|
||||||
},
|
},
|
||||||
|
"All supported architectures": {
|
||||||
|
"fr": "Toutes les architectures supportées",
|
||||||
|
"en": "All supported architectures",
|
||||||
|
},
|
||||||
|
"(includes emulated architectures — some VMs are slow)": {
|
||||||
|
"fr": "(inclut des architectures émulées — certaines VM sont lentes)",
|
||||||
|
"en": "(includes emulated architectures — some VMs are slow)",
|
||||||
|
},
|
||||||
"Waiting for the VM to start (boot + cloud-init)": {
|
"Waiting for the VM to start (boot + cloud-init)": {
|
||||||
"fr": "En attente du démarrage de la VM (boot + cloud-init)",
|
"fr": "En attente du démarrage de la VM (boot + cloud-init)",
|
||||||
"en": "Waiting for the VM to start (boot + cloud-init)",
|
"en": "Waiting for the VM to start (boot + cloud-init)",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue