[ADD] catalogue: Fedora 43 for s390x

Fedora does publish an s390x cloud image, just elsewhere: the arch is
SECONDARY there, its images live under "fedora-secondary" rather than
/pub/fedora/linux/. The catalog comment read "404" -- it was the wrong
tree.

It brings what nothing else has on this architecture: qpdf 12.2.0,
exactly the pikepdf 10 threshold. The qpdf build, half an hour under
emulation, disappears. With GCC 15, Python 3.14 and cargo 1.90, none of
the s390x workarounds fire there.

Only 43 is kept: Fedora builds s390x for the current release only. 41 and
42 return 404 on the master mirror, 44 sits on third-party mirrors only.
Hence a positive per-architecture declaration, read by both interfaces --
the catalog never offers what deployment would refuse.

--- FR ---

Fedora publie bien une image cloud s390x, mais ailleurs : l'architecture
est SECONDAIRE chez elle, ses images vivent sous « fedora-secondary » et
non sous /pub/fedora/linux/. Le commentaire du catalogue disait « 404 » —
c'était la mauvaise arborescence.

Elle apporte ce qu'aucune autre n'a sur cette architecture : qpdf 12.2.0,
soit exactement le seuil de pikepdf 10. La compilation de qpdf, une demi-
heure sous émulation, disparaît. Avec GCC 15, Python 3.14 et cargo 1.90,
aucun des contournements s390x ne s'y déclenche.

Seule la 43 est retenue : Fedora ne construit s390x que pour la version
courante. Les 41 et 42 rendent 404 sur le miroir maître, la 44 n'est que
sur certains miroirs tiers. D'où une déclaration positive par
architecture, que les deux interfaces relisent — le catalogue ne propose
pas ce que le déploiement refuserait.

Assisted-by: Claude Opus 5
This commit is contained in:
Mathieu Benoit 2026-08-11 19:55:09 -04:00
parent 3d6d2395b3
commit 96464ab0eb
5 changed files with 70 additions and 8 deletions

View file

@ -179,11 +179,14 @@ Catalog, per architecture (`deploy_qemu.py` is the source of truth):
|---|---|:-:|:-:|:-:| |---|---|:-:|:-:|:-:|
| ubuntu | `24.04` (default), `25.10`, `26.04` | ✔ | ✔ | ✔ | | ubuntu | `24.04` (default), `25.10`, `26.04` | ✔ | ✔ | ✔ |
| debian | `11`, `12` (default), `13` | ✔ | ✔ | — | | debian | `11`, `12` (default), `13` | ✔ | ✔ | — |
| fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | — | | fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | `43` only |
| almalinux | `9` (default), `10` | ✔ | ✔ | ✔ | | almalinux | `9` (default), `10` | ✔ | ✔ | ✔ |
| rocky | `9`, `10` (default) | ✔ | ✔ | ✔ | | rocky | `9`, `10` (default) | ✔ | ✔ | ✔ |
| arch | `latest` | ✔ | — | — | | arch | `latest` | ✔ | — | — |
Fedora builds s390x only for the current release, and on a separate tree
(`fedora-secondary`) — hence the single version there.
Provide an explicit image path as a positional argument to override the Provide an explicit image path as a positional argument to override the
automatic download location. automatic download location.
@ -201,11 +204,14 @@ Catalogue, par architecture (`deploy_qemu.py` fait autorité) :
|---|---|:-:|:-:|:-:| |---|---|:-:|:-:|:-:|
| ubuntu | `24.04` (défaut), `25.10`, `26.04` | ✔ | ✔ | ✔ | | ubuntu | `24.04` (défaut), `25.10`, `26.04` | ✔ | ✔ | ✔ |
| debian | `11`, `12` (défaut), `13` | ✔ | ✔ | — | | debian | `11`, `12` (défaut), `13` | ✔ | ✔ | — |
| fedora | `41`, `42` (défaut), `43`, `44` | ✔ | ✔ | — | | fedora | `41`, `42` (défaut), `43`, `44` | ✔ | ✔ | `43` seule |
| almalinux | `9` (défaut), `10` | ✔ | ✔ | ✔ | | almalinux | `9` (défaut), `10` | ✔ | ✔ | ✔ |
| rocky | `9`, `10` (défaut) | ✔ | ✔ | ✔ | | rocky | `9`, `10` (défaut) | ✔ | ✔ | ✔ |
| arch | `latest` | ✔ | — | — | | arch | `latest` | ✔ | — | — |
Fedora ne construit s390x que pour la version courante, et sur une
arborescence à part (`fedora-secondary`) — d'où la version unique.
Fournissez un chemin d'image en argument positionnel pour surcharger Fournissez un chemin d'image en argument positionnel pour surcharger
l'emplacement de téléchargement automatique. l'emplacement de téléchargement automatique.

View file

@ -98,11 +98,14 @@ Catalogue, par architecture (`deploy_qemu.py` fait autorité) :
|---|---|:-:|:-:|:-:| |---|---|:-:|:-:|:-:|
| ubuntu | `24.04` (défaut), `25.10`, `26.04` | ✔ | ✔ | ✔ | | ubuntu | `24.04` (défaut), `25.10`, `26.04` | ✔ | ✔ | ✔ |
| debian | `11`, `12` (défaut), `13` | ✔ | ✔ | — | | debian | `11`, `12` (défaut), `13` | ✔ | ✔ | — |
| fedora | `41`, `42` (défaut), `43`, `44` | ✔ | ✔ | — | | fedora | `41`, `42` (défaut), `43`, `44` | ✔ | ✔ | `43` seule |
| almalinux | `9` (défaut), `10` | ✔ | ✔ | ✔ | | almalinux | `9` (défaut), `10` | ✔ | ✔ | ✔ |
| rocky | `9`, `10` (défaut) | ✔ | ✔ | ✔ | | rocky | `9`, `10` (défaut) | ✔ | ✔ | ✔ |
| arch | `latest` | ✔ | — | — | | arch | `latest` | ✔ | — | — |
Fedora ne construit s390x que pour la version courante, et sur une
arborescence à part (`fedora-secondary`) — d'où la version unique.
Fournissez un chemin d'image en argument positionnel pour surcharger Fournissez un chemin d'image en argument positionnel pour surcharger
l'emplacement de téléchargement automatique. l'emplacement de téléchargement automatique.

View file

@ -92,11 +92,14 @@ Catalog, per architecture (`deploy_qemu.py` is the source of truth):
|---|---|:-:|:-:|:-:| |---|---|:-:|:-:|:-:|
| ubuntu | `24.04` (default), `25.10`, `26.04` | ✔ | ✔ | ✔ | | ubuntu | `24.04` (default), `25.10`, `26.04` | ✔ | ✔ | ✔ |
| debian | `11`, `12` (default), `13` | ✔ | ✔ | — | | debian | `11`, `12` (default), `13` | ✔ | ✔ | — |
| fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | — | | fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | `43` only |
| almalinux | `9` (default), `10` | ✔ | ✔ | ✔ | | almalinux | `9` (default), `10` | ✔ | ✔ | ✔ |
| rocky | `9`, `10` (default) | ✔ | ✔ | ✔ | | rocky | `9`, `10` (default) | ✔ | ✔ | ✔ |
| arch | `latest` | ✔ | — | — | | arch | `latest` | ✔ | — | — |
Fedora builds s390x only for the current release, and on a separate tree
(`fedora-secondary`) — hence the single version there.
Provide an explicit image path as a positional argument to override the Provide an explicit image path as a positional argument to override the
automatic download location. automatic download location.

View file

@ -146,7 +146,27 @@ NON_X86_ARCHES: tuple[str, ...] = ("arm64", "s390x")
# - s390x (IBM Z) : Ubuntu seulement (Debian/Fedora : 404 ; Arch : x86/arm). # - s390x (IBM Z) : Ubuntu seulement (Debian/Fedora : 404 ; Arch : x86/arm).
# - arm64/aarch64 : Ubuntu, Debian, Fedora (Arch : pas d'image cloud officielle # - arm64/aarch64 : Ubuntu, Debian, Fedora (Arch : pas d'image cloud officielle
# aarch64 sur geo.mirror.pkgbuild.com). # aarch64 sur geo.mirror.pkgbuild.com).
S390X_DISTROS: tuple[str, ...] = ("ubuntu", "almalinux", "rocky") S390X_DISTROS: tuple[str, ...] = ("ubuntu", "almalinux", "rocky", "fedora")
# Une distro peut ne publier qu'une PARTIE de ses versions sur une
# architecture. Déclaration POSITIVE : hors de cette table, toutes les versions
# du catalogue sont réputées disponibles.
#
# Fedora ne construit s390x que pour la version courante, et sur une
# arborescence à part (« fedora-secondary ») : la 41 et la 42 y sont retirées
# (404 sur le miroir maître), la 44 n'est pour l'instant que sur certains
# miroirs tiers. Seule la 43 est servie par dl.fedoraproject.org — vérifié.
ARCH_ONLY_VERSIONS: dict[str, dict[str, tuple[str, ...]]] = {
"s390x": {"fedora": ("43",)},
}
def arch_versions(distro: str, arch: str, versions) -> list[str]:
"""Versions de `distro` réellement publiées pour `arch`."""
only = ARCH_ONLY_VERSIONS.get(arch, {}).get(distro)
return [v for v in versions if only is None or v in only]
ARM64_DISTROS: tuple[str, ...] = ( ARM64_DISTROS: tuple[str, ...] = (
"ubuntu", "ubuntu",
"debian", "debian",
@ -197,6 +217,15 @@ FEDORA_BASE = "https://download.fedoraproject.org/pub/fedora/linux/releases"
# redirecteur envoie sur un miroir incomplet (fréquent en déploiement # 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é). # 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" FEDORA_BASE_MASTER = "https://dl.fedoraproject.org/pub/fedora/linux/releases"
# s390x est une architecture SECONDAIRE chez Fedora : ses images ne sont PAS
# sous /pub/fedora/linux/ mais sous /pub/fedora-secondary/, et seule la
# version courante y est construite.
FEDORA_SECONDARY = (
"https://download.fedoraproject.org/pub/fedora-secondary/releases"
)
FEDORA_SECONDARY_MASTER = (
"https://dl.fedoraproject.org/pub/fedora-secondary/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
@ -275,12 +304,18 @@ def resolve_fedora_url(version: str, arch: str, dry_run: bool) -> str:
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"
) )
# Architecture secondaire (s390x, ppc64le) : autre arborescence.
primary, master = (
(FEDORA_SECONDARY, FEDORA_SECONDARY_MASTER)
if arch == "s390x"
else (FEDORA_BASE, FEDORA_BASE_MASTER)
)
if dry_run: if dry_run:
index = f"{FEDORA_BASE}/{version}/Cloud/{a}/images/" index = f"{primary}/{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"
# On essaie le redirecteur (2 fois : chaque requête peut viser un miroir # On essaie le redirecteur (2 fois : chaque requête peut viser un miroir
# différent) puis le serveur maître (toujours complet). # différent) puis le serveur maître (toujours complet).
bases = [FEDORA_BASE, FEDORA_BASE, FEDORA_BASE_MASTER] bases = [primary, primary, master]
last_err = "" last_err = ""
for base in bases: for base in bases:
index = f"{base}/{version}/Cloud/{a}/images/" index = f"{base}/{version}/Cloud/{a}/images/"
@ -2173,6 +2208,14 @@ def main() -> None:
f"Architecture {args.arch} indisponible pour {args.distro!r} : " f"Architecture {args.arch} indisponible pour {args.distro!r} : "
f"images cloud publiées seulement pour {', '.join(supported)}." f"images cloud publiées seulement pour {', '.join(supported)}."
) )
# Toutes les versions d'une distro ne sont pas publiées sur toutes les
# architectures : le dire ici plutôt que d'échouer au téléchargement.
ok_versions = arch_versions(args.distro, args.arch, versions)
if args.version not in ok_versions:
sys.exit(
f"{args.distro} {args.version} n'est pas publié en {args.arch}.\n"
f" Versions disponibles : {', '.join(ok_versions) or 'aucune'}."
)
code, default_osinfo, min_ram, min_disk = versions[args.version] code, default_osinfo, min_ram, min_disk = versions[args.version]
if args.codename: if args.codename:
code = args.codename code = args.codename

View file

@ -1074,7 +1074,7 @@ class TODO:
# Distros publiant des images cloud par architecture (cohérent avec # Distros publiant des images cloud par architecture (cohérent avec
# S390X_DISTROS / ARM64_DISTROS de deploy_qemu.py). amd64 : toutes. # S390X_DISTROS / ARM64_DISTROS de deploy_qemu.py). amd64 : toutes.
_QEMU_S390X_DISTROS = ("ubuntu", "almalinux", "rocky") _QEMU_S390X_DISTROS = ("ubuntu", "almalinux", "rocky", "fedora")
_QEMU_ARM64_DISTROS = ( _QEMU_ARM64_DISTROS = (
"ubuntu", "ubuntu",
"debian", "debian",
@ -5186,10 +5186,17 @@ class TODO:
déployable, aussi bien pour la liste granulaire de la CLI que pour la déployable, aussi bien pour la liste granulaire de la CLI que pour la
liste à cocher du formulaire TUI.""" liste à cocher du formulaire TUI."""
flat = [] flat = []
# Une distro peut ne publier qu'une partie de ses versions sur une
# architecture (Fedora ne construit que la courante en s390x). La
# table vit dans deploy_qemu.py, qui refuse aussi ces combinaisons :
# une seule source, donc aucun écran n'offre un choix rejeté ensuite.
only = getattr(mod, "arch_versions", None)
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():
for a in self._qemu_arches_for(d, arch): for a in self._qemu_arches_for(d, arch):
if only and v not in only(d, a, versions_map):
continue
flat.append( flat.append(
{ {
"distro": d, "distro": d,