La colonne ⚠ donne le NOMBRE ; on peut désormais LIRE les lignes associées.
Touche « d » (ou indice dans la barre) : ouvre une petite fenêtre modale
(ErrorLinesScreen) listant, pour la VM sélectionnée, les lignes d'erreurs
puis d'avertissements (numéro de ligne + texte), défilable. Échap/q ferme.
- scan_log_error_lines() : mêmes détection + listes d'ignore que la suite de
tests ERPLibre, mais retient les lignes (bornées à 500) avec leur numéro.
- Scan à la demande à l'ouverture -> toujours à jour (marche même pendant
l'installation).
Validé headless : modale s'ouvre avec les lignes, se ferme à Échap.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sur les images cloud, /var/lib/apt/lists est vide (package_update désactivé)
-> « Unable to locate package qemu-guest-agent » et agent inactif. On
rafraîchit l'index (timeout 120, || true) AVANT l'install dans le runcmd
(après sshd, sans bloquer SSH). Idem pacman -Sy. Sous-shell ( ) et non
accolades { } (indicateur YAML).
Validé sur une VM de test Ubuntu 24.04 (redéployée) :
- cloud-init status: done ; user erplibre créé + mot de passe (login console
erplibre/erplibre OK) ;
- qemu-guest-agent: active ;
- guest-ping OK ; guest-exec autorisé (echo -> code 0, tourne en root).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La ligne runcmd Fedora commençait par « - [ -f … ] » : en YAML, « - [ »
démarre une SÉQUENCE EN FLUX, donc « [ -f … ] && sed … » rendait tout le
user-data invalide. cloud-init rejetait alors la config ENTIÈRE : aucun
utilisateur créé, pas de SSH, login console erplibre/erplibre impossible,
VM « en attente de démarrage ».
- « test -f … && … » au lieu de « [ -f … ] && … » (ne démarre pas de
séquence YAML).
- timeout 300 sur l'installation de qemu-guest-agent : un miroir lent ne
bloque plus cloud-init.
- Validé : le user-data se parse en YAML (tous les runcmd sont des chaînes),
avec et sans mot de passe.
Les VM déjà déployées avec le mauvais seed doivent être redéployées ; les
prochaines repartent correctement.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Suivi d'installation (qemu_install_monitor.py) :
- Table VM/État LISIBLE : largeurs de colonnes fixes (VM 26, ⚠ 4, État 12,
Durée 7, Disque 8) -> l'État n'est plus tronqué à 3-4 caractères
(« ❌ effacée », « ⏸ en pause » lisibles) ; table défilable (overflow-x,
height 1fr) pour les longs noms et les gros parcs.
- « w » web : offre désormais la LISTE des navigateurs CLI installés
(_choose_browser) pour choisir lequel utiliser, + option [i] installer.
Déploiement (deploy_qemu.py) :
- guest-exec AUTORISÉ : on vide la liste de blocage de qemu-ga
(block-rpcs/blacklist vides — pas allow-rpcs qui est une liste BLANCHE et
casserait les autres RPC), + neutralise /etc/sysconfig/qemu-ga (Fedora).
Installation (todo.py) :
- Profils AVEC Odoo (install_odoo*) UNIQUEMENT : Odoo est enregistré comme
service systemd (erplibre.service, inspiré de script/systemd/
install_daemon.sh) puis enable --now. Pas pour ERPLibre seul / mobile /
Déploiement.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Provisioning (deploy_qemu.py) :
- qemu-guest-agent installé + activé dans le runcmd cloud-init (APRÈS
sshd, « || true » : ne bloque pas le boot si le réseau est lent).
- Canal virtio org.qemu.guest_agent.0 ajouté à virt-install : virsh peut
piloter la VM SANS réseau.
- Extension du FS invité (todo.py) : nouveau tier AGENT INVITÉ
(_qemu_guest_exec via qemu-agent-command guest-exec) entre SSH et la
console série -> étend le FS même sans IP.
Suivi d'installation (qemu_install_monitor.py) :
- Détection d'erreurs dans le log à la complétion (succès OU échec) en
réutilisant la logique de script/test/run_parallel_test.py (sous-chaîne
error/warning + listes d'ignore). Nouvelle colonne « ⚠ » À GAUCHE d'État
(⚠N erreurs / ⚡N avert. / ✓ propre).
- Sommaire de stats EN CHIFFRES (📊 total · ✅ · ❌ · ⏳ · ⏸ · 🗑 · ⚠ · ⚡) ;
CLIC pour déplier le détail (VM en erreur + durées).
- Boutons « p » Pause tout (virsh suspend des VM running) et « o »
Reprendre tout (virsh resume) — les logs continuent (offsets conservés).
Validé headless : succès-avec-erreur -> ⚠1, stats/détail, pause du parc.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Trois améliorations QEMU :
- Extension du FS invité robuste : résolution d'IP avec BATTEMENT
(_qemu_resolve_ips, parallèle, boot émulé lent) au lieu d'un timeout
court ; en cas d'absence d'IP ou d'échec SSH, repli sur la CONSOLE
SÉRIE avec la commande growpart/resize prête à coller (login
erplibre/erplibre). Commande factorisée dans _GROW_FS_REMOTE.
- Temps estimés PAR VERSION : nouveau mon.avg_by_version(distro, version)
et _qemu_stat_avg("version", v, distro) -> suffixe « · ~46s moy (1) »
dans les listes de versions (prompt simple + granulaire).
- i18n : « Versions for » n'avait AUCUNE traduction (restait en anglais).
Ajout FR « Versions des » (+ « Version des ») et capitalisation de la
distro -> « Versions des Ubuntu : ».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deux points :
- Fil d'Ariane depuis la télémétrie : une commande lancée DEPUIS le TUI de
télémétrie ne passait par aucun menu, donc son chemin n'était jamais
affiché. On imprime désormais « 📍 TODO › … › <commande> » (dernier
segment traduit + icône) avant l'exécution, et on enregistre le chemin.
- Arrêt de VM (réduction disque) par SIGNAL : virsh shutdown --mode
acpi,agent (bouton ACPI puis agent invité) au lieu d'un arrêt implicite.
Pendant l'attente, on affiche un compte à rebours du timeout
(« ⏳ arrêt en cours… NNN s restantes ») et le délai max au départ.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- F3 fait maintenant défiler Arbre -> Kanban -> Liste -> Arbre. Le résumé
et le footer annoncent la PROCHAINE vue (« F3 → Liste »).
- Nouvelle vue Liste : tous les menus empilés verticalement, chacun avec
ses sections et ses commandes exécutables.
- Les colonnes Kanban et la vue Liste affichent les SECTIONS (── … ──)
pour guider le choix, et chaque commande porte son ICÔNE.
L'icône vient de t() : l'AST extrait la clé i18n (prompt_description /
prompt_description_key), et _disp() la résout en libellé traduit + icône.
Les sections sont capturées via _choice_entries (marqueurs {"section": …}).
Validé headless : cycle F3, 11 en-têtes de menu, sections en Liste/Kanban.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Après « virsh list --all », le menu propose désormais :
[1] Infos avancées (vCPU, RAM, disque)
[2] Changer l'état d'une ou plusieurs VM
[Entrée] Rien
Changement d'état (_qemu_change_state) :
- Saisie d'une liste de VM séparée par des virgules (noms ou ID, résolus
via _qemu_domname et validés contre les VM existantes).
- Choix de l'état cible : Ouvrir (start) ou Fermer (shutdown).
- DOUBLE validation (« Appliquer : … ? » puis « Confirmer pour de vrai ? »)
avant d'exécuter virsh start/shutdown sur chaque VM.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Si la VM a dû être éteinte pour la réduction, on le NOTE (« La VM a été
éteinte pour le redimensionnement. ») puis on demande (o/N) si on veut la
redémarrer (virsh start sur le nom canonique). Si la VM était déjà éteinte
ou n'a pas eu besoin de l'être (agrandissement à chaud), on ne demande
rien : drapeau was_shut_down positionné uniquement après un arrêt effectif.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Avant, réduire le disque d'une VM allumée affichait seulement « Éteignez
la VM » puis abandonnait. Désormais on DEMANDE (o/N) si on veut l'éteindre
et réessayer :
- _qemu_shutdown_wait : arrêt ACPI gracieux (virsh shutdown), attente
jusqu'à « shut off » (timeout 120s), puis propose un arrêt forcé
(virsh destroy) si l'arrêt traîne.
- _qemu_domname : résout un ID numérique en nom canonique — l'ID
disparaît une fois la VM éteinte, le polling doit utiliser le nom.
Validé : domname(14) -> erplibre-ubuntu-2004.
- Tous les nouveaux prompts affichent la valeur par défaut (o/N).
Une fois éteinte, la réduction (qemu-img resize --shrink) se poursuit
automatiquement après confirmation du risque.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Après « sudo virsh list --all », le menu propose désormais (o/N) un
tableau détaillé par VM : état, vCPU, RAM allouée (Max memory), taille
disque virtuelle et réelle (qemu-img info -U, lit même VM allumée), plus
l'espace total/libre/utilisé du stockage des images (shutil.disk_usage).
- _qemu_list_vms(ask_advanced=False) : seul le menu [4] prompte ;
les appels internes (IP, console, resize, delete) restent inchangés.
- Helpers _qemu_dominfo (vcpu + Max memory) et _qemu_disk_sizes
(virtuel + réel, -U). Validé en réel : 8 vCPU / 8.0G / 30.0G / 2.5G.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Icônes devant chaque entrée du menu Execute (Code 💻, Config 🔧, Run 🏃,
Test 🧪, Process 📟, Database 💾, Git 🌿, Mise à jour 🔃, Doc 📖, GPT code
🤖, Automatisation 🦾, Déploiement 🚀, Réseau 📡, Sécurité 🔒, Langue 🌍).
- Icônes sur les titres de section (Développement 🧰, Données 📊, Sources &
documentation 📚, IA & automatisation 🧠, Déploiement/réseau/sécurité 🌐,
Préférences 🎨).
- « Back » (Retour) reçoit 🔙 — icône « Précédent » partagée par tous les
sous-menus via fill_help_info.
Emojis larges (2 cellules) -> 1 espace, alignement de la colonne label
préservé. Modifs uniquement dans les VALEURS de todo_i18n.py.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
qemu-img info échouait (« Failed to get shared write lock ») sur une VM
running car libvirt tient le lock d'écriture : la taille virtuelle lue
tombait à 0.0 G, et « -10G » donnait alors 0-10 = -10 → « Taille invalide ».
- Ajout de -U (--force-share) aux deux appels qemu-img info (affichage +
_qemu_disk_virtual_bytes) : lecture seule sûre même VM allumée.
- Garde-fou : si la taille reste illisible (0), on abandonne avec un
message clair au lieu de calculer une cible négative.
Le redimensionnement lui-même était déjà correct (virsh blockresize à
chaud si running, qemu-img resize si éteinte) — pas besoin d'éteindre la
VM pour AGRANDIR. Validé : lecture -U renvoie 30.0 G sur une VM running.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deux problèmes du bouton « w » (ouvrir l'UI web de la VM) :
- L'installation prenait w3m sans demander. Désormais on CHOISIT le
navigateur CLI à installer (w3m / lynx / links / elinks) via _install_cli_
browser ; la commande (adaptée à l'OS) est affichée puis validée.
browser_install_command prend un paramètre `browser`.
- Au lancement, le navigateur « clignotait » et revenait au TUI sans qu'on
voie l'erreur (souvent Odoo pas démarré sur :8069). On affiche maintenant
la commande, le CODE DE SORTIE, un indice (Odoo/réseau) et une PAUSE
« Entrée pour revenir » pour diagnostiquer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
L'historique d'installation est désormais enregistré dans un fichier DÉDIÉ
.venv.erplibre/qemu_install_stats.json (repli ~/.erplibre) : chaque run garde
distro + version + architecture + durée + horodatage (500 derniers).
- record_duration(distro, version, arch, secs) enregistre le run (appelé par
le dashboard à la complétion d'une VM).
- Menus de sélection enrichis : chaque architecture et chaque distribution
affiche la DURÉE MOYENNE d'install historique « · ~5m moy (3) » quand la
donnée existe. La DERNIÈRE install (distro version [arch] — durée) est
rappelée en tête du déploiement.
- eta_reference lit désormais les runs (médiane par arch, repli global).
Nouveaux helpers : avg_by_arch, avg_by_distro, last_run.
Validé : enregistrement + moyennes (amd64 ~5m (2), ubuntu ~13m (3)),
dernière install affichée, distros sans données masquées.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Quand on installe ERPLibre sur une/des VM, on choisit désormais CE qu'on
installe (au lieu de forcer install_odoo_18) :
ERPLibre + Odoo 18/17/16/15/14/13/12 (make install_os && make install_odoo_X)
ERPLibre + toutes les versions Odoo (make install_odoo_all_version)
ERPLibre seulement (sans Odoo) (./script/install/install_erplibre.sh)
ERPLibre mobile (home) (./mobile/install_and_run.sh)
ERPLibre Déploiement (+ QEMU + dev) (install_dev + qemu/libvirt/virtinst)
_qemu_pick_install_profile renvoie la commande finale ; _qemu_erplibre_remote_cmd
l'exécute dans ~/git/erplibre ; le profil est threadé aux installeurs
(monitoré + streamé). Cibles make vérifiées dans les Makefiles.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Après « i » (installer lm-sensors) dans la vue système F2, l'affichage
n'était pas garanti d'être remis à jour : le message « lm-sensors absent »
pouvait rester même si les capteurs devenaient lisibles.
Fix : à la fin de action_install_sensors, on ré-échantillonne le système
(température incluse, _sys_prev remis à zéro) et on réécrit la case
SYNCHRONEMENT + self.refresh(), puis on notifie le résultat (« capteurs
désormais disponibles » ou « toujours pas de température — reboot/modprobe
requis ? »).
Validé headless : la ligne Température passe de « lm-sensors absent… » à
« 48°C (max) » une fois la température lisible.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ajoute une icône descriptive devant chaque section et entrée du menu QEMU :
🚀 Déploiement / Déployer, 🔍 Prévisualiser, ⬇ Télécharger, 🛠 Gérer,
📋 Lister, 🌐 IP, 🖥 Console, 📐 Redimensionner, 🗑 Effacer, 🧹 Nettoyer,
📚 Catalogue, 🗂 Lister images.
Uniquement les VALEURS i18n (fr+en) changent -> aucune modif de todo.py, les
clés (et donc les appels t(...) + la télémétrie) restent inchangés.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- F2 : nouvelle vue SYSTÈME (état/uptime + charge, CPU %, mémoire, disque,
réseau ↓/↑, batterie, température). Les I/O sont déportées en thread
(asyncio.to_thread) ; rafraîchissement 2 s (deltas CPU/réseau). Si la
température n'est pas lisible (ni /sys/class/thermal ni lm-sensors), on
propose d'installer lm-sensors avec la touche « i » (commande selon l'OS —
apt/dnf/pacman — affichée puis validée). read_temperature essaie
/sys/class/thermal d'abord (sans dépendance).
- Vue Kanban GRILLE : clic sur le TITRE d'une case -> elle s'AGRANDIT
(row-span, prend toute la hauteur d'une colonne) ; re-clic -> taille
normale (classe kbig).
Validé headless : vue système peuplée (mém/disque/temp), F2/F3 basculent,
clic titre en grille -> kbig on/off.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Après exécution d'une commande choisie dans la télémétrie, on propose de
REVENIR (r) ou de quitter. En revenant, la vue ET la position du curseur
sont RESTAURÉES (chemin porté par chaque nœud/carte ; run_tui prend/rend un
`state`).
- Vue Kanban : F4 fait défiler la DISPOSITION —
columns (une rangée de colonnes) / swimlanes (une rangée par menu de
niveau 1) / grid (grille 3 colonnes). F3 bascule Arbre/Kanban.
Validé headless : F3/F4 cyclent les dispositions, sélection -> action+état,
relance avec `state` -> curseur restauré sur le bon nœud.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Ticks ASYNCHRONES : les I/O bloquantes (lecture des logs, stat disque,
subprocess « virsh list », /proc) sont déportées en THREAD via
asyncio.to_thread ; seules les mises à jour d'UI restent sur la boucle
d'événements Textual -> plus de gel, même sous forte charge ou disque lent.
_collect_table (thread) rassemble statut+disque+télémétrie, l'application
au tableau se fait ensuite sur la boucle. _tick_log/_tick_domstate idem.
Helper _read_new (lecture incrémentale) réutilisé.
- Touche « w » : si aucun navigateur CLI n'est présent, on PROPOSE de
l'installer selon l'OS (apt Ubuntu/Debian, dnf Fedora, pacman Arch — nos 4
systèmes) : la commande est AFFICHÉE puis exécutée après validation (o/N).
Validé headless : ticks async mettent l'UI à jour ; browser_install_command
renvoie la bonne commande selon l'OS.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le TUI de télémétrie devient aussi un LANCEUR, avec deux vues :
- Sélectionner une COMMANDE (feuille de l'arbre, ou carte du Kanban) +
Entrée -> le TUI se ferme et la commande est EXÉCUTÉE (getattr(self, méthode)
(**kwargs)). Les kwargs littéraux sont extraits du code (ex. Aperçu ->
_qemu_deploy(dry_run=True)), donc la commande est rejouée à l'identique.
- Vue KANBAN : une colonne par menu contenant des commandes (issu du code),
cartes = commandes exécutables + compteur de visites du menu.
- F3 bascule entre vue Arbre et vue Kanban. Résumé mis à jour (Entrée =
exécuter, F3 = vue).
_dispatch capture désormais (méthode, kwargs) ; les feuilles de l'arbre
portent la méthode en data ; run_tui renvoie (méthode, kwargs) à exécuter.
Validé headless : 11 colonnes Kanban, kwargs (dry_run/production_ready)
capturés, bascule F3, capture de l'action à exécuter.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
La télémétrie n'affichait que les chemins effectivement visités. Elle
observe désormais les MÉTADONNÉES DE NAVIGATION issues du CODE : todo.py est
analysé (AST) pour reconstruire l'arbre RÉEL des menus et commandes.
- build_code_tree() lit _MENU_LABELS + les listes « choices » + le dispatch
« status == N: self.X() » de chaque menu pour bâtir l'arborescence complète
(sous-menus = cibles présentes dans _MENU_LABELS ; sinon commandes-feuilles,
libellées par leur prompt_description).
- Le TUI affiche cet arbre COMPLET (tous les menus, même jamais visités) avec
le compteur de visites en surimpression sur chaque menu (via la télémétrie
persistée). Repli sur l'arbre des seuls chemins visités si l'analyse échoue.
Validé : l'arbre reconstruit couvre Execute -> Deploy -> SSH/QEMU (+ toutes
leurs commandes : Resize, Delete, …), Git -> Git local server, GPT code ->
RTK, etc. ; compteurs corrects (menus visités > 0, autres 0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nouvelle entrée « [5] Télémétrie de navigation (TUI) » dans le menu principal.
- Enregistrement : Todo._menu_header (seul constructeur du fil d'Ariane)
appelle todo_telemetry.record(fil) à chaque affichage de menu. Dédup des
ré-affichages consécutifs -> on ne compte que les TRANSITIONS de
navigation. Persistant dans ~/.erplibre/todo_telemetry.json. Best-effort :
ne casse jamais la navigation.
- Visualisation : todo_telemetry.run_tui() ouvre un TUI Textual affichant
l'ARBRE des fonctionnalités visitées (chaque nœud = un menu, avec son
nombre de visites), trié par usage décroissant. Touches : q (quitter),
r (réinitialiser), e (tout déplier). Sommaire : total navigations + menus.
Validé headless : enregistrement + dédup, arbre imbriqué à compteurs,
montage du TUI, peuplement, touches.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pendant le suivi, une VM pouvait « stagner » sans qu'on sache pourquoi
(mise en pause, ou effacée à côté). Le dashboard interroge désormais l'état
libvirt (« virsh list --all ») à INTERVALLE LENT (toutes les 10 s, un seul
appel pour tout le parc ; le tableau applique le cache à chaque tick de 2 s) :
- VM en pause (virsh suspend) -> État « ⏸ pause » (non terminal, peut
reprendre).
- VM absente de virsh (effacée pendant l'attente) -> État « ❌ effacée »,
terminal (on cesse de lire son log).
Sinon on garde le statut basé sur le log (⏳ / ✅ / ❌).
Validé headless : running -> ⏳, paused -> ⏸ pause, absente -> ❌ effacée.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nouvelle entrée dans le menu QEMU/KVM (section Gérer). Elle :
- affiche le disque principal (qcow2 via domblklist) + « qemu-img info »
(taille virtuelle + réelle) et l'état de la VM ;
- demande +NG (agrandir), -NG (réduire) ou NG (taille cible) ;
- applique : agrandissement À CHAUD si la VM tourne (virsh blockresize),
sinon qemu-img resize ; réduction via qemu-img resize --shrink (VM éteinte
obligatoire + avertissement fort : le FS invité n'est PAS réduit, risque
de perte de données) ;
- propose ensuite d'étendre le FS invité via SSH (growpart + resize2fs /
xfs_growfs / btrfs, device et type de FS détectés).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ajouts au suivi d'installation (dashboard Textual) :
- Télémétrie hôte (barre dédiée, MAJ 2 s) : CPU % = charge / nb CPU, et
disque du dossier des images (utilisé/total/libre) — utile pour anticiper
le remplissage du disque (cas vécu).
- Colonne « Disque » par VM : taille RÉELLE du qcow2 (st_blocks) -> on voit
quelle VM grossit.
- ETA « hypothèse » : les durées d'install sont MÉMORISÉES par architecture
dans ~/.erplibre/qemu-install/stats.json ; l'ETA du parc = médiane
historique (par arch, repli global) - temps écoulé, affichée au sous-titre.
- Touche « w » : ouvre l'UI web de la VM (Odoo :8069) dans un navigateur CLI
(browsh/carbonyl/w3m/links/elinks/lynx, le 1er trouvé ; sinon notifie quoi
installer). Surtout utile quand l'install est terminée.
Helpers module : load_stats/record_duration/eta_reference, _fmt_size/_fmt_secs,
vm_disk_path/disk_actual_size, cli_browser. run_monitor(run_app=False) expose
l'app pour test headless.
Validé headless (run_test) : montage, ticks, enregistrement des durées, ETA,
télémétrie, touches f/w — sans crash.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Encore du lag à 16 VM : update_cell était appelé pour CHAQUE ligne à chaque
tick (état + « Durée »), or la Durée — dérivée d'un `started` global — est
identique sur toutes les lignes et se réécrivait sans cesse -> re-render
permanent de la DataTable.
- _set_cell : n'appelle update_cell (donc ne re-render) que si la valeur
CHANGE. Mesuré : 312 -> 18 update_cell sur 10 ticks × 16 VM.
- La durée « live » passe dans le SOUS-TITRE (une seule mise à jour) ; la
colonne Durée n'est écrite qu'à la complétion (durée finale figée).
- Le NOMBRE de VM est affiché : titre « … (N VM) », sous-titre
« k/N terminées · mm:ss ».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le TUI de suivi laggait à 30 VM et se figeait quand l'I/O ralentissait
(disque plein / logs effacés). Cause : à chaque tick (1 s) on lisait le
fichier log ENTIER de CHAQUE VM pour le statut + on relisait tout le log
sélectionné, en synchrone sur la boucle d'événements Textual.
Corrections :
- read_status ne lit que les 4 derniers Ko (le marqueur de sortie est sur
la dernière ligne) : un log de 2 Mo passe de « tout lire » à 0,1 ms.
- _load_selected_log lit de façon INCRÉMENTALE (seek à l'offset) au lieu de
relire tout le fichier.
- Les VM TERMINÉES ne sont plus relues (cache _final).
- _tick_table (2 s) et _tick_log (1 s) séparés et PROTÉGÉS par try/except :
une erreur I/O transitoire (disque plein, log supprimé) ne tue plus la
boucle -> l'interface reste réactive aux touches.
- RichLog borné (max_lines=5000).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sur un gros parc (30 VM, ~18 émulées), la résolution d'IP « bloquait » 10 min
en silence sur les VM lentes. Trois causes traitées :
- Joignabilité par PING (ICMP) d'abord, TCP:22 en repli. Le ping répond dès
que le réseau de la VM est up, BIEN AVANT sshd : on ne retenait pas une VM
qui a déjà son IP juste parce que sshd (lent en émulation) n'était pas prêt.
Le ping distingue toujours le bail actif (répond) du bail périmé (non).
- IP cherchée sur PLUSIEURS sources : lease (dnsmasq), agent (qemu-guest-
agent DANS la VM) et arp (table ARP hôte). Le bail dnsmasq peut être vide
sous forte charge alors que la VM a une IP (constaté sur ce parc).
- BATTEMENT toutes les 30 s listant les VM encore en attente + timeout PAR VM
ramené à 5 min (au lieu de 10) dans la phase de résolution -> plus de
silence prolongé, et on n'attend pas indéfiniment une VM sans IP.
NB : déployer la matrice complète (30 VM dont ~18 émulées TCG) sature un seul
hôte ; certaines VM émulées n'obtiennent pas de bail DHCP à temps (limite de
capacité, pas un bug). La résolution dégrade désormais proprement.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Améliore le suivi du déploiement multi-VM :
- Compteur de COMPLÉTION devant chaque résultat (« [1/26] », « [2/26] »… =
ordre où les tâches TERMINENT), en plus de l'ID de préparation stable
(« [7/26] ») — utile car l'exécution parallèle rend les résultats
désordonnés.
- Temps d'exécution PAR ÉTAPE : durée de chaque VM (déploiement, résolution
d'IP) + bilan de phase (« Bilan déploiement : 24 OK, 2 en échec, 26 VM,
3m10s » ; « IP résolues : 25/26 (2m). »).
- SOMMAIRE TOTAL encadré en fin de flux (VM déployées, total avec
existantes, temps total).
Helper _fmt_dur (« 45s » / « 2m05s »).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chaque question oui/non affiche désormais explicitement la valeur par défaut
appliquée si on laisse vide, ex. :
« Suivi interactif (dashboard) ? (o/N, défaut : non) : »
Les 18 prompts passent par _is_yes(input(...)) : une réponse vide vaut NON.
On l'indique donc dans les traductions (fr « (o/N, défaut : non) », en
« (y/N, default: no) »). Seules les VALEURS i18n changent ; les clés (donc
les appels t(...) dans todo.py) sont inchangées.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sur un gros parc (ex. 26 VM), on ne voyait ni combien de VM allaient être
déployées ni lesquelles étaient en cours (résultats parallèles dans le
désordre). Deux améliorations :
- Le prompt de parallélisme affiche le NOMBRE de VM à déployer :
« Déploiements en parallèle (défaut : 24, 26 VM) : ». Pour cela, la
séparation à-créer / déjà-existantes est faite AVANT le prompt (on connaît
le vrai compte).
- Chaque VM reçoit un ID « k/N » suivant l'ordre de préparation, affiché
dans les résultats de déploiement (« ✅ [3/26] nom ») et dans la résolution
d'IP (« [5/30] nom : ip »). L'ID reste stable même si les résultats
reviennent dans le désordre -> on suit lesquelles sont traitées.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le menu QEMU avait deux commandes de déploiement redondantes : [1] « Déployer
une VM » (mono, noms/ressources personnalisés) et [4] « Déployer l'infra »
(multi, matrice distro×version×archi). Elles sont FUSIONNÉES en une seule,
[1] « Déployer une ou plusieurs VM » (_qemu_deploy), qui gère aussi bien 1 VM
que N, avec :
- renommage GRANULAIRE des VM à la demande (_qemu_customize_names) : noms
auto par défaut, on en renomme certains par numéros séparés de virgules ;
- multiplicateur de ressources (x1..x4) déjà présent ;
- aperçu dry-run ([2]) qui passe par le même flux et imprime les commandes
deploy_qemu (--dry-run) via le helper partagé _qemu_build_deploy_parts.
Menu simplifié : [1] Déployer une/plusieurs VM, [2] Aperçu (dry-run),
[3] Télécharger une image, puis Gérer/Catalogue renumérotés. Code mort retiré
(_qemu_deploy_vm, _qemu_prompt_arch, _normalize_disk_size,
_qemu_offer_ssh_config).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Quand le téléchargement échoue sur tous les miroirs, le message indique
désormais le CHEMIN de destination visé et une commande prête à copier pour
reprendre manuellement :
Destination : /var/lib/.../fedora-cloud-41-aarch64.qcow2
Reprendre le téléchargement manuellement :
sudo curl -fL -C - -o <dest> \
<url>
puis relancez le déploiement (l'image en cache sera réutilisée).
curl -C - reprend un .part partiel (ou repart de zéro), -f échoue proprement
sur une erreur HTTP. Complète la détection de téléchargement incomplet.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le menu Deploy listait 11 entrées « SSH - … » à plat, ce qui le surchargeait.
Elles sont déplacées dans un sous-menu « SSH (hôte distant)… »
(prompt_execute_deploy_ssh), comme le sous-menu QEMU. Le menu Deploy tient
désormais en 5 entrées :
── Local ──
[1] Cloner ERPLibre localement
[2] Configurer sshfs
── Distant & services ──
[3] SSH (hôte distant)… -> sous-menu (11 opérations SSH)
[4] NTFY
[5] QEMU/KVM…
Le fil d'Ariane affiche « TODO › Execute › Deploy › SSH » dans le sous-menu.
Les libellés et actions SSH sont inchangés (traductions réutilisées).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Avant le déploiement infra, on demande un multiplicateur de ressources :
x1 (minimum catalogue) .. x4. Il multiplie la RAM (base = minimum de la
version) et les vCPU (base 2), en bornant les vCPU au nombre de cœurs de
l'hôte et en signalant si la RAM totale dépasse la RAM libre.
- Le prompt affiche les ressources de l'hôte (vCPU, RAM libre) et, pour
chaque multiplicateur, le total RAM + vCPU/VM avec un ⚠ si ça dépasse.
- Le plan reflète les ressources effectives (vCPU + RAM×mult par VM).
- Les jobs passent --memory et --vcpus effectifs à deploy_qemu (avant,
l'infra laissait le minimum catalogue + 2 vCPU par défaut).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Après un déploiement infra, la résolution d'IP tournait EN SÉRIE (boucle
ssh_config puis install), jusqu'à 10 min par VM émulée, SANS aucune sortie :
le dashboard « n'ouvrait jamais » (impression de blocage), d'autant qu'une
VM qui ne boote pas (IP jamais attribuée) bloquait tout le reste.
Fix : _qemu_resolve_ips résout les IP de toutes les VM EN PARALLÈLE, avec
progression affichée par VM, une seule fois, réutilisée pour ~/.ssh/config
ET l'installation (plus de double résolution). _qemu_install_erplibre_*
acceptent une IP/ip_map déjà résolue.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Une VM arm64 (Fedora aarch64 émulée) restait FIGÉE au firmware (CPU ~2 %,
aucune IP, seed non appliqué). Deux causes :
1) Téléchargement tronqué non détecté. _download_one ne vérifiait pas que le
nombre d'octets reçus == Content-Length. Une connexion coupée en cours
laissait un .part TRONQUÉ, validé comme « complet » (tmp.replace) : un
qcow2 valide mais VIDE (128 Kio, juste l'en-tête, 5 Gio virtuels) ->
disque sans OS -> pas de boot. Pire, ce cache corrompu était réutilisé.
Fix : contrôle de complétude (done < total -> exception -> miroir suivant
ou échec net, jamais de commit d'un fichier tronqué).
2) arm64 : « --boot uefi » simple laissait libvirt choisir l'AAVMF « secure »
(clés Microsoft enrôlées) -> pas de boot. On désactive Secure Boot comme
pour x86 (secure-boot=no -> AAVMF_CODE.no-secboot.fd).
Validé : redéploiement Fedora 42 aarch64 avec image complète + firmware
non-SB -> CPU 111 % (boot actif), IP en ~80 s, SSH OK (erplibre, aarch64,
Fedora 42 Cloud, sudo OK).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Le log d'installation commence désormais par un en-tête identifiant
l'installation : date, VM, distribution + version, architecture, branche, IP.
Écrit dès la création du log (plus jamais vide au démarrage).
_qemu_install_erplibre_monitored déduit distro/version/arch de chaque VM
(nom via _qemu_infra_name + arch via virsh dumpxml) et les passe à
launch_installs, qui écrit l'en-tête et les stocke dans le manifeste.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
L'install ERPLibre échouait sur une VM Ubuntu 26.04 :
« configure: error: no acceptable C compiler found in $PATH » -> pyenv ne
compile pas Python -> pas de venv -> pip/poetry/repo absents.
Cause : install_dev.sh ne listait Ubuntu que jusqu'à 25.10. Sur 26.04 il
tombait dans le « else » (« Your version is not supported… : 26.04 ») et
n'exécutait donc PAS install_debian_dependency.sh -> ni build-essential ni
gcc installés. Le catalogue de déploiement propose pourtant 26.04.
Fix : ajout de 26.04 à la liste des versions Ubuntu supportées.
Note : Ubuntu 26.04 utilise uutils (rust-coreutils), bogué en big-endian ;
sur s390x un « sort » peut paniquer (non bloquant ici) — problème amont.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Symptôme : ~/.ssh/config (et l'install) pointaient sur .31 alors que la VM
était joignable sur .32 -> SSH KO (« No route to host »), console OK.
Cause : au boot, une image cloud demande d'abord une IP DHCP avec son
hostname par défaut (« ubuntu ») -> 1er bail ; puis cloud-init fixe le vrai
hostname et le client redemande -> 2e bail (IP différente). La MÊME MAC a
donc DEUX baux ; le 1er (« ubuntu ») devient périmé. Le code retenait
aveuglément le PREMIER IPv4 de « virsh domifaddr » = le bail périmé. Plus
visible sur s390x/arm64 émulé (boot lent -> les deux baux coexistent).
Fix :
- todo._qemu_vm_ip : renvoie en priorité l'IP dont le bail dnsmasq porte le
hostname == nom de la VM (bail définitif), sinon une IP JOIGNABLE (sshd up,
test TCP:22), sinon le dernier bail — jamais le 1er au hasard. Attente
portée à 10 min (boot émulé lent). Helpers _qemu_lease_candidates /
_qemu_ip_reachable / _qemu_lease_ip_for_host.
- deploy_qemu.wait_for_ip : même logique (IP joignable, sinon la plus
récente) pour l'IP affichée en fin de déploiement standalone.
Validé sur la VM s390x réelle : candidats [.31, .32] -> choisit .32
(hostname-match + seule joignable) ; ssh via alias OK.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1) Nommage : _qemu_infra_name ajoute un suffixe d'architecture quand elle
diffère de la native de l'hôte -> déployer un s390x sur un hôte amd64
donne « erplibre-ubuntu-2604-s390x » (au lieu de « erplibre-ubuntu-2604 »).
Évite les collisions de noms entre archis et rend l'archi visible. Passé
dans les 3 appelants (VM unique + plan + jobs de l'infra).
2) Log d'installation vide : sur une archi ÉMULÉE (s390x/arm64 sur x86) le
boot prend plusieurs minutes ; pendant ce temps l'attente n'écrivait rien
-> le log restait VIDE et paraissait « bloqué ». _launch_one écrit
désormais un en-tête d'attente immédiat + un battement toutes les ~30 s,
et l'attente sshd/cloud-init passe de ~12 à ~20 min (boot émulé lent).
_qemu_wait_ssh (chemin streamé) : timeout porté à 20 min également.
Validé : nommage (amd64/natif sans suffixe, s390x/arm64 suffixés) ; le log
se remplit dès le départ (en-tête + « ... 30s »).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ajoute l'architecture arm64 (aarch64) au déploiement, en plus d'amd64
(x86_64) et s390x. Disponibilité réelle vérifiée (juillet 2026) :
- arm64 : Ubuntu, Debian, Fedora (Arch : pas d'image cloud aarch64 -> rejet).
- s390x : Ubuntu seulement (inchangé).
deploy_qemu.py :
- host_arch() : arch native de l'hôte ; toute arch différente est ÉMULÉE
(TCG, --virt-type qemu) — plus de liste FOREIGN_ARCHES figée.
- virt_install : arm64 -> --arch aarch64 --machine virt --boot uefi (firmware
AAVMF résolu par libvirt) ; s390x inchangé ; x86 UEFI/OVMF inchangé.
- ensure_emulator(arch) généralisé : installe qemu-system-aarch64 + firmware
UEFI AAVMF (arm64) ou qemu-system-s390x (s390x), selon le gestionnaire de
paquets, avec vérif de présence (binaire + firmware pour arm64).
- Validation --arch tôt via ARCH_DISTRO_SUPPORT (message clair si la distro
ne publie pas l'arch). Les URLs d'images arm64 marchent déjà via les alias
(fedora/arch aarch64 ; ubuntu/debian arm64).
todo.py : menus d'architecture (VM unique + infra) proposent amd64/arm64/
s390x selon la distro ; l'architecture NATIVE de l'hôte est marquée d'un *
(défaut) ; les autres sont signalées « émulé, lent ». Le catalogue infra est
restreint aux distros publiant l'arch choisie (arm64 -> ubuntu/debian/fedora,
s390x -> ubuntu).
install_debian_dependency.sh : wkhtmltopdf (deb amd64 en dur) ignoré
best-effort sur toute arch non-x86_64 (au lieu d'avorter l'install).
Validé : dry-runs Ubuntu/Debian/Fedora arm64 (bonnes URLs + virt-install
aarch64/virt/uefi/qemu), rejet Arch arm64, non-régression s390x, menus et
filtrage simulés (natif *, arm64 par distro).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
repo sync échouait sur Fedora :
git: 'daemon' is not a git command.
fatal: cannot obtain manifest git://127.0.0.1:9418/ -> Connection refused
Unable to sync manifest ./manifest/git_manifest_erplibre.xml
Cause : sur Fedora la sous-commande « git daemon » N'EST PAS fournie par le
paquet « git » de base (contrairement à Debian/Ubuntu/Arch) mais par le
paquet séparé « git-daemon ». ERPLibre sert son manifeste via un « git
daemon » local (git://127.0.0.1:9418/) pendant repo sync ; sans le binaire,
le daemon ne démarre pas -> connexion refusée -> synchro du manifeste KO.
Fix : ajout de git-daemon aux dépendances Fedora.
Validé sur VM Fedora 42 réelle : avant, « git daemon » rc=1 ; après
« dnf install git-daemon », rc=0, et un git daemon local sert bien
git://127.0.0.1:9418/ (git ls-remote renvoie les refs).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Menu « Déployer l'infra ERPLibre » :
- Nouveau choix [granulaire] dans la sélection des distributions : affiche
la liste À PLAT de TOUTES les versions du catalogue (distro + version,
défauts marqués d'un *) et permet d'en choisir plusieurs par leurs numéros
séparés par des virgules (ex. « 1,3,12 »). Complète [all] et [principal].
- Demande l'ARCHITECTURE du parc en début de flux, par défaut l'architecture
NATIVE de l'hôte (amd64/arm64/s390x via uname -m). s390x est proposé mais
émulé (lent) et n'a d'images cloud que pour Ubuntu -> le catalogue est
alors restreint à Ubuntu (les autres distros sont ignorées avec un
avertissement). --arch est transmis à deploy_qemu.py quand ≠ amd64.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Après le passage à pacman, l'init PostgreSQL échouait :
« /usr/bin/postgres: /usr/lib/libm.so.6: version GLIBC_2.44 not found ».
Cause : Arch est en rolling release et NE SUPPORTE PAS les mises à jour
partielles. Sur une image cloud dont la glibc date du build de l'image, un
« pacman -S <paquet récent> » (postgresql 18.4) installe un binaire lié à
une glibc plus récente que celle du système -> symbole introuvable.
Fix : mise à jour COMPLÈTE (pacman -Syu) avant d'installer, dans les deux
endroits : install_arch_linux.sh (deps OS) et le bootstrap Arch de
_qemu_erplibre_remote_cmd (todo.py, remplace -Syy par -Syu).
Validé sur VM Arch réelle : après -Syu, « postgres (PostgreSQL) 18.4 » OK,
initdb OK, service postgresql actif, superuser erplibre créé, psql connecte.
Chaîne complète confirmée : gcc 16.1.1, make, node, psql tous présents.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>