Files
local-ci-cd-system/docs/postmortem-2026-06-06-linux-template-no-ip.md
Simone 210b4f5f16
Lint / pssa (push) Successful in 16s
Lint / python (push) Successful in 39s
docs: postmortem + changelog for 2026-06-06 template/DHCP session
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>
2026-06-06 13:38:34 +02:00

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:

  1. Origine reale della sessioneprepare-linux falliva allo Step 4a con Unable to locate package gir1.2-gtk-4.0. Causa: --skip-update saltava anche apt-get update, lasciando l'indice apt vecchio. Non c'entrava la rete. Fix banale, applicato.

  2. Bug deploy-linux --force — il resize allo Step 4 falliva con "disk is part of a snapshot chain" perché --force riusava la directory senza rimuovere la snapshot chain precedente. Bug deterministico, colpito due volte. Fix applicato.

  3. 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, tcpdump promiscuo, DISCOVER ripetuti del guest). Risolto con un restart di vmware-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-networkd a volte non applicava un lease DHCPv4 (link up, solo IPv6LL, networkd-wait-online in 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 ens192 vs ens160 — 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 xvfb con assert su import gi e Xvfb (richiesta originale).
  • Step 1: apt-get update ora gira sempre; --skip-update salta solo l'upgrade. Risolve il fallimento Step 4a.

Commit 2 — robustezza deploy/prepare

src/ci_orchestrator/commands/template.py (+ test)

  • _clean_force_artifacts: con --force rimuove snapshot delta, .vmsn, .vmsd e .lck prima del resize → niente più errore snapshot-chain. Coperto da 3 unit test.
  • prepare-linux Step 7d (seal cloud-init): rimuove la 50-cloud-init.yaml stale, rigenera netplan (resta solo il 99-ci-dhcp-allnics MAC-agnostic), disabilita cloud-init (/etc/cloud/cloud-init.disabled) così non rigira sui cloni.
  • deploy user-data: package_update/upgrade: false per non tenere il lock dpkg al primo boot e non ritardare open-vm-tools oltre il poll dello Step 7.
  • Step 7 timeout: 300s → 600s come 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 (vedi template-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 con CFG_HASH in /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.