[ADD] install: openSUSE support, mirrors and packages
Tumbleweed is the only catalog entry whose qpdf already clears the pikepdf threshold: 12.3.2 against 12.2 required, so the half-hour qpdf build under s390x emulation never runs there. It is also the only family foreign to both RHEL and Debian, and it brings zypper, absent from the repository: wired into the install_dev.sh dispatch, a dependency script, the remote bootstrap and the desktop block. Four SUSE traps, all met on real machines. Global options precede the subcommand, and misplaced ones abort the call; without "--auto-agree-with-licenses" zypper waits for an answer nobody gives in a detached install. A compat package that PROVIDES another under a different name makes zypper raise a conflict and drop the whole batch, so only what nothing already provides is requested. pkg-config no longer exists as an RPM, only as a capability. And a single mirror, unreachable one day, sent everyone back to Europe -- three are probed in order now. CentOS Stream is dropped again: it served as a canary but 10 duplicates what Alma and Rocky already cover. --- FR --- Tumbleweed est la seule entrée du catalogue dont qpdf franchit déjà le seuil de pikepdf : 12.3.2 contre 12.2 exigé, si bien que la demi-heure de compilation de qpdf sous émulation s390x ne s'y déclenche jamais. C'est aussi la seule famille étrangère à RHEL comme à Debian, et elle apporte zypper, absent du dépôt : câblé dans l'aiguillage d'install_dev.sh, un script de dépendances, l'amorçage distant et le bloc bureau. Quatre pièges SUSE, tous rencontrés sur machine réelle. Les options globales précèdent la sous-commande, mal placées elles arrêtent l'appel ; sans « --auto-agree-with-licenses » zypper attend une réponse que personne ne donne dans une installation détachée. Un paquet compat qui FOURNIT un autre sous un nom différent fait lever un conflit à zypper, qui abandonne le lot entier : on ne demande donc que ce que rien ne fournit déjà. pkg-config n'existe plus comme RPM, seulement comme capacité. Et un miroir unique, injoignable un jour, renvoyait tout le monde en Europe — trois sont désormais sondés dans l'ordre. CentOS Stream repart : il servait de canari, mais 10 double ce qu'Alma et Rocky couvrent déjà. Assisted-by: Claude Opus 5
This commit is contained in:
parent
96464ab0eb
commit
7120732c25
12 changed files with 522 additions and 17 deletions
|
|
@ -7,7 +7,8 @@
|
||||||
- **DNS** : `script/deployment/update_dns_cloudflare.py`
|
- **DNS** : `script/deployment/update_dns_cloudflare.py`
|
||||||
|
|
||||||
Plateformes supportées : Ubuntu 24.04 / 25.10 / 26.04, Linux Mint 22.3,
|
Plateformes supportées : Ubuntu 24.04 / 25.10 / 26.04, Linux Mint 22.3,
|
||||||
Debian 12, AlmaLinux 9+, Rocky Linux 9+, Arch Linux, macOS (pyenv),
|
Debian 12, AlmaLinux 9+, Rocky Linux 9+, openSUSE Tumbleweed, Arch Linux,
|
||||||
|
macOS (pyenv),
|
||||||
Windows (WSL/Docker).
|
Windows (WSL/Docker).
|
||||||
|
|
||||||
Ubuntu 20.04 et 22.04 sont abandonnées : pikepdf exige qpdf >= 12.2, compilé
|
Ubuntu 20.04 et 22.04 sont abandonnées : pikepdf exige qpdf >= 12.2, compilé
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ Recréer l'environnement virtuel, utiliser le guide d'installation depuis l'outi
|
||||||
- Support Selenium grid from selenium_lib.py
|
- Support Selenium grid from selenium_lib.py
|
||||||
- Add addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
- Add addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
||||||
- Deploy ERPLibre VMs with QEMU/KVM from cloud images (Ubuntu, Debian, Fedora,
|
- Deploy ERPLibre VMs with QEMU/KVM from cloud images (Ubuntu, Debian, Fedora,
|
||||||
AlmaLinux, Rocky Linux, Arch) on amd64, arm64 and s390x, with a menu to list,
|
AlmaLinux, Rocky Linux, openSUSE Tumbleweed, Arch) on amd64,
|
||||||
|
arm64 and s390x, with a menu to list,
|
||||||
test, resize, delete and clean up
|
test, resize, delete and clean up
|
||||||
- Graphical VMs: a server / desktop choice offering GNOME or Cinnamon (the
|
- Graphical VMs: a server / desktop choice offering GNOME or Cinnamon (the
|
||||||
Linux Mint desktop), with remote access through xrdp — TigerVNC on Arch
|
Linux Mint desktop), with remote access through xrdp — TigerVNC on Arch
|
||||||
|
|
@ -111,7 +112,8 @@ Recréer l'environnement virtuel, utiliser le guide d'installation depuis l'outi
|
||||||
- Support de la grille Selenium depuis selenium_lib.py
|
- Support de la grille Selenium depuis selenium_lib.py
|
||||||
- Ajout des addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
- Ajout des addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
||||||
- Déploiement de VM ERPLibre en QEMU/KVM depuis des images cloud (Ubuntu,
|
- Déploiement de VM ERPLibre en QEMU/KVM depuis des images cloud (Ubuntu,
|
||||||
Debian, Fedora, AlmaLinux, Rocky Linux, Arch) en amd64, arm64 et s390x, avec
|
Debian, Fedora, AlmaLinux, Rocky Linux, openSUSE Tumbleweed,
|
||||||
|
Arch) en amd64, arm64 et s390x, avec
|
||||||
un menu pour lister, tester, redimensionner, supprimer et nettoyer
|
un menu pour lister, tester, redimensionner, supprimer et nettoyer
|
||||||
- VM graphiques : un choix serveur / bureau proposant GNOME ou Cinnamon (le
|
- VM graphiques : un choix serveur / bureau proposant GNOME ou Cinnamon (le
|
||||||
bureau de Linux Mint), avec accès distant par xrdp — TigerVNC sur Arch
|
bureau de Linux Mint), avec accès distant par xrdp — TigerVNC sur Arch
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ Recréer l'environnement virtuel, utiliser le guide d'installation depuis l'outi
|
||||||
- Support de la grille Selenium depuis selenium_lib.py
|
- Support de la grille Selenium depuis selenium_lib.py
|
||||||
- Ajout des addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
- Ajout des addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
||||||
- Déploiement de VM ERPLibre en QEMU/KVM depuis des images cloud (Ubuntu,
|
- Déploiement de VM ERPLibre en QEMU/KVM depuis des images cloud (Ubuntu,
|
||||||
Debian, Fedora, AlmaLinux, Rocky Linux, Arch) en amd64, arm64 et s390x, avec
|
Debian, Fedora, AlmaLinux, Rocky Linux, openSUSE Tumbleweed,
|
||||||
|
Arch) en amd64, arm64 et s390x, avec
|
||||||
un menu pour lister, tester, redimensionner, supprimer et nettoyer
|
un menu pour lister, tester, redimensionner, supprimer et nettoyer
|
||||||
- VM graphiques : un choix serveur / bureau proposant GNOME ou Cinnamon (le
|
- VM graphiques : un choix serveur / bureau proposant GNOME ou Cinnamon (le
|
||||||
bureau de Linux Mint), avec accès distant par xrdp — TigerVNC sur Arch
|
bureau de Linux Mint), avec accès distant par xrdp — TigerVNC sur Arch
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ Recreating the virtual environment, use installation guide from tool `make`.
|
||||||
- Support Selenium grid from selenium_lib.py
|
- Support Selenium grid from selenium_lib.py
|
||||||
- Add addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
- Add addons OnlyOffice, Cetmix, OCA automation, OCA shopfloor
|
||||||
- Deploy ERPLibre VMs with QEMU/KVM from cloud images (Ubuntu, Debian, Fedora,
|
- Deploy ERPLibre VMs with QEMU/KVM from cloud images (Ubuntu, Debian, Fedora,
|
||||||
AlmaLinux, Rocky Linux, Arch) on amd64, arm64 and s390x, with a menu to list,
|
AlmaLinux, Rocky Linux, openSUSE Tumbleweed, Arch) on amd64,
|
||||||
|
arm64 and s390x, with a menu to list,
|
||||||
test, resize, delete and clean up
|
test, resize, delete and clean up
|
||||||
- Graphical VMs: a server / desktop choice offering GNOME or Cinnamon (the
|
- Graphical VMs: a server / desktop choice offering GNOME or Cinnamon (the
|
||||||
Linux Mint desktop), with remote access through xrdp — TigerVNC on Arch
|
Linux Mint desktop), with remote access through xrdp — TigerVNC on Arch
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
if [[ "${OSTYPE}" == "linux-gnu" ]]; then
|
# « $OSTYPE » ne decrit PAS le systeme : bash le fige au triplet avec lequel il
|
||||||
|
# a ete compile. openSUSE batit bash en « x86_64-suse-linux » et le renseigne
|
||||||
|
# donc a « linux », la ou Debian et Fedora donnent « linux-gnu ». Le test
|
||||||
|
# echouait, sans else, donc sans une ligne de sortie ni code d'erreur : AUCUNE
|
||||||
|
# dependance systeme n'etait posee, install_system() rendait 0, et
|
||||||
|
# l'installation s'arretait une heure plus tard sur « [Errno 2] ... 'cc' ».
|
||||||
|
# « uname -s » interroge le noyau et ne depend pas de la facon dont bash a ete
|
||||||
|
# bati. install_dev_extra_ubuntu.sh garde OSTYPE : il ne vise qu'Ubuntu.
|
||||||
|
OS_KERNEL="$(uname -s)"
|
||||||
|
|
||||||
|
if [[ "${OS_KERNEL}" == "Linux" ]]; then
|
||||||
source /etc/os-release
|
source /etc/os-release
|
||||||
if [[ "${ID}" == "ubuntu" ]]; then
|
if [[ "${ID}" == "ubuntu" ]]; then
|
||||||
# 20.04 et 22.04 retirees : leur chaine d'outils ne suffit plus a ERPLibre
|
# 20.04 et 22.04 retirees : leur chaine d'outils ne suffit plus a ERPLibre
|
||||||
|
|
@ -24,6 +34,10 @@ if [[ "${OSTYPE}" == "linux-gnu" ]]; then
|
||||||
./script/install/install_debian_dependency.sh
|
./script/install/install_debian_dependency.sh
|
||||||
elif [[ "${ID}" == "arch" ]]; then
|
elif [[ "${ID}" == "arch" ]]; then
|
||||||
./script/install/install_arch_linux.sh
|
./script/install/install_arch_linux.sh
|
||||||
|
elif [[ "${ID}" == opensuse* || "${ID_LIKE}" == *"suse"* ]]; then
|
||||||
|
# openSUSE Tumbleweed / Leap, SLES : gestionnaire zypper.
|
||||||
|
echo "\n---- SUSE installation process started ----"
|
||||||
|
./script/install/install_suse_dependency.sh
|
||||||
elif [[ "${ID}" == "fedora" || "${ID_LIKE}" == *"fedora"* || "${ID_LIKE}" == *"rhel"* ]]; then
|
elif [[ "${ID}" == "fedora" || "${ID_LIKE}" == *"fedora"* || "${ID_LIKE}" == *"rhel"* ]]; then
|
||||||
# AlmaLinux et Rocky declarent ID_LIKE="rhel centos fedora" : elles passent
|
# AlmaLinux et Rocky declarent ID_LIKE="rhel centos fedora" : elles passent
|
||||||
# donc par ce meme script, qui aiguille dnf.
|
# donc par ce meme script, qui aiguille dnf.
|
||||||
|
|
@ -31,9 +45,15 @@ if [[ "${OSTYPE}" == "linux-gnu" ]]; then
|
||||||
./script/install/install_fedora_dependency.sh
|
./script/install/install_fedora_dependency.sh
|
||||||
else
|
else
|
||||||
./script/install/install_debian_dependency.sh
|
./script/install/install_debian_dependency.sh
|
||||||
echo "Your Linux system is not supported, only support Ubuntu 24.04, 25.10, 26.04, Linux Mint 22.3, Debian, Fedora, AlmaLinux, Rocky Linux, Arch."
|
echo "Your Linux system is not supported, only support Ubuntu 24.04, 25.10, 26.04, Linux Mint 22.3, Debian, Fedora, AlmaLinux, Rocky Linux, openSUSE, Arch."
|
||||||
fi
|
fi
|
||||||
elif [[ "${OSTYPE}" == "darwin"* ]]; then
|
elif [[ "${OS_KERNEL}" == "Darwin" ]]; then
|
||||||
echo "\n---- Darwin installation process started ----"
|
echo "\n---- Darwin installation process started ----"
|
||||||
./script/install/install_OSX_dependency.sh
|
./script/install/install_OSX_dependency.sh
|
||||||
|
else
|
||||||
|
# Un aiguillage muet qui rend 0 est le pire des cas : l'installation continue
|
||||||
|
# sur un systeme depourvu de tout. Meme sans savoir quoi poser, on le dit et
|
||||||
|
# on arrete.
|
||||||
|
echo "Systeme non reconnu (uname -s = ${OS_KERNEL}) : aucune dependance installee."
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
337
script/install/install_suse_dependency.sh
Executable file
337
script/install/install_suse_dependency.sh
Executable file
|
|
@ -0,0 +1,337 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||||
|
#
|
||||||
|
# Dépendances système ERPLibre pour la famille SUSE (zypper). Équivalent SUSE
|
||||||
|
# de install_debian_dependency.sh et install_fedora_dependency.sh.
|
||||||
|
#
|
||||||
|
# Visé : openSUSE Tumbleweed, la seule distribution du catalogue dont qpdf
|
||||||
|
# (12.3.2) dépasse déjà le seuil de pikepdf 10 — la compilation de qpdf, une
|
||||||
|
# demi-heure sous émulation s390x, ne s'y déclenche pas.
|
||||||
|
|
||||||
|
. ./env_var.sh
|
||||||
|
|
||||||
|
EL_USER=${USER}
|
||||||
|
|
||||||
|
# « --non-interactive » est une option GLOBALE de zypper, elle précède la
|
||||||
|
# sous-commande. Les deux autres appartiennent à « install » et doivent la
|
||||||
|
# SUIVRE : placées avant, zypper répond « The flag
|
||||||
|
# --auto-agree-with-licenses is not known » et s'arrête.
|
||||||
|
#
|
||||||
|
# On demande à zypper quelles options il accepte, plutôt que de le supposer :
|
||||||
|
# la famille SUSE n'est pas testée ici, et un drapeau inconnu fait échouer la
|
||||||
|
# commande entière au lieu du seul paquet visé.
|
||||||
|
# --auto-agree-with-licenses : sinon zypper attend l'acceptation d'une
|
||||||
|
# licence, réponse que personne ne donnera dans une installation détachée.
|
||||||
|
# --ignore-unknown : saute un nom de paquet absent au lieu de refuser tout
|
||||||
|
# le lot, l'équivalent de « --skip-unavailable » côté dnf.
|
||||||
|
ZYP="sudo zypper --non-interactive"
|
||||||
|
ZYP_HELP="$(zypper install --help 2>&1 || true)"
|
||||||
|
ZYP_LIC=""
|
||||||
|
ZYP_IGN=""
|
||||||
|
case "${ZYP_HELP}" in
|
||||||
|
*--auto-agree-with-licenses*) ZYP_LIC="--auto-agree-with-licenses" ;;
|
||||||
|
esac
|
||||||
|
case "${ZYP_HELP}" in
|
||||||
|
*--ignore-unknown*) ZYP_IGN="--ignore-unknown" ;;
|
||||||
|
esac
|
||||||
|
echo "zypper : options retenues = ${ZYP_LIC} ${ZYP_IGN}"
|
||||||
|
# Lot obligatoire : un paquet manquant doit se voir.
|
||||||
|
ZYP_IN="${ZYP} install ${ZYP_LIC}"
|
||||||
|
# Lot best-effort : un nom absent est sauté.
|
||||||
|
ZYP_SOFT="${ZYP_IN} ${ZYP_IGN}"
|
||||||
|
|
||||||
|
# openSUSE remplace des paquets par des variantes « compat » qui les FOURNISSENT
|
||||||
|
# sans en porter le nom : sur Tumbleweed, zlib-ng-compat-devel fournit
|
||||||
|
# zlib-devel et se trouve posé d'office. Demander « zlib-devel » par son nom
|
||||||
|
# force alors un échange, zypper soulève un conflit — et --non-interactive n'a
|
||||||
|
# aucune solution par défaut : il énumère les choix, puis ABANDONNE le lot
|
||||||
|
# entier. C'est ce qui a arrêté l'installation sur amd64, en emportant les huit
|
||||||
|
# autres dépendances de pyenv qui, elles, ne posaient aucun problème.
|
||||||
|
# « --ignore-unknown » ne couvre que les noms absents, jamais les conflits.
|
||||||
|
#
|
||||||
|
# On ne demande donc que ce que rien ne fournit déjà. rpm interroge les
|
||||||
|
# « Provides », pas seulement les noms : c'est la seule autorité sur la
|
||||||
|
# question. Effet de bord bienvenu, une relance ne redemande plus rien.
|
||||||
|
zyp_filter() {
|
||||||
|
local p
|
||||||
|
for p in "$@"; do
|
||||||
|
rpm -q --whatprovides "${p}" > /dev/null 2>&1 || printf '%s\n' "${p}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Un telechargement tronque par le miroir fait echouer le LOT ENTIER, et
|
||||||
|
# zypper ne reessaie pas. Vecu : « libLLVM22 ... OpenSSL SSL_read: unexpected
|
||||||
|
# eof while reading » a emporte « rust cargo », et l'absence de cargo n'est
|
||||||
|
# apparue qu'une heure plus tard, dans la compilation de bcrypt. Une seconde
|
||||||
|
# tentative suffit dans la quasi-totalite des cas.
|
||||||
|
zyp_retry() {
|
||||||
|
local cmd=("$@")
|
||||||
|
"${cmd[@]}" && return 0
|
||||||
|
echo " zypper a echoue (reseau ?), seconde tentative..." >&2
|
||||||
|
"${cmd[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
zyp_in() {
|
||||||
|
local todo
|
||||||
|
mapfile -t todo < <(zyp_filter "$@")
|
||||||
|
if [ "${#todo[@]}" -eq 0 ]; then
|
||||||
|
echo " deja fourni : $*"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
zyp_retry ${ZYP_IN} "${todo[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
zyp_soft() {
|
||||||
|
local todo
|
||||||
|
mapfile -t todo < <(zyp_filter "$@")
|
||||||
|
if [ "${#todo[@]}" -eq 0 ]; then
|
||||||
|
echo " deja fourni : $*"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
zyp_retry ${ZYP_SOFT} "${todo[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Miroir des dépôts
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Le redirecteur officiel d'openSUSE n'est PAS géographique : mesuré depuis
|
||||||
|
# Montréal sur les métadonnées oss s390x (15 Mo), download.opensuse.org met
|
||||||
|
# 23,8 s — il sert depuis l'Europe — contre 2,7 s pour mirrors.rit.edu.
|
||||||
|
#
|
||||||
|
# Chaque miroir est SONDÉ sur le chemin de l'architecture courante : tous ne
|
||||||
|
# répliquent pas les architectures secondaires, et rit.edu sert justement
|
||||||
|
# zsystems mais pas x86_64. Aucun sondage concluant : on garde les dépôts de
|
||||||
|
# l'image, donc le comportement d'avant.
|
||||||
|
# Plusieurs miroirs, sondés dans l'ordre sur le chemin exact du produit et
|
||||||
|
# de l'architecture : aucun ne réplique tout. Relevé le 2026-08-12 —
|
||||||
|
# csclub sert Leap mais pas Tumbleweed, leaseweb sert Tumbleweed x86_64
|
||||||
|
# mais pas les ports zsystems, et rit.edu — seule entrée jusqu'ici — était
|
||||||
|
# injoignable ce jour-là, ce qui renvoyait tout le monde en Europe.
|
||||||
|
ZYP_MIRRORS="https://mirror.csclub.uwaterloo.ca/opensuse https://mirrors.rit.edu/opensuse https://mirror.us.leaseweb.net/opensuse"
|
||||||
|
# Leap et Tumbleweed sont deux PRODUITS, pas deux versions du même : arbres de
|
||||||
|
# dépôts différents, et surtout une mise à jour de nature différente (plus bas).
|
||||||
|
SUSE_ID="$([ -r /etc/os-release ] && . /etc/os-release && echo "${ID}")"
|
||||||
|
SUSE_VER="$([ -r /etc/os-release ] && . /etc/os-release && echo "${VERSION_ID}")"
|
||||||
|
case "${SUSE_ID}" in
|
||||||
|
*tumbleweed*) SUSE_ROLLING=1 ;;
|
||||||
|
*) SUSE_ROLLING=0 ;;
|
||||||
|
esac
|
||||||
|
if [ "${SUSE_ROLLING}" = 1 ]; then
|
||||||
|
# Tumbleweed isole les architectures secondaires sous /ports/.
|
||||||
|
zp=tumbleweed
|
||||||
|
[ "$(uname -m)" = s390x ] && zp=ports/zsystems/tumbleweed
|
||||||
|
else
|
||||||
|
# Leap 16 unifie tout : un seul arbre, avec s390x dedans. Les chemins
|
||||||
|
# /ports/ équivalents rendent 404 — relevé, pas déduit.
|
||||||
|
zp="distribution/leap/${SUSE_VER}"
|
||||||
|
fi
|
||||||
|
for zm in ${ZYP_MIRRORS}; do
|
||||||
|
if curl -fsS --max-time 20 -o /dev/null \
|
||||||
|
"${zm}/${zp}/repo/oss/repodata/repomd.xml"; then
|
||||||
|
sudo sed -i "s|https\?://download\.opensuse\.org|${zm}|g" \
|
||||||
|
/etc/zypp/repos.d/*.repo 2> /dev/null || true
|
||||||
|
echo "miroir openSUSE : ${zm}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\n---- Rafraichissement des depots ----"
|
||||||
|
# Tumbleweed est ROLLING : installer sans rafraîchir mène à des paquets
|
||||||
|
# introuvables (l'index local pointe des versions déjà retirées du miroir).
|
||||||
|
sudo zypper --non-interactive refresh || true
|
||||||
|
|
||||||
|
# Mise à jour COMPLÈTE, obligatoire pour la même raison qu'Arch : une rolling
|
||||||
|
# release ne supporte PAS les mises à jour partielles. L'image cloud est un
|
||||||
|
# instantané figé dont les dépôts ont avancé — vécu sur s390x, git 2.54
|
||||||
|
# réclamait un perl-Git bâti contre un perl-base plus ancien que celui de
|
||||||
|
# l'image. zypper proposait alors trois solutions et ATTENDAIT un choix ;
|
||||||
|
# « --non-interactive » prend le défaut, « c » = annuler, et tout s'arrêtait.
|
||||||
|
echo -e "\n---- Mise a jour complete (dup) ----"
|
||||||
|
${ZYP} dup ${ZYP_LIC} --allow-vendor-change || true
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Outils de compilation (build Python via pyenv, extensions Python)
|
||||||
|
#--------------------------------------------------
|
||||||
|
echo -e "\n---- Outils de developpement ----"
|
||||||
|
# Les compilateurs sont installés EXPLICITEMENT, jamais par le seul motif :
|
||||||
|
# un « pattern » absent ou incomplet laisserait le système sans g++, et
|
||||||
|
# l'échec n'apparaîtrait qu'à la compilation de numpy — la leçon d'EL, où le
|
||||||
|
# groupe « development-tools » n'existe pas et où le repli ne partait jamais.
|
||||||
|
# Les noms non versionnés existent bien dans Tumbleweed (relevé dans le
|
||||||
|
# primary.xml du dépôt oss) : « gcc » y est un méta-paquet qui tire gcc15.
|
||||||
|
zyp_in gcc gcc-c++ make automake patch
|
||||||
|
retVal=$?
|
||||||
|
if [[ ${retVal} -ne 0 ]]; then
|
||||||
|
echo "zypper install compilers error."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Le motif ensuite, en complément et sans jamais bloquer.
|
||||||
|
${ZYP_IN} -t pattern devel_basis > /dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Python appelle son compilateur par le nom gravé dans sysconfig, souvent
|
||||||
|
# « cc ». Sur openSUSE ce lien n'est garanti par aucune déclaration de
|
||||||
|
# paquet — vécu sur amd64 : « cc -pthread … error: [Errno 2] No such file or
|
||||||
|
# directory » à la compilation de python-ldap, alors que gcc était installé.
|
||||||
|
if ! command -v cc > /dev/null 2>&1 && command -v gcc > /dev/null 2>&1; then
|
||||||
|
sudo ln -sf "$(command -v gcc)" /usr/local/bin/cc
|
||||||
|
echo "cc -> $(command -v gcc)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# PostgreSQL
|
||||||
|
#--------------------------------------------------
|
||||||
|
echo -e "\n---- Install PostgreSQL Server ----"
|
||||||
|
zyp_in postgresql-server postgresql-contrib postgresql-server-devel
|
||||||
|
retVal=$?
|
||||||
|
if [[ ${retVal} -ne 0 ]]; then
|
||||||
|
echo "zypper install postgresql installation error."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# openSUSE n'initialise pas le cluster : le service le fait au 1er démarrage,
|
||||||
|
# mais seulement si le répertoire de données est vide.
|
||||||
|
sudo systemctl enable --now postgresql 2> /dev/null || true
|
||||||
|
# PostGIS : absent des dépôts Tumbleweed s390x. Optionnel, ne bloque pas.
|
||||||
|
zyp_soft postgis || echo "PostGIS non installe (optionnel)."
|
||||||
|
|
||||||
|
echo -e "\n---- Creating the ERPLibre PostgreSQL User ----"
|
||||||
|
sudo su - postgres -c "createuser -s ${EL_USER}" 2> /dev/null || true
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Dépendances de build (extensions Python, Odoo)
|
||||||
|
#--------------------------------------------------
|
||||||
|
echo -e "\n--- Installing suse dependency --"
|
||||||
|
# git-daemon : comme sur Fedora, « git daemon » n'est pas dans le paquet git de
|
||||||
|
# base. ERPLibre sert son manifeste par git://127.0.0.1:9418/ pendant
|
||||||
|
# « repo sync » — sans lui, « Connection refused » et synchro impossible.
|
||||||
|
# Rust n'est nécessaire QUE là où les roues manquent : bcrypt et cryptography
|
||||||
|
# portent une extension Rust, et sur amd64 leurs roues masquent le besoin. Sur
|
||||||
|
# s390x tout compile, et bcrypt s'arrête sur « error: can't find Rust
|
||||||
|
# compiler ». Tumbleweed livre 1.94, bien au-dessus du 1.78 qu'exige le
|
||||||
|
# Cargo.lock v4 de cryptography. On évite ainsi ~200 Mo inutiles sur amd64.
|
||||||
|
if [ "$(uname -m)" = "s390x" ]; then
|
||||||
|
zyp_soft rust cargo
|
||||||
|
if ! command -v cargo > /dev/null 2>&1; then
|
||||||
|
# FATAL, et non plus un simple avertissement : sur s390x, bcrypt et
|
||||||
|
# cryptography n'ont aucune roue et portent une extension Rust. Sans
|
||||||
|
# cargo l'installation est perdue d'avance — mais elle ne le montrait
|
||||||
|
# qu'une heure plus tard, au fond d'une trace pip. Mieux vaut s'arreter
|
||||||
|
# ici, ou la cause est encore lisible.
|
||||||
|
echo "cargo introuvable apres deux tentatives." >&2
|
||||||
|
echo " bcrypt et cryptography ne peuvent pas se compiler sans lui." >&2
|
||||||
|
echo " Verifiez le miroir zypper, puis relancez." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Sans roue s390x, TOUT se compile contre les en-têtes de la distribution.
|
||||||
|
# Cette liste reprend donc celles d'apt et de dnf, aux noms d'openSUSE près
|
||||||
|
# — relevés dans l'index oss de zsystems, jamais devinés. La tenir alignée
|
||||||
|
# ici plutôt que d'attendre : trois fois de suite, le même manque a été
|
||||||
|
# découvert d'abord par Debian, puis retrouvé une distribution à la fois.
|
||||||
|
# tbb-devel manifold3d refuse de configurer sans lui, et le dit dans un
|
||||||
|
# message de CMake, pas de compilateur : « Parallel mode
|
||||||
|
# enabled, but tbb was not found ».
|
||||||
|
# clang-devel pymupdf charge libclang.so par ctypes (lien juste après).
|
||||||
|
# cmake, pkgconf-pkg-config : nécessaires à el_qpdf_ensure, et ils
|
||||||
|
# n'arrivent que plus bas dans le script.
|
||||||
|
#
|
||||||
|
# « pkgconf-pkg-config » et non « pkg-config » : aucun RPM ne porte ce
|
||||||
|
# dernier nom dans Tumbleweed, il n'existe plus que comme capacité fournie
|
||||||
|
# par le premier. La capacité résout aujourd'hui, le nom réel ne dépend
|
||||||
|
# de rien.
|
||||||
|
#
|
||||||
|
# GeographicLib est absent : openSUSE n'empaquette que le binding Python,
|
||||||
|
# pas la bibliothèque C++. Rien à poser, contrairement à apt et dnf.
|
||||||
|
zyp_soft qpdf-devel libjpeg8-devel cmake pkgconf-pkg-config \
|
||||||
|
tbb-devel geos-devel proj-devel krb5-devel ninja clang-devel llvm-devel
|
||||||
|
# Tumbleweed livre qpdf 12.3.2 : l'appel ne fait que le constater. Il est là
|
||||||
|
# pour que les trois familles suivent la même règle.
|
||||||
|
el_qpdf_ensure
|
||||||
|
# pymupdf charge « libclang.so » par son nom nu, via ctypes ; le paquet ne
|
||||||
|
# livre qu'un nom versionné. Il ne manque que le lien — même correctif que
|
||||||
|
# côté apt et dnf.
|
||||||
|
for d in /usr/lib64 /usr/lib; do
|
||||||
|
if [ -d "${d}" ] && [ ! -e "${d}/libclang.so" ]; then
|
||||||
|
so="$(ls -1 "${d}"/libclang.so.* 2> /dev/null | sort -V | tail -1)"
|
||||||
|
if [ -n "${so}" ]; then
|
||||||
|
sudo ln -s "${so}" "${d}/libclang.so" && sudo ldconfig
|
||||||
|
echo "libclang.so -> ${so}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
zyp_soft \
|
||||||
|
git git-daemon wget libxslt-devel libzip-devel openldap2-devel \
|
||||||
|
cyrus-sasl-devel libffi-devel libbz2-devel gnu_parallel swig cmake \
|
||||||
|
portaudio-devel cups-devel xmlsec1 xmlsec1-openssl-devel \
|
||||||
|
libmariadb-devel freetds-devel
|
||||||
|
retVal=$?
|
||||||
|
if [[ ${retVal} -ne 0 ]]; then
|
||||||
|
echo "zypper suse tool installation error."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dépendances de build pour pyenv (compilation de CPython) — CRITIQUE.
|
||||||
|
echo -e "\n---- Dependances pyenv (compilation Python) ----"
|
||||||
|
zyp_in \
|
||||||
|
make gcc zlib-devel libbz2-devel readline-devel sqlite3-devel \
|
||||||
|
libopenssl-devel tk-devel libffi-devel xz-devel patch findutils
|
||||||
|
retVal=$?
|
||||||
|
if [[ ${retVal} -ne 0 ]]; then
|
||||||
|
echo "zypper pyenv dependencies installation error."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dépendances selenium / bindings.
|
||||||
|
zyp_soft \
|
||||||
|
cairo-devel python3-devel pkgconf-pkg-config gobject-introspection-devel \
|
||||||
|
libXt-devel || echo "Dependances selenium partielles (optionnel)."
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Node.js + npm (rtlcss, less)
|
||||||
|
#--------------------------------------------------
|
||||||
|
echo -e "\n---- Installing nodeJS NPM and rtlcss ----"
|
||||||
|
# openSUSE versionne les paquets node (nodejs22, nodejs24…) et ne fournit pas
|
||||||
|
# toujours de méta-paquet « nodejs ». On prend le plus récent disponible.
|
||||||
|
NODE_OK=0
|
||||||
|
for pkg in nodejs24 nodejs22 nodejs20 nodejs; do
|
||||||
|
if ${ZYP_IN} "${pkg}" "${pkg/nodejs/npm}" 2> /dev/null; then
|
||||||
|
NODE_OK=1
|
||||||
|
echo "node fourni par ${pkg}"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ ${NODE_OK} -ne 1 ]] || ! command -v npm > /dev/null 2>&1; then
|
||||||
|
echo "zypper nodejs installation error."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sudo npm install -g rtlcss less || echo "npm rtlcss/less: erreur (optionnel)."
|
||||||
|
|
||||||
|
echo -e "\n---- Test tool ----"
|
||||||
|
npm install || echo "npm install (prettier/plugin-xml): erreur (optionnel)."
|
||||||
|
sudo ln -fs /usr/local/bin/lessc /usr/bin/lessc 2> /dev/null || true
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# nginx (optionnel)
|
||||||
|
#--------------------------------------------------
|
||||||
|
if [ "${EL_INSTALL_NGINX}" = "True" ]; then
|
||||||
|
echo -e "\n---- Installing nginx ----"
|
||||||
|
zyp_soft nginx || echo "nginx: erreur (optionnel)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# wkhtmltopdf (optionnel)
|
||||||
|
#--------------------------------------------------
|
||||||
|
if [ "${EL_INSTALL_WKHTMLTOPDF}" = "True" ]; then
|
||||||
|
if ! command -v wkhtmltopdf > /dev/null 2>&1; then
|
||||||
|
echo -e "\n---- Installing wkhtml (best-effort) ----"
|
||||||
|
# wkhtmltopdf ne publie AUCUN paquet openSUSE. Le dépôt de la distribution
|
||||||
|
# fournit « wkhtmltopdf » quand il existe pour l'architecture ; sinon on
|
||||||
|
# renonce, Odoo sait imprimer sans lui (rendu dégradé des PDF).
|
||||||
|
zyp_soft wkhtmltopdf || echo "wkhtmltopdf non installe (optionnel)."
|
||||||
|
else
|
||||||
|
echo -e "\n---- Already installed wkhtml ----"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n---- SUSE dependency installation done ----"
|
||||||
|
|
@ -182,11 +182,16 @@ Catalog, per architecture (`deploy_qemu.py` is the source of truth):
|
||||||
| fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | `43` only |
|
| fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | `43` only |
|
||||||
| almalinux | `9` (default), `10` | ✔ | ✔ | ✔ |
|
| almalinux | `9` (default), `10` | ✔ | ✔ | ✔ |
|
||||||
| rocky | `9`, `10` (default) | ✔ | ✔ | ✔ |
|
| rocky | `9`, `10` (default) | ✔ | ✔ | ✔ |
|
||||||
|
| opensuse | `tumbleweed` | ✔ | ✔ | ✔ |
|
||||||
| arch | `latest` | ✔ | — | — |
|
| arch | `latest` | ✔ | — | — |
|
||||||
|
|
||||||
Fedora builds s390x only for the current release, and on a separate tree
|
Fedora builds s390x only for the current release, and on a separate tree
|
||||||
(`fedora-secondary`) — hence the single version there.
|
(`fedora-secondary`) — hence the single version there.
|
||||||
|
|
||||||
|
`opensuse` is openSUSE Tumbleweed, the only entry whose qpdf (12.3.2) already
|
||||||
|
clears the pikepdf threshold: the half-hour qpdf build never runs there, which
|
||||||
|
matters under s390x emulation.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
@ -207,11 +212,16 @@ Catalogue, par architecture (`deploy_qemu.py` fait autorité) :
|
||||||
| fedora | `41`, `42` (défaut), `43`, `44` | ✔ | ✔ | `43` seule |
|
| 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) | ✔ | ✔ | ✔ |
|
||||||
|
| opensuse | `tumbleweed` | ✔ | ✔ | ✔ |
|
||||||
| arch | `latest` | ✔ | — | — |
|
| arch | `latest` | ✔ | — | — |
|
||||||
|
|
||||||
Fedora ne construit s390x que pour la version courante, et sur une
|
Fedora ne construit s390x que pour la version courante, et sur une
|
||||||
arborescence à part (`fedora-secondary`) — d'où la version unique.
|
arborescence à part (`fedora-secondary`) — d'où la version unique.
|
||||||
|
|
||||||
|
`opensuse` désigne openSUSE Tumbleweed, seule entrée dont qpdf (12.3.2)
|
||||||
|
dépasse déjà le seuil de pikepdf : la compilation de qpdf, une demi-heure, ne
|
||||||
|
s'y déclenche jamais — ce qui compte sous émulation s390x.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,11 +101,16 @@ Catalogue, par architecture (`deploy_qemu.py` fait autorité) :
|
||||||
| fedora | `41`, `42` (défaut), `43`, `44` | ✔ | ✔ | `43` seule |
|
| 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) | ✔ | ✔ | ✔ |
|
||||||
|
| opensuse | `tumbleweed` | ✔ | ✔ | ✔ |
|
||||||
| arch | `latest` | ✔ | — | — |
|
| arch | `latest` | ✔ | — | — |
|
||||||
|
|
||||||
Fedora ne construit s390x que pour la version courante, et sur une
|
Fedora ne construit s390x que pour la version courante, et sur une
|
||||||
arborescence à part (`fedora-secondary`) — d'où la version unique.
|
arborescence à part (`fedora-secondary`) — d'où la version unique.
|
||||||
|
|
||||||
|
`opensuse` désigne openSUSE Tumbleweed, seule entrée dont qpdf (12.3.2)
|
||||||
|
dépasse déjà le seuil de pikepdf : la compilation de qpdf, une demi-heure, ne
|
||||||
|
s'y déclenche jamais — ce qui compte sous émulation s390x.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,11 +95,16 @@ Catalog, per architecture (`deploy_qemu.py` is the source of truth):
|
||||||
| fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | `43` only |
|
| fedora | `41`, `42` (default), `43`, `44` | ✔ | ✔ | `43` only |
|
||||||
| almalinux | `9` (default), `10` | ✔ | ✔ | ✔ |
|
| almalinux | `9` (default), `10` | ✔ | ✔ | ✔ |
|
||||||
| rocky | `9`, `10` (default) | ✔ | ✔ | ✔ |
|
| rocky | `9`, `10` (default) | ✔ | ✔ | ✔ |
|
||||||
|
| opensuse | `tumbleweed` | ✔ | ✔ | ✔ |
|
||||||
| arch | `latest` | ✔ | — | — |
|
| arch | `latest` | ✔ | — | — |
|
||||||
|
|
||||||
Fedora builds s390x only for the current release, and on a separate tree
|
Fedora builds s390x only for the current release, and on a separate tree
|
||||||
(`fedora-secondary`) — hence the single version there.
|
(`fedora-secondary`) — hence the single version there.
|
||||||
|
|
||||||
|
`opensuse` is openSUSE Tumbleweed, the only entry whose qpdf (12.3.2) already
|
||||||
|
clears the pikepdf threshold: the half-hour qpdf build never runs there, which
|
||||||
|
matters under s390x emulation.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,12 @@ ROCKY_VERSIONS: dict[str, tuple[str, str, int, str]] = {
|
||||||
"9": ("9", "rocky9", 2048, "20G"),
|
"9": ("9", "rocky9", 2048, "20G"),
|
||||||
"10": ("10", "rocky10", 2048, "20G"),
|
"10": ("10", "rocky10", 2048, "20G"),
|
||||||
}
|
}
|
||||||
|
# openSUSE Tumbleweed : rolling, donc une seule « version ». C'est la seule
|
||||||
|
# distribution du catalogue dont qpdf (12.3.2) dépasse déjà le seuil de
|
||||||
|
# pikepdf 10 — aucune compilation de qpdf, ce qui change tout sous émulation.
|
||||||
|
OPENSUSE_VERSIONS: dict[str, tuple[str, str, int, str]] = {
|
||||||
|
"tumbleweed": ("tumbleweed", "opensusetumbleweed", 2048, "20G"),
|
||||||
|
}
|
||||||
# Arch est en rolling release : une seule « version » (latest).
|
# Arch est en rolling release : une seule « version » (latest).
|
||||||
ARCH_VERSIONS: dict[str, tuple[str, str, int, str]] = {
|
ARCH_VERSIONS: dict[str, tuple[str, str, int, str]] = {
|
||||||
"latest": ("latest", "archlinux", 1024, "20G"),
|
"latest": ("latest", "archlinux", 1024, "20G"),
|
||||||
|
|
@ -125,6 +131,7 @@ DISTROS: dict[str, tuple[dict[str, tuple[str, str, int, str]], str]] = {
|
||||||
"fedora": (FEDORA_VERSIONS, "42"),
|
"fedora": (FEDORA_VERSIONS, "42"),
|
||||||
"almalinux": (ALMALINUX_VERSIONS, "9"),
|
"almalinux": (ALMALINUX_VERSIONS, "9"),
|
||||||
"rocky": (ROCKY_VERSIONS, "10"),
|
"rocky": (ROCKY_VERSIONS, "10"),
|
||||||
|
"opensuse": (OPENSUSE_VERSIONS, "tumbleweed"),
|
||||||
"arch": (ARCH_VERSIONS, "latest"),
|
"arch": (ARCH_VERSIONS, "latest"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,6 +141,7 @@ ARCH_ALIASES: dict[str, dict[str, str]] = {
|
||||||
"fedora": {"amd64": "x86_64", "arm64": "aarch64"},
|
"fedora": {"amd64": "x86_64", "arm64": "aarch64"},
|
||||||
"almalinux": {"amd64": "x86_64", "arm64": "aarch64"},
|
"almalinux": {"amd64": "x86_64", "arm64": "aarch64"},
|
||||||
"rocky": {"amd64": "x86_64", "arm64": "aarch64"},
|
"rocky": {"amd64": "x86_64", "arm64": "aarch64"},
|
||||||
|
"opensuse": {"amd64": "x86_64", "arm64": "aarch64"},
|
||||||
"arch": {"amd64": "x86_64", "arm64": "aarch64"},
|
"arch": {"amd64": "x86_64", "arm64": "aarch64"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,7 +154,13 @@ 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", "fedora")
|
S390X_DISTROS: tuple[str, ...] = (
|
||||||
|
"ubuntu",
|
||||||
|
"almalinux",
|
||||||
|
"rocky",
|
||||||
|
"fedora",
|
||||||
|
"opensuse",
|
||||||
|
)
|
||||||
|
|
||||||
# Une distro peut ne publier qu'une PARTIE de ses versions sur une
|
# Une distro peut ne publier qu'une PARTIE de ses versions sur une
|
||||||
# architecture. Déclaration POSITIVE : hors de cette table, toutes les versions
|
# architecture. Déclaration POSITIVE : hors de cette table, toutes les versions
|
||||||
|
|
@ -173,6 +187,7 @@ ARM64_DISTROS: tuple[str, ...] = (
|
||||||
"fedora",
|
"fedora",
|
||||||
"almalinux",
|
"almalinux",
|
||||||
"rocky",
|
"rocky",
|
||||||
|
"opensuse",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -211,6 +226,7 @@ DEBIAN_CLOUD_BASES: tuple[str, ...] = (
|
||||||
"https://laotzu.ftp.acc.umu.se/cdimage/cloud",
|
"https://laotzu.ftp.acc.umu.se/cdimage/cloud",
|
||||||
)
|
)
|
||||||
ALMALINUX_CLOUD_BASE = "https://repo.almalinux.org/almalinux"
|
ALMALINUX_CLOUD_BASE = "https://repo.almalinux.org/almalinux"
|
||||||
|
OPENSUSE_BASE = "https://download.opensuse.org"
|
||||||
ROCKY_CLOUD_BASE = "https://dl.rockylinux.org/pub/rocky"
|
ROCKY_CLOUD_BASE = "https://dl.rockylinux.org/pub/rocky"
|
||||||
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
|
# Serveur MAÎTRE (pas de redirection MirrorManager) : repli fiable quand le
|
||||||
|
|
@ -287,6 +303,18 @@ def image_candidates(
|
||||||
f"{ROCKY_CLOUD_BASE}/{version}/images/{a}/"
|
f"{ROCKY_CLOUD_BASE}/{version}/images/{a}/"
|
||||||
f"Rocky-{version}-GenericCloud.latest.{a}.qcow2"
|
f"Rocky-{version}-GenericCloud.latest.{a}.qcow2"
|
||||||
]
|
]
|
||||||
|
if distro == "opensuse":
|
||||||
|
# Les architectures secondaires vivent sous /ports/, et zsystems DOUBLE
|
||||||
|
# l'architecture dans le nom du fichier — irrégularité vérifiée dans
|
||||||
|
# l'index, pas déduite : « .s390x-s390x-Cloud » contre « .x86_64-Cloud ».
|
||||||
|
port = {"s390x": "ports/zsystems/", "arm64": "ports/aarch64/"}.get(
|
||||||
|
arch, ""
|
||||||
|
)
|
||||||
|
tag = f"{a}-{a}" if arch == "s390x" else a
|
||||||
|
return [
|
||||||
|
f"{OPENSUSE_BASE}/{port}tumbleweed/appliances/"
|
||||||
|
f"openSUSE-Tumbleweed-Minimal-VM.{tag}-Cloud.qcow2"
|
||||||
|
]
|
||||||
if distro == "arch":
|
if distro == "arch":
|
||||||
# Rolling release : image « latest » officielle (cloud-init inclus).
|
# Rolling release : image « latest » officielle (cloud-init inclus).
|
||||||
return [f"{ARCH_CLOUD_BASE}/Arch-Linux-{a}-cloudimg.qcow2"]
|
return [f"{ARCH_CLOUD_BASE}/Arch-Linux-{a}-cloudimg.qcow2"]
|
||||||
|
|
@ -346,6 +374,8 @@ def default_image_name(distro: str, code: str, arch: str, version: str) -> str:
|
||||||
return f"debian-{version}-genericcloud-{a}.qcow2"
|
return f"debian-{version}-genericcloud-{a}.qcow2"
|
||||||
if distro == "arch":
|
if distro == "arch":
|
||||||
return f"arch-linux-{a}-cloudimg.qcow2"
|
return f"arch-linux-{a}-cloudimg.qcow2"
|
||||||
|
if distro == "opensuse":
|
||||||
|
return f"opensuse-tumbleweed-minimal-vm-{a}.qcow2"
|
||||||
if distro in ("almalinux", "rocky"):
|
if distro in ("almalinux", "rocky"):
|
||||||
# « latest » est MUTABLE : le nom de cache porte donc la majeure, et
|
# « latest » est MUTABLE : le nom de cache porte donc la majeure, et
|
||||||
# une image déjà téléchargée sera réutilisée telle quelle. C'est voulu
|
# une image déjà téléchargée sera réutilisée telle quelle. C'est voulu
|
||||||
|
|
@ -1374,12 +1404,25 @@ def host_timezone() -> str:
|
||||||
return "UTC"
|
return "UTC"
|
||||||
|
|
||||||
|
|
||||||
def admin_group(distro: str) -> str:
|
def user_groups(distro: str) -> str:
|
||||||
"""Groupe d'administration de la distribution.
|
"""Groupes secondaires du compte créé par cloud-init.
|
||||||
|
|
||||||
Debian et Ubuntu : « sudo ». Famille RHEL (AlmaLinux, Rocky, Fedora) et
|
Le nom du groupe d'administration change d'une famille à l'autre, et un
|
||||||
Arch : « wheel » — elles n'ont aucun groupe « sudo »."""
|
nom INCONNU fait échouer « useradd -G » : l'utilisateur n'est alors pas
|
||||||
return "sudo" if distro in ("ubuntu", "debian") else "wheel"
|
créé du tout, donc ni mot de passe ni clé SSH, et la VM démarre
|
||||||
|
inaccessible. Le privilège vient de toute façon de la directive « sudo: »
|
||||||
|
du cloud-config, pas du groupe — celui-ci n'est qu'une commodité.
|
||||||
|
|
||||||
|
- Debian, Ubuntu : « sudo ».
|
||||||
|
- Famille RHEL (AlmaLinux, Rocky, CentOS, Fedora), Arch : « wheel ».
|
||||||
|
- openSUSE : aucun. Son cloud-init par défaut n'en met pas, et rien ne
|
||||||
|
garantit « wheel » sur une image Minimal-VM — dans le doute on s'abstient
|
||||||
|
plutôt que de risquer un compte non créé."""
|
||||||
|
if distro in ("ubuntu", "debian"):
|
||||||
|
return "users, sudo"
|
||||||
|
if distro == "opensuse":
|
||||||
|
return "users"
|
||||||
|
return "users, wheel"
|
||||||
|
|
||||||
|
|
||||||
def build_cloud_config(
|
def build_cloud_config(
|
||||||
|
|
@ -1400,7 +1443,7 @@ def build_cloud_config(
|
||||||
# même écart, elles n'ont pas de groupe « sudo » mais « wheel ».
|
# même écart, elles n'ont pas de groupe « sudo » mais « wheel ».
|
||||||
# Le privilège lui-même vient de la ligne « sudo: » ci-dessus, pas du
|
# Le privilège lui-même vient de la ligne « sudo: » ci-dessus, pas du
|
||||||
# groupe : celui-ci n'est qu'une commodité.
|
# groupe : celui-ci n'est qu'une commodité.
|
||||||
f" groups: users, {admin_group(args.distro)}",
|
f" groups: {user_groups(args.distro)}",
|
||||||
" shell: /bin/bash",
|
" shell: /bin/bash",
|
||||||
" lock_passwd: false" if pw_hash else " lock_passwd: true",
|
" lock_passwd: false" if pw_hash else " lock_passwd: true",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1027,6 +1027,7 @@ class TODO:
|
||||||
"fedora": (["41", "42", "43", "44"], "42"),
|
"fedora": (["41", "42", "43", "44"], "42"),
|
||||||
"almalinux": (["9", "10"], "9"),
|
"almalinux": (["9", "10"], "9"),
|
||||||
"rocky": (["9", "10"], "10"),
|
"rocky": (["9", "10"], "10"),
|
||||||
|
"opensuse": (["tumbleweed"], "tumbleweed"),
|
||||||
"arch": (["latest"], "latest"),
|
"arch": (["latest"], "latest"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1074,13 +1075,20 @@ 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", "fedora")
|
_QEMU_S390X_DISTROS = (
|
||||||
|
"ubuntu",
|
||||||
|
"almalinux",
|
||||||
|
"rocky",
|
||||||
|
"fedora",
|
||||||
|
"opensuse",
|
||||||
|
)
|
||||||
_QEMU_ARM64_DISTROS = (
|
_QEMU_ARM64_DISTROS = (
|
||||||
"ubuntu",
|
"ubuntu",
|
||||||
"debian",
|
"debian",
|
||||||
"fedora",
|
"fedora",
|
||||||
"almalinux",
|
"almalinux",
|
||||||
"rocky",
|
"rocky",
|
||||||
|
"opensuse",
|
||||||
)
|
)
|
||||||
# Alias distro pour l'affichage (jeton générique -> nom courant).
|
# Alias distro pour l'affichage (jeton générique -> nom courant).
|
||||||
_QEMU_ARCH_ALIAS = {"amd64": "x86_64", "arm64": "aarch64"}
|
_QEMU_ARCH_ALIAS = {"amd64": "x86_64", "arm64": "aarch64"}
|
||||||
|
|
@ -4325,6 +4333,7 @@ class TODO:
|
||||||
"dnf_env": "graphical-server-environment "
|
"dnf_env": "graphical-server-environment "
|
||||||
"workstation-product-environment gnome-desktop",
|
"workstation-product-environment gnome-desktop",
|
||||||
"pacman": "gnome gdm",
|
"pacman": "gnome gdm",
|
||||||
|
"zypper": "patterns-gnome-gnome_basic gdm",
|
||||||
"service": "gdm",
|
"service": "gdm",
|
||||||
},
|
},
|
||||||
"cinnamon": {
|
"cinnamon": {
|
||||||
|
|
@ -4336,6 +4345,7 @@ class TODO:
|
||||||
"apt": "cinnamon-desktop-environment dbus-x11",
|
"apt": "cinnamon-desktop-environment dbus-x11",
|
||||||
"dnf_env": "cinnamon-desktop",
|
"dnf_env": "cinnamon-desktop",
|
||||||
"pacman": "cinnamon lightdm lightdm-gtk-greeter",
|
"pacman": "cinnamon lightdm lightdm-gtk-greeter",
|
||||||
|
"zypper": "cinnamon lightdm",
|
||||||
"service": "lightdm",
|
"service": "lightdm",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -4344,6 +4354,7 @@ class TODO:
|
||||||
"apt": {"packages": "xrdp", "port": 3389, "client": "RDP"},
|
"apt": {"packages": "xrdp", "port": 3389, "client": "RDP"},
|
||||||
"dnf": {"packages": "xrdp", "port": 3389, "client": "RDP"},
|
"dnf": {"packages": "xrdp", "port": 3389, "client": "RDP"},
|
||||||
"pacman": {"packages": "tigervnc", "port": 5901, "client": "VNC"},
|
"pacman": {"packages": "tigervnc", "port": 5901, "client": "VNC"},
|
||||||
|
"zypper": {"packages": "xrdp", "port": 3389, "client": "RDP"},
|
||||||
}
|
}
|
||||||
# Place que prend un bureau complet, annoncée dans le plan : sur une image
|
# Place que prend un bureau complet, annoncée dans le plan : sur une image
|
||||||
# cloud de 40 G, l'oublier remplit le disque en pleine installation.
|
# cloud de 40 G, l'oublier remplit le disque en pleine installation.
|
||||||
|
|
@ -4408,6 +4419,44 @@ class TODO:
|
||||||
">/dev/null 2>&1 || true; "
|
">/dev/null 2>&1 || true; "
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Miroirs openSUSE préférés, du plus proche au dernier recours. Le
|
||||||
|
# redirecteur officiel n'est PAS géographique pour cette distribution :
|
||||||
|
# mesuré depuis Montréal sur les métadonnées oss s390x (15 Mo),
|
||||||
|
# download.opensuse.org met 23,8 s — il sert depuis l'Europe — contre
|
||||||
|
# 2,7 s pour mirrors.rit.edu. Les trois familles dnf, elles, choisissent
|
||||||
|
# déjà un miroir canadien toutes seules ; rien à faire de ce côté.
|
||||||
|
#
|
||||||
|
# Chaque miroir est SONDÉ sur le chemin de l'architecture ET du produit
|
||||||
|
# courants, puis le premier qui répond gagne. C'est nécessaire : aucun ne
|
||||||
|
# réplique tout. Relevé le 2026-08-12 —
|
||||||
|
# csclub Leap oui, Tumbleweed non (404)
|
||||||
|
# rit.edu zsystems oui ; injoignable ce jour-là (curl 7)
|
||||||
|
# leaseweb Tumbleweed x86_64 et Leap oui, ports zsystems non
|
||||||
|
# D'où plusieurs entrées plutôt qu'une : avec la seule rit.edu, sa panne
|
||||||
|
# renvoyait tout le monde sur download.opensuse.org, servi d'Europe.
|
||||||
|
# Ordonnées par proximité de Montréal. Aucun sondage concluant : on garde
|
||||||
|
# les dépôts de l'image, donc le comportement d'avant.
|
||||||
|
_QEMU_ZYPPER_MIRRORS = (
|
||||||
|
"https://mirror.csclub.uwaterloo.ca/opensuse",
|
||||||
|
"https://mirrors.rit.edu/opensuse",
|
||||||
|
"https://mirror.us.leaseweb.net/opensuse",
|
||||||
|
)
|
||||||
|
|
||||||
|
def _qemu_zypper_mirror_cmd(self):
|
||||||
|
"""Réécrit l'hôte des dépôts zypper vers un miroir plus proche."""
|
||||||
|
mirrors = " ".join(self._QEMU_ZYPPER_MIRRORS)
|
||||||
|
return (
|
||||||
|
"zp=tumbleweed; "
|
||||||
|
'[ "$(uname -m)" = s390x ] && zp=ports/zsystems/tumbleweed; '
|
||||||
|
f"for zm in {mirrors}; do "
|
||||||
|
"if curl -fsS --max-time 20 -o /dev/null "
|
||||||
|
'"$zm/$zp/repo/oss/repodata/repomd.xml"; then '
|
||||||
|
"sudo sed -i "
|
||||||
|
'"s|https\\?://download\\.opensuse\\.org|$zm|g" '
|
||||||
|
"/etc/zypp/repos.d/*.repo 2>/dev/null || true; "
|
||||||
|
f'echo " {t("openSUSE mirror:")} $zm"; break; fi; done; '
|
||||||
|
)
|
||||||
|
|
||||||
def _qemu_desktop_remote_cmd(self, flavour="gnome"):
|
def _qemu_desktop_remote_cmd(self, flavour="gnome"):
|
||||||
"""Bloc shell installant le bureau choisi + son accès distant, quelle
|
"""Bloc shell installant le bureau choisi + son accès distant, quelle
|
||||||
que soit la distribution. Même aiguillage que l'installation ERPLibre,
|
que soit la distribution. Même aiguillage que l'installation ERPLibre,
|
||||||
|
|
@ -4440,6 +4489,14 @@ class TODO:
|
||||||
"|| sudo rm -f /var/lib/pacman/db.lck; "
|
"|| sudo rm -f /var/lib/pacman/db.lck; "
|
||||||
f"sudo pacman -S --needed --noconfirm {de['pacman']} "
|
f"sudo pacman -S --needed --noconfirm {de['pacman']} "
|
||||||
f"{rem['pacman']['packages']}; "
|
f"{rem['pacman']['packages']}; "
|
||||||
|
"elif command -v zypper >/dev/null 2>&1; then "
|
||||||
|
"sudo zypper --non-interactive refresh || true; "
|
||||||
|
# « --auto-agree-with-licenses » appartient à la SOUS-COMMANDE
|
||||||
|
# install, pas aux options globales : placé avant, zypper répond
|
||||||
|
# « The flag --auto-agree-with-licenses is not known ».
|
||||||
|
"sudo zypper --non-interactive install "
|
||||||
|
f"--auto-agree-with-licenses {de['zypper']} "
|
||||||
|
f"{rem['zypper']['packages']}; "
|
||||||
"else echo 'Gestionnaire de paquets inconnu'; exit 1; fi; "
|
"else echo 'Gestionnaire de paquets inconnu'; exit 1; fi; "
|
||||||
# Le bureau ne sert à rien s'il ne démarre pas tout seul : les
|
# Le bureau ne sert à rien s'il ne démarre pas tout seul : les
|
||||||
# images cloud démarrent en multi-user.target.
|
# images cloud démarrent en multi-user.target.
|
||||||
|
|
@ -4550,10 +4607,29 @@ class TODO:
|
||||||
"--save /etc/pacman.d/mirrorlist || true; "
|
"--save /etc/pacman.d/mirrorlist || true; "
|
||||||
"sudo pacman -Syu --noconfirm || true; "
|
"sudo pacman -Syu --noconfirm || true; "
|
||||||
"sudo pacman -S --needed --noconfirm $PKGS; "
|
"sudo pacman -S --needed --noconfirm $PKGS; "
|
||||||
|
"elif command -v zypper >/dev/null 2>&1; then "
|
||||||
|
# openSUSE : « --non-interactive » vaut le -y des autres, et
|
||||||
|
# « --auto-agree-with-licenses », qui va APRÈS « install »,
|
||||||
|
# évite un blocage sur une licence à accepter.
|
||||||
|
# Tumbleweed étant rolling, on rafraîchit avant d'installer.
|
||||||
|
+ self._qemu_zypper_mirror_cmd()
|
||||||
|
+ "sudo zypper --non-interactive refresh || true; "
|
||||||
|
# Tumbleweed est ROLLING et ne supporte pas les mises à jour
|
||||||
|
# partielles, exactement comme Arch. L'image cloud est un
|
||||||
|
# instantané figé : ses dépôts ont avancé depuis, et un
|
||||||
|
# « install » simple bute sur une incohérence — vécu, git 2.54
|
||||||
|
# réclamait perl-Git bâti contre un perl-base plus ancien que
|
||||||
|
# celui de l'image. zypper proposait alors trois solutions et
|
||||||
|
# attendait un choix ; « --non-interactive » prend le défaut,
|
||||||
|
# « c » = annuler, et l'installation s'arrêtait là.
|
||||||
|
"sudo zypper --non-interactive dup --auto-agree-with-licenses "
|
||||||
|
"--allow-vendor-change || true; "
|
||||||
|
"sudo zypper --non-interactive install "
|
||||||
|
"--auto-agree-with-licenses $PKGS; "
|
||||||
"elif command -v yum >/dev/null 2>&1; then "
|
"elif command -v yum >/dev/null 2>&1; then "
|
||||||
"sudo yum makecache -q || true; sudo yum install -y $PKGS; "
|
"sudo yum makecache -q || true; sudo yum install -y $PKGS; "
|
||||||
"else echo 'Aucun gestionnaire de paquets "
|
"else echo 'Aucun gestionnaire de paquets "
|
||||||
"(apt/dnf/pacman/yum)'; exit 1; fi; "
|
"(apt/dnf/pacman/zypper/yum)'; exit 1; fi; "
|
||||||
# Vérifie explicitement que tout est là : erreur nette plutôt
|
# Vérifie explicitement que tout est là : erreur nette plutôt
|
||||||
# qu'un « command not found » cryptique plus loin.
|
# qu'un « command not found » cryptique plus loin.
|
||||||
"for t in curl git make; do command -v $t >/dev/null 2>&1 || "
|
"for t in curl git make; do command -v $t >/dev/null 2>&1 || "
|
||||||
|
|
|
||||||
|
|
@ -2055,6 +2055,10 @@ TRANSLATIONS = {
|
||||||
"fr": "Installation du bureau GNOME (long)",
|
"fr": "Installation du bureau GNOME (long)",
|
||||||
"en": "Installing the GNOME desktop (long)",
|
"en": "Installing the GNOME desktop (long)",
|
||||||
},
|
},
|
||||||
|
"openSUSE mirror:": {
|
||||||
|
"fr": "miroir openSUSE :",
|
||||||
|
"en": "openSUSE mirror:",
|
||||||
|
},
|
||||||
"Remote desktop:": {
|
"Remote desktop:": {
|
||||||
"fr": "Bureau distant :",
|
"fr": "Bureau distant :",
|
||||||
"en": "Remote desktop:",
|
"en": "Remote desktop:",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue