feat(anaconda): add hostname field to user spoke and fix keyboard layout by territory

Replace keyboard correction logic in kickstart with anaconda package patches:

- Add "Nom de machine" (hostname) field to the User spoke in anaconda GUI
- user.py writes the hostname value to /tmp/fws-hostname for the kickstart %post
- Simplify kickstart to read from /tmp/fws-hostname instead of live hostname
- Fix keyboard layout selection to use full locale (e.g. fr_CH) instead of just language (fr)
  to correctly derive territory-specific keymaps (ch(fr) for Switzerland, not fr for France)
- Remove outdated fix_keyboard() function from kickstart

Also add --network=host flag to podman run in setup-aur.sh to ensure DNS and internet
connectivity through the host stack instead of the bridge (fixes timeout issues on
certain networks with firewalld/NAT).

Bump anaconda pkgrel from 2 to 4.
This commit is contained in:
2026-06-23 10:48:32 +02:00
parent 1184ba17d9
commit 7d6bba42b2
3 changed files with 115 additions and 51 deletions
@@ -89,17 +89,15 @@ SYSROOT=/mnt/sysroot
# DNS pour que « pacman -S <bureau> » fonctionne dans le chroot.
cp -f /etc/resolv.conf "$SYSROOT/etc/resolv.conf" 2>/dev/null || true
# --- Hostname : reprendre celui saisi dans Anaconda, sinon « fws » -----------
# BUG observé : Anaconda écrit un /etc/hostname VIDE dans la cible (le hostname
# du spoke Réseau n'est pas capté). On reprend donc le hostname COURANT du LIVE
# (Anaconda l'applique au live quand on le saisit dans le spoke) s'il diffère du
# défaut archiso, sinon on pose un défaut propre « fws » — jamais de hostname
# vide. (Ce %post tourne APRÈS l'écriture d'Anaconda → on écrase son fichier
# vide.)
HN="$(cat /proc/sys/kernel/hostname 2>/dev/null)"
case "$HN" in
""|archlinux|localhost|localhost.localdomain) HN="fws" ;;
esac
# --- Hostname : valeur saisie dans le champ « Nom de machine » du spoke User --
# Anaconda ne capte PAS le hostname du spoke Réseau (→ /etc/hostname vide). On a
# donc ajouté un champ Hostname au spoke Utilisateur (cf. patch du paquet
# anaconda) : user.py écrit la valeur dans /tmp/fws-hostname (live). On la
# nettoie (caractères de hostname valides) et on l'écrit dans la cible ; défaut
# « fws » si vide/absent → plus jamais de hostname vide ni « archiso ».
HN=""
[ -f /tmp/fws-hostname ] && HN="$(tr -cd 'a-zA-Z0-9._-' < /tmp/fws-hostname)"
[ -n "$HN" ] || HN="fws"
echo "$HN" > "$SYSROOT/etc/hostname"
# Choix du bureau (écrit par l'addon « Choix du bureau », à venir ; valeur lue
@@ -207,44 +205,6 @@ else
echo "[FWS] AVERTISSEMENT : grub-install a échoué — bootloader à refaire à la main"
fi
# --- 3bis) Clavier : corriger le keymap selon le TERRITOIRE de la locale ------
# BUG observé : Anaconda dérive le clavier de la LANGUE en IGNORANT le territoire
# → fr_CH (Suisse) donne « fr » (France) au lieu du clavier SUISSE. On corrige :
# si un keymap console spécifique au territoire existe (fr_CH, de_CH…), on
# l'impose dans /etc/vconsole.conf, et on règle aussi le clavier X11 (pour un
# bureau installé ensuite) via langtable. Locale lue dans /etc/locale.conf, à
# défaut dans /root/anaconda-ks.cfg (« lang … »).
fix_keyboard() {
local langv loc lng terr font xk xl xv
langv="$(. /etc/locale.conf 2>/dev/null; printf '%s' "${LANG:-}")"
[ -n "$langv" ] || langv="$(sed -n 's/^lang[[:space:]]\+//p' /root/anaconda-ks.cfg 2>/dev/null | head -1)"
loc="${langv%%.*}" # fr_CH.UTF-8 → fr_CH
lng="${loc%%_*}" # fr
terr="${loc#*_}"; [ "$terr" = "$loc" ] && terr="" # CH
[ -n "$terr" ] || return 0
find /usr/share/kbd/keymaps -name "${lng}_${terr}.map.gz" 2>/dev/null | grep -q . || return 0
# vconsole (console TTY) : keymap du territoire (ex. fr_CH). On préserve FONT.
font="$(grep '^FONT=' /etc/vconsole.conf 2>/dev/null)"
{ echo "KEYMAP=${lng}_${terr}"; [ -n "$font" ] && echo "$font"; } > /etc/vconsole.conf
# X11 (bureau) : layout/variant via langtable (ex. fr_CH → 'ch(fr)' → ch/fr).
xk="$(python3 -c "import langtable; k=langtable.list_keyboards(languageId='$lng', territoryId='$terr'); print(k[0] if k else '')" 2>/dev/null)"
case "$xk" in
*'('*')') xl="${xk%%(*}"; xv="${xk#*(}"; xv="${xv%)}" ;;
?*) xl="$xk"; xv="" ;;
*) return 0 ;;
esac
mkdir -p /etc/X11/xorg.conf.d
cat > /etc/X11/xorg.conf.d/00-keyboard.conf <<EOF
Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbLayout" "$xl"
Option "XkbVariant" "$xv"
EndSection
EOF
}
fix_keyboard || echo "[FWS] clavier : ajustement territoire ignoré"
# --- 4) Bureau choisi : pacman -S du DE (non bloquant si pas de réseau) -------
DESK="cli"
[ -f /tmp/fws-desktop ] && DESK="$(tr -d '[:space:]' < /tmp/fws-desktop)"
+102 -1
View File
@@ -25,7 +25,7 @@
# ============================================================================
pkgname=anaconda
pkgver=45.8
pkgrel=2
pkgrel=4
pkgdesc="The Anaconda installer (porté sur Arch pour FWS, payload liveimg)"
arch=('x86_64')
url="https://github.com/rhinstaller/anaconda"
@@ -57,6 +57,107 @@ source=("anaconda-$pkgver.tar.gz::https://github.com/rhinstaller/anaconda/archiv
sha256sums=('5ef1464bff7f28a4a09a821cbb0121f09ef504ec169288d742373f86807ec4ed')
_srcdir="anaconda-anaconda-$pkgver"
prepare() {
cd "$srcdir/$_srcdir"
# ── FWS : clavier par défaut selon le TERRITOIRE de la locale ──────────────
# set_layouts() amont fait « locale = get_language_id(self.language) » →
# get_language_id JETTE le territoire (fr_CH.UTF-8 → 'fr') → list_keyboards('fr')
# = 'fr(oss)' (France) au lieu de 'ch(fr)' (Suisse). On passe la LOCALE COMPLÈTE
# (self.language) : langtable.list_keyboards('fr_CH.UTF-8') = 'ch(fr)'. La
# validation l'accepte (is_valid_langcode → parse_locale().language non vide).
# → le clavier du GUI ET du système installé suivent enfin la locale choisie.
sed -i \
's/^\(\s*\)locale = get_language_id(self\.language)/\1locale = self.language # FWS: garder le territoire (fr_CH -> ch(fr))/' \
pyanaconda/modules/localization/localization.py
# Garde-fou : casse le build si le motif amont a changé (le patch silencieux).
grep -q 'locale = self.language # FWS' \
pyanaconda/modules/localization/localization.py
# ── FWS : champ « Nom de machine » dans le spoke Utilisateur ───────────────
# Anaconda ne propage PAS le hostname (le champ du spoke Réseau est perdu chez
# nous → /etc/hostname vide). On ajoute donc un champ Hostname à l'onglet de
# création de compte (ligne 2 de la grille, libre) ; user.py écrit la valeur
# dans /tmp/fws-hostname, que le %post du kickstart applique à /etc/hostname.
python3 - <<'PYEOF'
import glob
# 1) user.glade : insérer label + entry "Host name" APRÈS le bloc username_entry.
glades = [p for p in glob.glob("pyanaconda/**/user.glade", recursive=True)
if 'username_entry' in open(p, encoding='utf-8').read()]
assert glades, "FWS: user.glade introuvable"
g = glades[0]
s = open(g, encoding='utf-8').read()
assert 'id="hostname_entry"' not in s, "FWS: glade déjà patché"
i = s.index('id="username_entry"')
k = s.index('</packing>', i) # fin du packing de username_entry
j = s.index('</child>', k) + len('</child>') # fin du <child> EXTERNE (pas l'accessible)
block = '''
<child>
<object class="GtkLabel" id="hostname_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="xpad">10</property>
<property name="label" translatable="yes" context="GUI|User">_Host name</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">hostname_entry</property>
<property name="xalign">1</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="hostname_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="width-chars">50</property>
<child internal-child="accessible">
<object class="AtkObject" id="hostname_entry-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Host Name</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>'''
open(g, 'w', encoding='utf-8').write(s[:j] + block + s[j:])
# 2) user.py (GUI) : récupérer le widget + écrire /tmp/fws-hostname dans apply().
pys = glob.glob("pyanaconda/ui/gui/spokes/user.py")
assert pys, "FWS: user.py introuvable"
p = pys[0]
s = open(p, encoding='utf-8').read()
anchor = 'self._username_entry = self.builder.get_object("username_entry")'
assert anchor in s, "FWS: ancre username_entry absente"
s = s.replace(anchor,
anchor + '\n self._hostname_entry = self.builder.get_object("hostname_entry")',
1)
ap = 'set_user_list(self._users_module, self._user_list, remove_unset=True)'
assert ap in s, "FWS: ancre apply() absente"
s = s.replace(ap, ap + '''
# FWS : mémorise le nom de machine saisi (cible pas encore montée) pour
# le %post du kickstart, qui l'écrira dans /etc/hostname.
try:
_hn = self._hostname_entry.get_text().strip()
except Exception:
_hn = ""
try:
with open("/tmp/fws-hostname", "w") as _f:
_f.write(_hn)
except OSError:
pass''', 1)
open(p, 'w', encoding='utf-8').write(s)
print("FWS: champ Hostname ajouté au spoke Utilisateur (glade + user.py)")
PYEOF
}
build() {
cd "$srcdir/$_srcdir"
# Glade désactivé (catalogue designer, inutile au runtime) → pas de dép glade.
+4 -1
View File
@@ -114,7 +114,10 @@ if [ -z "$FWS_IN_CONTAINER" ] && ! host_is_arch; then
"${SUDO[@]}" podman pull "$IMAGE"
info "Relance dans le conteneur (setup-aur.sh)…"
"${SUDO[@]}" podman run --rm "${TTY[@]}" --privileged \
# --network=host : le bridge podman ne route plus vers l'extérieur sur
# certains réseaux (firewalld/NAT, → « Resolving timed out »). On partage la
# pile réseau de l'hôte (internet + DNS OK) pour les pacman/makepkg/AUR.
"${SUDO[@]}" podman run --rm "${TTY[@]}" --network=host --privileged \
-e FWS_IN_CONTAINER=1 \
-v "$REPO_DIR":"$REPO_DIR" \
-v fws-pacman-cache:/var/cache/pacman/pkg \