Postmortem of the Linux template deploy/prepare 'no IP' investigation: separates the three distinct causes (apt index stale from --skip-update, deploy --force snapshot-chain, wedged host vmnet-dhcpd) and documents the recovery (restart vmware-networks). Changelog entry summarising the toolchain, xvfb, --force cleanup and cloud-init seal changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.0 KiB
Postmortem — Template Linux: deploy/prepare "no IP" (2026-06-06)
Sintesi
Durante l'aggiunta di dipendenze GUI al toolchain del template Linux
(python3-gi gir1.2-gtk-4.0 xvfb), una serie di fallimenti ha aperto una lunga
sessione di debug. Sono emersi due problemi distinti, più una causa
ambientale che ha confuso la diagnosi:
-
Origine reale della sessione —
prepare-linuxfalliva allo Step 4a conUnable to locate package gir1.2-gtk-4.0. Causa:--skip-updatesaltava ancheapt-get update, lasciando l'indice apt vecchio. Non c'entrava la rete. Fix banale, applicato. -
Bug
deploy-linux --force— il resize allo Step 4 falliva con "disk is part of a snapshot chain" perché--forceriusava la directory senza rimuovere la snapshot chain precedente. Bug deterministico, colpito due volte. Fix applicato. -
Saga "no IP" (ambientale) — il rilevamento IP via open-vm-tools andava in timeout in modo intermittente. Causa finale: il servizio DHCP/NAT di vmnet8 sull'host si era inceppato a causa della churn di debug (decine di
vmrun start/stop,tcpdumppromiscuo, DISCOVER ripetuti del guest). Risolto con un restart divmware-networks. Non è un bug del codice né del CI normale.
Stato finale: template BaseClean-Linux ricostruito da powered-off, con gtk/xvfb
e cloud-init sigillato. Tutti i test passano (coverage 94.4%).
Cronologia
| Ora (host) | Evento |
|---|---|
| ~10:50 | prepare-linux --skip-update → fallisce allo Step 4a (gir1.2-gtk-4.0 non trovato) per indice apt stale |
| ~11:00 | Dopo fix apt + revert snapshot: prepare-linux riesce, guest ottiene IP .153, snapshot ripreso |
| ~11:03+ | I boot successivi dello snapshot non ottengono IP utile → inizio debug rete |
| 11:20 | Cattura sul filo: DHCP OFFER/ACK presenti, ma il guest non applica l'IPv4 |
| 12:06 | Deploy fresco: il guest ottiene .143 (cloud-init), ma deploy Step 7 va in timeout sui tools |
| 12:26 | Reboot: stesso guest non ottiene IP (intermittenza) |
| ~12:30 | vmware-networks --stop/--start → l'IP torna stabile. Sblocco confermato |
| dopo | Implementati e testati i fix; template rigenerato |
Analisi cause
2.1 Step 4a apt (origine della sessione)
Install-CIToolchain-Linux2404.sh faceva apt-get update solo se non era
passato --skip-update. Ma --skip-update dovrebbe saltare il solo upgrade
(lento), non il refresh dell'indice. Con indice vecchio, i pacchetti nuovi
(gir1.2-gtk-4.0, xvfb) non venivano trovati.
A riprova che a quel punto la rete funzionava: quel prepare-linux era entrato
in SSH nel guest senza problemi.
2.2 deploy-linux --force e la snapshot chain
deploy-linux --force riusa la directory della VM ma non rimuoveva gli artefatti
di un'eventuale snapshot precedente (-NNNNNN.vmdk, .vmsn, .vmsd). Con la
chain presente, vmware-vdiskmanager rifiuta il resize dello Step 4:
This disk is part of a snapshot chain in '.../LinuxBuild2404.vmx'.
The selected operation can only be executed on a disk with no snapshots.
2.3 La saga "no IP" — vmnet8 DHCP inceppato
Sintomo: vmrun getGuestIPAddress → "VMware Tools are not running" /
"Unable to get the IP address", in modo intermittente. Il guest in realtà:
- bootava correttamente (login prompt),
- aveva open-vm-tools installato e attivo,
- ma
systemd-networkda volte non applicava un lease DHCPv4 (link up, solo IPv6LL,networkd-wait-onlinein timeout).
Sul filo il DHCP a volte completava (.143 applicato e raggiungibile), a volte
no. Il server rispondeva (altre VM ottenevano lease). La causa finale: il demone
vmnet-dhcpd/vmnet-natd di vmnet8 era andato in uno stato degradato dopo la
churn di debug. Il restart vmware-networks --stop/--start lo ha sbloccato
e l'IP è tornato stabile e immediato.
Ipotesi scartate (vicoli ciechi)
- Controller pvscsi vs lsilogic — il boot funzionava con pvscsi; irrilevante.
- Naming NIC
ens192vsens160— cloud-init si adattava; l'IP arrivava lo stesso quando la rete funzionava. - Saturazione del pool DHCP — il pool era di fatto libero (0 lease attivi); i MAC multipli per IP nel lease DB sono storia normale di ISC dhcpd.
- Seal cloud-init / machine-id — difensivi ma non erano la causa del no-IP.
Fix applicati (branch fix/linux-template-toolchain-deploy)
Commit 1 — toolchain
template/Install-CIToolchain-Linux2404.sh
- Step 4a: installa
python3-gi gir1.2-gtk-4.0 xvfbcon assert suimport gieXvfb(richiesta originale). - Step 1:
apt-get updateora gira sempre;--skip-updatesalta solo l'upgrade. Risolve il fallimento Step 4a.
Commit 2 — robustezza deploy/prepare
src/ci_orchestrator/commands/template.py (+ test)
_clean_force_artifacts: con--forcerimuove snapshot delta,.vmsn,.vmsde.lckprima del resize → niente più errore snapshot-chain. Coperto da 3 unit test.- prepare-linux Step 7d (seal cloud-init): rimuove la
50-cloud-init.yamlstale, rigenera netplan (resta solo il99-ci-dhcp-allnicsMAC-agnostic), disabilita cloud-init (/etc/cloud/cloud-init.disabled) così non rigira sui cloni. - deploy user-data:
package_update/upgrade: falseper non tenere il lock dpkg al primo boot e non ritardare open-vm-tools oltre il poll dello Step 7. - Step 7 timeout:
300s → 600scome rete di sicurezza per primi boot lenti.
Verifica: ruff ✅, mypy --strict (23 file) ✅, suite completa ✅,
coverage 94.4% (gate 90%). Prod venv reinstallato (non-editable).
Procedura di recovery: deploy/prepare non ottiene IP
Quando deploy-linux (Step 7) o prepare-linux non riescono a rilevare l'IP
ma il guest sembra sano (booting, tools attivi), prima di sospettare
immagine o codice, riavvia il networking VMware sull'host:
sudo /usr/bin/vmware-networks --stop
sudo /usr/bin/vmware-networks --start
Flush opzionale dei lease (backup prima), solo se nessuna VM è accesa:
sudo cp /etc/vmware/vmnet8/dhcpd/dhcpd.leases /tmp/dhcpd.leases.bak
sudo sh -c ': > /etc/vmware/vmnet8/dhcpd/dhcpd.leases'
Distinto da:
- Tools-not-running sul template → revert a
BaseClean-Linux(veditemplate-live-state-recovery). - vmmon/vmnet non compilati dopo bump kernel → il guard systemd ricostruisce
i moduli al boot (vedi
vmware-modules-kernel-upgrade).
Raccomandazioni (NON applicate di proposito)
Cosa NON fare
- Restart/flush automatico ad ogni clone/deploy/prepare.
vmware-networksè globale (bridge + hostonly + NAT insieme): un restart sotto un job in corso rompe la rete di tutte le VM in esecuzione → job concorrenti falliti. Il flush dei lease con VM attive causa conflitti IP al rinnovo. Sproporzionato rispetto a un problema non dimostrato ricorrente.
Cosa fare
- Monitorare. L'inceppamento è nato dalla churn anomala di debug, non dal CI normale. Tenere la recovery manuale e agire solo se ricapita con dati reali.
Se servisse hardening preventivo (a freddo, con cautela)
- Abbassare
max-lease-time(i cloni vivono minuti → IP liberati in fretta; i job lunghi rinnovano da soli via networkd). - Allargare il range DHCP per più margine.
- Caveat:
/etc/vmware/vmnet8/dhcpd/dhcpd.confè auto-generato da VMware ("DO NOT MODIFY", validato conCFG_HASHin/etc/vmware/networking). Edit a mano fragili: rischio rigenerazione al prossimo--configure/update. Da fare solo se il problema si dimostra ricorrente.
Lezioni
- L'attività di debug intensa sulla rete host (start/stop ripetuti, sniffing
promiscuo) può degradare
vmnet-dhcpd: in futuro, minimizzare la churn e preferire osservazione mirata. - Tre cause distinte si sono sovrapposte; separarle prima ha richiesto tempo. Il guest era fondamentalmente sano per quasi tutta la sessione — l'errore di rilevamento IP non implicava un guest rotto.
- Non sovrastimare: i fix committati coprono i bug veri e provati; il DHCP è stato lasciato invariato per evitare over-engineering.