Le conseil « rejouer install_proxmox.sh sur l'hôte » ne pouvait PAS marcher : la VM clone le dépôt distant, donc sa copie du script est celle du distant — tant que le correctif n'y est pas, celle qui ne corrige rien. Trois hôtes de suite sont tombés dessus, avec le même message inutile. L'écran répare donc : gel de cloud-init, réécriture de /etc/hosts, relance des unités, constat du montage — le pendant exact de l'offre de créer un pont. Écrit, puis ATTAQUÉ par trois lentilles sur le code réel. Ce qu'elles ont mesuré valait la peine. /etc/hosts se réécrivait en DEUX écritures — « sed -i » puis « printf >> » — alors que la docstring promettait l'inverse. Sed refusé et ajout réussi, la ligne 127.0.1.1 survivait EN PREMIER et la nôtre s'ajoutait une fois par tentative ; sed réussi et ajout refusé, l'hôte perdait l'entrée de son nom, et chaque sudo y attendait ensuite le résolveur. C'est maintenant un fichier complet bâti dans un temporaire, VÉRIFIÉ, puis recopié — « cat > » et non « mv », qui remplacerait l'inode et perdrait mode et propriétaire. Le contrôle final s'en remettait à « getent hosts », qui réussit via mDNS même quand rien n'a été écrit — et acceptait les fe80:: que notre propre code rejette. Il relit désormais ce qui a été écrit. awk remplace sed pour filtrer : « print » émet un saut de ligne, donc un /etc/hosts non terminé par un — cloud-init n'en met pas — est normalisé. Sans ça notre ligne se collait à la précédente et le nom du nœud partait sur l'adresse d'une autre machine. Trois autres, du même acabit. Les dépendants de pmxcfs sont relancés eux aussi : actifs pendant la panne, ils échouaient sur ipcc_send_rec, et les laisser donnait une GUI en « communication failure » juste après notre ✓. Un silence du lien n'est plus lu comme une absence de montage. Et l'adresse n'est mise en cause que si pve-cluster a réellement démarré. Les tests exécutent les commandes au lieu de les relire, bouchons capables d'ÉCHOUER : écriture refusée, fichier sans saut de ligne final, tabulations, start qui rate, montage qui disparaît pendant la reconfirmation. Prouvé par mutation — trois HOSTS-KO changés en HOSTS-OK font rougir le test. --- EN --- The advice "replay install_proxmox.sh on the host" could NOT work: the VM clones the remote, so its copy of the script is the remote's — while the fix is not there, the one that fixes nothing. Three hosts in a row hit it with the same useless message. So the screen repairs: freeze cloud-init, rewrite /etc/hosts, restart the units, verify the mount — the exact counterpart of the offer to create a bridge. Written, then ATTACKED by three lenses on the real code. What they measured was worth it. /etc/hosts was rewritten in TWO writes — "sed -i" then "printf >>" — while the docstring promised the opposite. Sed refused and append succeeded: the 127.0.1.1 line survived FIRST and ours was added once per attempt; sed succeeded and append refused: the host lost its own name entry, and every sudo then waited on the resolver. It is now a complete file built in a temporary, VERIFIED, then copied over — "cat >" not "mv", which would replace the inode and lose mode and owner. The final check relied on "getent hosts", which succeeds via mDNS even when nothing was written — and accepted the fe80:: our own code rejects. It now re-reads what was written. awk replaces sed for filtering: "print" emits a newline, so an /etc/hosts with no final one — cloud-init omits it — gets normalised. Without that our line glued onto the previous one and the node's name pointed at another machine's address. Three more of the same kind. pmxcfs's dependents are restarted too: active throughout the outage, they failed on ipcc_send_rec, and leaving them gave a GUI in "communication failure" right after our ✓. A silent link is no longer read as a missing mount. And the address is only blamed if pve-cluster actually started. The tests execute the commands instead of reading them, with stubs able to FAIL: refused write, file with no final newline, tabs, a start that fails, a mount that vanishes during reconfirmation. Proven by mutation — three HOSTS-KO turned into HOSTS-OK make the test go red. Assisted-by: Claude Opus 5 (cherry picked from commit d4f9358c6cb562029cc2ca9eb478d80c6a0a19a4) |
||
|---|---|---|
| .. | ||
| auto_ask.py | ||
| database_manager.py | ||
| deploy_form_extras.py | ||
| deploy_form_lib.py | ||
| deploy_form_plan.py | ||
| kdbx_manager.py | ||
| logo_ascii.txt | ||
| migration_form.py | ||
| migration_stats.py | ||
| migration_status.py | ||
| migration_status_tui.py | ||
| proxmox_deploy_form.py | ||
| proxmox_menu.py | ||
| qemu_access.py | ||
| qemu_deploy.py | ||
| qemu_deploy_form.py | ||
| qemu_hardware.py | ||
| qemu_install.py | ||
| qemu_install_monitor.py | ||
| qemu_manage.py | ||
| qemu_menu.py | ||
| README.base.md | ||
| README.fr.md | ||
| README.md | ||
| source_todo.sh | ||
| textual_setup.py | ||
| todo.json | ||
| todo.py | ||
| todo_example.json | ||
| todo_file_browser.py | ||
| todo_i18n.py | ||
| todo_prefs.py | ||
| todo_telemetry.py | ||
| todo_upgrade.py | ||
| version_manager.py | ||
TODO is an assistant robot to use ERPLibre
Execute it with ./script/todo/todo.py or make todo.
For a new project, copy todo_example.json to private/todo/todo_override.json | private/todo/todo_override_private.json and edit it.
The mail/ package is the mail client reachable from Assistant > Mail:
several IMAP/SMTP accounts, a local cache, and a Textual TUI. See
../../doc/EMAIL.md.
Where the code lives
todo.py carries the menus and the general helpers. Everything around a
single subject sits in its own file, and the whole thing is assembled by
mixins on the TODO class — one file, one subject, its header states its
boundary.
| File | What it owns |
|---|---|
todo.py |
the menus, the configuration, the general helpers |
qemu_menu.py |
the QEMU/KVM menu, the image catalogue, the statistics |
qemu_deploy.py |
deciding then running a deployment |
qemu_install.py |
the recipes run inside a VM |
qemu_manage.py |
lifecycle, disks, hardware, cleanup, addresses |
qemu_access.py |
SSH, tunnels, consoles, Android emulator |
proxmox_menu.py |
the same, on a REMOTE Proxmox VE host |
The two deployment forms — libvirt here, Proxmox over there — ask the same questions, so they share a foundation rather than each holding a copy:
| File | What it owns |
|---|---|
deploy_form_lib.py |
pure logic (sizes, plan, totals, spec), the shared CSS, the resource-row factory, the progress view |
deploy_form_plan.py |
the plan's gestures: overrides, locks, copies, renaming, free values |
qemu_deploy_form.py |
what QEMU/KVM adds: desktops, tools, branches, install profiles |
proxmox_deploy_form.py |
what Proxmox adds: host, storage, bridge, VMID, address |
A form inherits PlanMixin and provides three hooks: which presets each
resource offers, the name a VM would fall back to, and what a lock freezes.
test_todo_deploy_form_lib.py fails if a form redefines a gesture the
foundation already carries — that is what keeps the architecture from drifting
back into two copies.