docs: introduce Phase C (pwsh removal), rename ESXi to Phase D

- Add plans/idea-3-powershell-removal.md: Phase C goal is to eliminate
  the pwsh dependency from the Linux host by porting the remaining PS
  scripts (bench run, validate host, smoke run) to Python sub-commands.
- Update idea-3-esxi-support.md header: Fase C → Fase D.
- Update ideas-overview.md: new four-phase table (A/B/C/D) with
  prerequisiti and criteri for Phase C.
- Rename all "Hook futuri Fase C" (ESXi) → "Hook futuri Fase D" in
  implementation-plan-A-B.md; add Phase C/D entries to summary and
  references section.
- Update PhaseB-user-checklist.md end note and CLAUDE.md to point
  Phase C → pwsh removal, Phase D → ESXi.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 20:46:01 +02:00
parent 43a69b82db
commit 6db20d66bf
6 changed files with 155 additions and 38 deletions
+1 -1
View File
@@ -91,7 +91,7 @@ The host **never executes build tools directly** — it only orchestrates VM lif
| `commands/monitor.py` | `monitor disk / runner` | | `commands/monitor.py` | `monitor disk / runner` |
| `commands/report.py` | `report job` | | `commands/report.py` | `report job` |
**Key design rule**: Application code (especially `commands/job.py`) must import `backends.load_backend` only — never `WorkstationVmrunBackend` directly. This keeps the Phase C ESXi extension path open. **Key design rule**: Application code (especially `commands/job.py`) must import `backends.load_backend` only — never `WorkstationVmrunBackend` directly. This keeps the Phase D ESXi extension path open.
### Transport selection ### Transport selection
+3 -2
View File
@@ -537,5 +537,6 @@ avviata abitualmente in Linux senza incidenti critici.
> Windows attivo. I due sistemi non girano mai contemporaneamente. > Windows attivo. I due sistemi non girano mai contemporaneamente.
Quando i passi 1-8 sono `[x]`, la **Fase B è chiusa** (B8 annullato per Quando i passi 1-8 sono `[x]`, la **Fase B è chiusa** (B8 annullato per
vincolo) e si può valutare l'apertura della Fase C (backend ESXi, vedi vincolo) e si può valutare l'apertura della Fase C (eliminazione `pwsh`
`plans/idea-3-esxi-support.md`). dall'host Linux, vedi `plans/idea-3-powershell-removal.md`). La Fase D
(backend ESXi, `plans/idea-3-esxi-support.md`) viene dopo.
+5 -4
View File
@@ -1,9 +1,10 @@
# Fase C — Supporto ESXi per le Build VM (futuro) # Fase D — Supporto ESXi per le Build VM (futuro)
> **Stato**: **piano differito**, da rivalutare dopo che Fase A > **Stato**: **piano differito**, da rivalutare dopo che Fase A
> ([rewrite Python](idea-1-python-rewrite.md)) e Fase B > ([rewrite Python](idea-1-python-rewrite.md)), Fase B
> ([host Linux](idea-2-linux-host.md)) sono stabili in produzione. > ([host Linux](idea-2-linux-host.md)) e Fase C
> Vedi [overview](ideas-overview.md). > ([eliminazione PowerShell](idea-3-powershell-removal.md)) sono stabili
> in produzione. Vedi [overview](ideas-overview.md).
> >
> Questo documento esiste per: > Questo documento esiste per:
> 1. Garantire che il design di Fase A abbia gli hook corretti > 1. Garantire che il design di Fase A abbia gli hook corretti
+102
View File
@@ -0,0 +1,102 @@
# Fase C — Eliminazione dipendenza PowerShell dall'host Linux
> **Stato**: **pianificata**, da avviare dopo che Fase B è stabile in
> produzione (≥1 settimana di burn-in, Passo 8 completato).
> Vedi [overview](ideas-overview.md).
---
## 1. Obiettivo
Rendere l'host Linux completamente indipendente da PowerShell Core (`pwsh`).
Dopo la Fase B l'orchestrazione ordinaria (job, timer, monitoring, backup)
è già Python puro. Rimangono script PS usati per test manuali, burn-in e
validazione host che richiedono `pwsh` installato.
**C done**: nessuno script in `scripts/*.ps1` viene più eseguito
direttamente sull'host Linux; `pwsh` può essere disinstallato senza
impatti operativi. I `.ps1` rimangono nel repo come riferimento storico
e per il runner Windows (fallback dual-boot).
---
## 2. Script da portare
| Script PS | Uso attuale (Linux host) | Target Python |
|-----------|--------------------------|---------------|
| `Test-CapacityBurnIn.ps1` | burn-in B7: 4 job × 10 round | `python -m ci_orchestrator bench run` |
| `Start-BurnInTest.ps1` | burn-in Windows single-shot | `python -m ci_orchestrator bench run --guest-os windows` |
| `Start-BurnInTest-Linux.ps1` | burn-in Linux single-shot | `python -m ci_orchestrator bench run --guest-os linux` |
| `Validate-HostState.ps1` | verifica stato host pre-cutover | `python -m ci_orchestrator validate host` |
| `Measure-CIBenchmark.ps1` | raccolta metriche timing | integrato in `bench run --collect-metrics` |
| `Test-Smoke.ps1` | smoke end-to-end manuale | `python -m ci_orchestrator smoke run` |
| `Test-CapacityBurnIn.ps1` | già referenziato in B7 checklist | vedi sopra |
Script **non da portare** (girano solo su Windows o sono già shim):
- `Register-CIScheduledTasks.ps1` — Windows Scheduler, non serve su Linux
- `Invoke-RetentionPolicy.ps1` / `Backup-CITemplate.ps1` — già portati in B5
- Tutti gli script shim in `scripts/` — 3 righe che chiamano Python, restano
- Script guest (`Install-CIToolchain-*.ps1`, `Prepare-*.ps1`, ecc.) — girano
dentro le VM Windows, non sull'host
---
## 3. Architettura prevista
Nuovi sub-comandi CLI sotto due nuovi gruppi:
```
python -m ci_orchestrator bench run --guest-os windows|linux
--template <path>
--concurrency N
--rounds N
--collect-metrics
python -m ci_orchestrator validate host # verifica stato host
python -m ci_orchestrator smoke run # end-to-end smoke test
```
Il gruppo `bench` sostituisce i tre script `*BurnIn*.ps1` con logica
unificata: avvia N clone in parallelo, misura tempo per job, confronta
con baseline, emette un report JSON in `CI_ARTIFACTS/bench/`.
Il gruppo `validate` porta `Validate-HostState.ps1`: verifica vmrun,
template snapshot, credenziali, permessi directory, act-runner attivo.
---
## 4. Aggiornamenti collaterali
- `plans/PhaseB-user-checklist.md` §B7: sostituire il comando `pwsh
Test-CapacityBurnIn.ps1` con `python -m ci_orchestrator bench run`.
- `deploy/systemd/README.md`: nessun riferimento a `pwsh`.
- `CLAUDE.md`: rimuovere nota "PowerShell 5.1 Constraints" se non più
rilevante per l'host (rimane valida per gli script guest Windows).
- `docs/RUNBOOK.md`: aggiornare procedure di burn-in e smoke test.
---
## 5. Prerequisiti
- Fase B completata e stabile (≥1 settimana, Passo 8 ✅).
- Nessuna dipendenza da `pwsh` nei timer systemd (già soddisfatta da B5).
---
## 6. Criteri di "C done"
- `python -m ci_orchestrator bench run --concurrency 4 --rounds 10` esegue
burn-in completo (Win + Linux) con output equivalente a `Test-CapacityBurnIn.ps1`.
- `python -m ci_orchestrator validate host` esce con 0 su host configurato
correttamente.
- `pwsh --version` può essere assente sull'host Linux senza che nessun
test, timer o script CI fallisca.
- Suite pytest ≥90% coverage, verde.
---
## 7. Rollback
I `.ps1` originali rimangono nel repo e funzionano su host Windows o su
Linux con `pwsh` installato. Il rollback è semplicemente reinstallare
`pwsh` e usare gli script esistenti.
+12 -5
View File
@@ -4,10 +4,11 @@ Decisione presa: implementare **prima Idea 1 (Python) + Idea 2 (host Linux)**
in sequenza, e **solo dopo** valutare Idea 3 (ESXi). in sequenza, e **solo dopo** valutare Idea 3 (ESXi).
| Fase | Cosa | File di dettaglio | | Fase | Cosa | File di dettaglio |
| ---- | ---------------------------------------------------------------------------------- | ---------------------------------------------------- | | ---- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| A | Rewrite in Python sull'host Windows attuale (codebase cross-platform-ready) | [idea-1-python-rewrite.md](idea-1-python-rewrite.md) | | A | Rewrite in Python sull'host Windows attuale (codebase cross-platform-ready) | [idea-1-python-rewrite.md](idea-1-python-rewrite.md) |
| B | Migrazione host: Windows 11 + Workstation Pro → Linux Mint + Workstation Pro Linux | [idea-2-linux-host.md](idea-2-linux-host.md) | | B | Migrazione host: Windows 11 + Workstation Pro → Linux Mint + Workstation Pro Linux | [idea-2-linux-host.md](idea-2-linux-host.md) |
| C | (Futuro, condizionato a A+B stabili) Aggiunta backend ESXi | [idea-3-esxi-support.md](idea-3-esxi-support.md) | | C | (Futuro, dopo B stabile) Eliminazione dipendenza `pwsh` dall'host Linux | [idea-3-powershell-removal.md](idea-3-powershell-removal.md) |
| D | (Futuro, condizionato a C stabili) Aggiunta backend ESXi | [idea-3-esxi-support.md](idea-3-esxi-support.md) |
--- ---
@@ -49,7 +50,8 @@ in sequenza, e **solo dopo** valutare Idea 3 (ESXi).
| ---- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | ---- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| A | Python 3.11+ su Windows; ambiente venv in `F:\CI\python\venv\` | Python, pytest, pypsrp/paramiko | | A | Python 3.11+ su Windows; ambiente venv in `F:\CI\python\venv\` | Python, pytest, pypsrp/paramiko |
| B | Hardware Linux Mint operativo; VMware Workstation Pro Linux installata; storage analogo a `F:\CI\` | systemd, bash, secret-tool, gestione utente di servizio | | B | Hardware Linux Mint operativo; VMware Workstation Pro Linux installata; storage analogo a `F:\CI\` | systemd, bash, secret-tool, gestione utente di servizio |
| C | Hardware ESXi + licenza Essentials o superiore; account vSphere dedicato | pyVmomi, datastore/portgroup management | | C | Fase B stabile ≥1 settimana; `pwsh` ancora installato durante il porting | click, subprocess, pytest |
| D | Hardware ESXi + licenza Essentials o superiore; account vSphere dedicato | pyVmomi, datastore/portgroup management |
--- ---
@@ -61,7 +63,10 @@ in sequenza, e **solo dopo** valutare Idea 3 (ESXi).
- **B done**: act_runner gira come systemd service su Linux Mint; tutti i - **B done**: act_runner gira come systemd service su Linux Mint; tutti i
workflow esistenti (Windows + Linux build) PASS dal nuovo host; storage workflow esistenti (Windows + Linux build) PASS dal nuovo host; storage
migrato a `/var/lib/ci/`; capacity burn-in PASS. migrato a `/var/lib/ci/`; capacity burn-in PASS.
- **C done** (se attivata): label `windows-build:esxi` operativa con backend - **C done** (se attivata): `pwsh` può essere disinstallato dall'host Linux
senza impatti operativi; `bench run`, `validate host` e `smoke run`
sostituiscono completamente i relativi `.ps1`; suite pytest verde ≥90%.
- **D done** (se attivata): label `windows-build:esxi` operativa con backend
pyVmomi; canary su almeno 1 workflow di produzione per ≥1 settimana pyVmomi; canary su almeno 1 workflow di produzione per ≥1 settimana
senza regressioni. senza regressioni.
@@ -75,5 +80,7 @@ in sequenza, e **solo dopo** valutare Idea 3 (ESXi).
- **Stop in B**: l'host Windows resta primario; eventuale runner Linux - **Stop in B**: l'host Windows resta primario; eventuale runner Linux
secondario può comunque essere utile per workload sperimentali (path secondario può comunque essere utile per workload sperimentali (path
"dual-host" descritto in [idea-2-linux-host.md](idea-2-linux-host.md) §7). "dual-host" descritto in [idea-2-linux-host.md](idea-2-linux-host.md) §7).
- **Stop pianificato in C**: nessun impatto — C è opzionale per definizione, - **Stop pianificato in C**: nessun impatto — gli script `.ps1` originali
restano funzionanti; `pwsh` resta installato. Il sistema continua a girare.
- **Stop pianificato in D**: nessun impatto — D è opzionale per definizione,
Workstation Pro su Linux copre già il caso d'uso primario. Workstation Pro su Linux copre già il caso d'uso primario.
+29 -23
View File
@@ -23,7 +23,12 @@ Sintesi fasi:
- **Stato: pronta** (gating "A done" soddisfatto). Esecuzione via - **Stato: pronta** (gating "A done" soddisfatto). Esecuzione via
`plans/PhaseB-user-checklist.md`; design/rischi/cronoprogramma in `plans/PhaseB-user-checklist.md`; design/rischi/cronoprogramma in
§2/§3/§5/§6 di questo piano. §2/§3/§5/§6 di questo piano.
- **Fase C — (Hook only, non implementata) backend ESXi via `pyVmomi`** - **Fase C — Eliminazione dipendenza `pwsh` dall'host Linux**
- Output verificabile: `bench run`, `validate host`, `smoke run` portati
in Python; `pwsh` disinstallabile senza impatti.
- Stato: non in scope (da avviare dopo B stabile). Design in
`plans/idea-3-powershell-removal.md`.
- **Fase D — (Hook only, non implementata) backend ESXi via `pyVmomi`**
- Output verificabile: Protocol `VmBackend` rispettato; `[backend]` - Output verificabile: Protocol `VmBackend` rispettato; `[backend]`
selector in `config.toml`. selector in `config.toml`.
- Stato: non in scope. - Stato: non in scope.
@@ -177,7 +182,7 @@ WinRM/SSH e credential store funzionanti contro l'ambiente reale via PoC
- [x] Test pytest unitari: `test_vmrun.py` (mock subprocess, casi `vmrun list` con e senza VMX target — copre errore #10), `test_winrm.py` (mock `pypsrp`), `test_ssh.py` (mock `paramiko`, copre errore #12), `test_credentials.py` (mock `keyring`) - [x] Test pytest unitari: `test_vmrun.py` (mock subprocess, casi `vmrun list` con e senza VMX target — copre errore #10), `test_winrm.py` (mock `pypsrp`), `test_ssh.py` (mock `paramiko`, copre errore #12), `test_credentials.py` (mock `keyring`)
- [x] Aggiungere job `python` a `gitea/workflows/lint.yml`: setup venv → `ruff check src/ tests/``mypy --strict src/``pytest --cov=ci_orchestrator --cov-fail-under=70` - [x] Aggiungere job `python` a `gitea/workflows/lint.yml`: setup venv → `ruff check src/ tests/``mypy --strict src/``pytest --cov=ci_orchestrator --cov-fail-under=70`
**Hook futuri Fase C**: il Protocol `VmBackend` deve usare nomi neutri **Hook futuri Fase D**: il Protocol `VmBackend` deve usare nomi neutri
(`clone_linked`, non `vmrun_clone`), accettare `template`/`snapshot`/`name` (`clone_linked`, non `vmrun_clone`), accettare `template`/`snapshot`/`name`
come stringhe opache (non path Windows), separare `clone_linked` da come stringhe opache (non path Windows), separare `clone_linked` da
`start` (ESXi richiede `PowerOn` come task distinto). Niente assunzioni `start` (ESXi richiede `PowerOn` come task distinto). Niente assunzioni
@@ -230,9 +235,9 @@ stato con l'orchestratore, sostituendoli con shim minimi.
- [ ] Convertire `tests/Remove-BuildVM.Tests.ps1` in `tests/test_commands_vm_remove.py` - [ ] Convertire `tests/Remove-BuildVM.Tests.ps1` in `tests/test_commands_vm_remove.py`
- [ ] Verificare che gli scheduled task esistenti (`Register-CIScheduledTasks.ps1`) continuino a funzionare invocando gli shim PS - [ ] Verificare che gli scheduled task esistenti (`Register-CIScheduledTasks.ps1`) continuino a funzionare invocando gli shim PS
**Hook futuri Fase C**: `vm cleanup` non deve assumere scan locale del **Hook futuri Fase D**: `vm cleanup` non deve assumere scan locale del
filesystem — la firma deve accettare un `VmBackend` come dipendenza, filesystem — la firma deve accettare un `VmBackend` come dipendenza,
così che in Fase C la stessa logica interroghi l'API ESXi (folder-scoped così che in Fase D la stessa logica interroghi l'API ESXi (folder-scoped
list). list).
**Test / validazione**: **Test / validazione**:
@@ -275,7 +280,7 @@ Python preservando il comportamento dei `.ps1` esistenti.
- [x] Aggiungere test pytest per `artifacts collect` (mock SFTP/WinRM file copy + tmp_path) - [x] Aggiungere test pytest per `artifacts collect` (mock SFTP/WinRM file copy + tmp_path)
- [ ] Validare end-to-end: clone WinBuild2025 → build script PowerShell trivial → collect artifact ZIP - [ ] Validare end-to-end: clone WinBuild2025 → build script PowerShell trivial → collect artifact ZIP
**Hook futuri Fase C**: `build run` deve ricevere un `VmHandle` opaco, **Hook futuri Fase D**: `build run` deve ricevere un `VmHandle` opaco,
non un path VMX (ESXi non ha path locale al control plane). Adattare le non un path VMX (ESXi non ha path locale al control plane). Adattare le
CLI a accettare entrambe (`--vmx` per workstation, `--vm-id` futuro per CLI a accettare entrambe (`--vmx` per workstation, `--vm-id` futuro per
ESXi) con dispatcher nel layer `commands/`. ESXi) con dispatcher nel layer `commands/`.
@@ -317,7 +322,7 @@ Gitea per chiamare la CLI Python direttamente.
- [ ] Eseguire workflow `self-test.yml` PASS - [ ] Eseguire workflow `self-test.yml` PASS
- [ ] Eseguire workflow `lint.yml` PASS - [ ] Eseguire workflow `lint.yml` PASS
**Hook futuri Fase C**: la selezione del backend deve avvenire in **Hook futuri Fase D**: la selezione del backend deve avvenire in
`job.py` leggendo `config.toml` `[backend].type` (default `workstation`). `job.py` leggendo `config.toml` `[backend].type` (default `workstation`).
Niente import diretto di `WorkstationVmrunBackend` in `job.py` — usare Niente import diretto di `WorkstationVmrunBackend` in `job.py` — usare
factory `backends.load_backend(config)`. factory `backends.load_backend(config)`.
@@ -359,7 +364,7 @@ aggiornare documentazione, eseguire burn-in finale.
- [ ] Eseguire burn-in 4 job concorrenti × 10 round PASS sull'host Windows — richiede VM reali, a carico utente - [ ] Eseguire burn-in 4 job concorrenti × 10 round PASS sull'host Windows — richiede VM reali, a carico utente
- [ ] Aggiornare `docs/RUNBOOK.md` con sezione "Operare da Python CLI" — deferito a chiusura Fase B (RUNBOOK riscritto end-to-end in B-finale) - [ ] Aggiornare `docs/RUNBOOK.md` con sezione "Operare da Python CLI" — deferito a chiusura Fase B (RUNBOOK riscritto end-to-end in B-finale)
**Hook futuri Fase C**: documentare in `docs/ARCHITECTURE.md` il **Hook futuri Fase D**: documentare in `docs/ARCHITECTURE.md` il
contratto `VmBackend` come "extension point" e il selettore `[backend]` contratto `VmBackend` come "extension point" e il selettore `[backend]`
in `config.toml` come unica via per aggiungere ESXi. in `config.toml` come unica via per aggiungere ESXi.
@@ -421,7 +426,7 @@ parallelo a A3/A4. Riferimento `idea-2-linux-host.md` §4.
- [ ] Validare `sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator --help` - [ ] Validare `sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator --help`
- [ ] Aggiungere `[paths.linux]` a `config.example.toml` con i path POSIX - [ ] Aggiungere `[paths.linux]` a `config.example.toml` con i path POSIX
**Hook futuri Fase C**: lo stesso host Linux farà da control plane se **Hook futuri Fase D**: lo stesso host Linux farà da control plane se
si attiverà ESXi. Non installare nulla che assuma "VM girano in locale" si attiverà ESXi. Non installare nulla che assuma "VM girano in locale"
(es. condivisioni `vmware-shared-folders` host-only). (es. condivisioni `vmware-shared-folders` host-only).
@@ -466,7 +471,7 @@ mantenendo snapshot integri.
- [ ] Validare snapshot `BaseClean-Linux` su `LinuxBuild2404.vmx` - [ ] Validare snapshot `BaseClean-Linux` su `LinuxBuild2404.vmx`
- [ ] Smoke test: `python -m ci_orchestrator vm new --template /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx --snapshot BaseClean --name smoke1` + `wait-ready` + `vm remove` - [ ] Smoke test: `python -m ci_orchestrator vm new --template /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx --snapshot BaseClean --name smoke1` + `wait-ready` + `vm remove`
**Hook futuri Fase C**: i template restano in formato VMX. Per ESXi **Hook futuri Fase D**: i template restano in formato VMX. Per ESXi
serviranno OVF (`ovftool`) — non fare nulla in B2, ma documentare che serviranno OVF (`ovftool`) — non fare nulla in B2, ma documentare che
il dataset attuale è la base per export futuro. il dataset attuale è la base per export futuro.
@@ -507,7 +512,7 @@ guest e i token Gitea, accessibili da `ci-runner` headless.
- [ ] PoC headless: testare lettura keyring da contesto systemd (no sessione D-Bus utente). Se fallisce, implementare backend `keyring` file-based con vault `age` o `sops` come fallback documentato - [ ] PoC headless: testare lettura keyring da contesto systemd (no sessione D-Bus utente). Se fallisce, implementare backend `keyring` file-based con vault `age` o `sops` come fallback documentato
- [ ] Documentare la scelta finale in `docs/HOST-SETUP.md` - [ ] Documentare la scelta finale in `docs/HOST-SETUP.md`
**Hook futuri Fase C**: anche ESXi userà credenziali da `keyring` (user **Hook futuri Fase D**: anche ESXi userà credenziali da `keyring` (user
vSphere). Lo stesso `KeyringCredentialStore` deve poter caricare `EsxiHost` vSphere). Lo stesso `KeyringCredentialStore` deve poter caricare `EsxiHost`
target — niente hard-coding di nomi credenziali. target — niente hard-coding di nomi credenziali.
@@ -551,7 +556,7 @@ systemd, equivalente al servizio Windows attuale.
- [ ] Validare `journalctl -u act-runner -f` mostra connessione a Gitea OK - [ ] Validare `journalctl -u act-runner -f` mostra connessione a Gitea OK
- [ ] **NON** avviare ancora workflow di produzione — il runner Windows è ancora primario - [ ] **NON** avviare ancora workflow di produzione — il runner Windows è ancora primario
**Hook futuri Fase C**: env vars `CI_*` restano valide; per ESXi si **Hook futuri Fase D**: env vars `CI_*` restano valide; per ESXi si
aggiungeranno solo `CI_BACKEND=esxi` + sezione `[backend.esxi]` in aggiungeranno solo `CI_BACKEND=esxi` + sezione `[backend.esxi]` in
`config.toml`. `act-runner.service` non cambia. `config.toml`. `act-runner.service` non cambia.
@@ -596,7 +601,7 @@ per l'inventario dei task.
- [ ] Validare `systemctl list-timers` mostra tutti i timer schedulati - [ ] Validare `systemctl list-timers` mostra tutti i timer schedulati
- [x] Documentare il mapping in `docs/HOST-SETUP.md` - [x] Documentare il mapping in `docs/HOST-SETUP.md`
**Hook futuri Fase C**: `vm cleanup` con backend ESXi userà la stessa **Hook futuri Fase D**: `vm cleanup` con backend ESXi userà la stessa
unit — il selettore backend è in `config.toml`, non nel comando. unit — il selettore backend è in `config.toml`, non nel comando.
**Rischi specifici**: **Rischi specifici**:
@@ -637,7 +642,7 @@ una finestra di manutenzione concordata.
- [ ] Trigger manuale `build-ns7zip.yml` matrix Win + Linux PASS - [ ] Trigger manuale `build-ns7zip.yml` matrix Win + Linux PASS
- [ ] Monitorare `journalctl -u act-runner -f` per ≥30 min sotto carico reale - [ ] Monitorare `journalctl -u act-runner -f` per ≥30 min sotto carico reale
**Hook futuri Fase C**: nessuno specifico in B6. Cutover non tocca **Hook futuri Fase D**: nessuno specifico in B6. Cutover non tocca
backend. backend.
**Rischi specifici**: **Rischi specifici**:
@@ -682,7 +687,7 @@ tempi paragonabili.
- [ ] Misurare uso disco `/var/lib/ci/build-vms/` durante e dopo burn-in (cleanup automatico) - [ ] Misurare uso disco `/var/lib/ci/build-vms/` durante e dopo burn-in (cleanup automatico)
- [ ] Documentare risultati in `docs/RUNBOOK.md` - [ ] Documentare risultati in `docs/RUNBOOK.md`
**Hook futuri Fase C**: i risultati di B7 sono il baseline contro cui **Hook futuri Fase D**: i risultati di B7 sono il baseline contro cui
confrontare un eventuale backend ESXi (criterio di "C done" in confrontare un eventuale backend ESXi (criterio di "C done" in
`idea-3-esxi-support.md` §8). `idea-3-esxi-support.md` §8).
@@ -725,7 +730,7 @@ host Windows.~~ → Host Windows mantenuto operativo a regime.
- [ ] Documentare in `docs/RUNBOOK.md` come usare entrambi gli host - [ ] Documentare in `docs/RUNBOOK.md` come usare entrambi gli host
- [ ] ~~Riallocare hardware~~ — NON applicabile (Windows host permanente) - [ ] ~~Riallocare hardware~~ — NON applicabile (Windows host permanente)
**Hook futuri Fase C**: nessuno. **Hook futuri Fase D**: nessuno.
**Rischi specifici**: **Rischi specifici**:
@@ -762,7 +767,7 @@ re-registrare runner Windows verso Gitea.
- [ ] Configurare `PSScriptAnalyzerSettings.psd1` per coprire `scripts/`, `template/`, `tests/` (già presente in repo) - [ ] Configurare `PSScriptAnalyzerSettings.psd1` per coprire `scripts/`, `template/`, `tests/` (già presente in repo)
- [ ] Configurare `pyproject.toml` con `[tool.ruff]`, `[tool.mypy]`, `[tool.pytest.ini_options]` - [ ] Configurare `pyproject.toml` con `[tool.ruff]`, `[tool.mypy]`, `[tool.pytest.ini_options]`
**Hook futuri Fase C**: nessuno specifico. **Hook futuri Fase D**: nessuno specifico.
**Test / validazione**: **Test / validazione**:
@@ -789,7 +794,7 @@ re-registrare runner Windows verso Gitea.
- [ ] In B4: configurare service unit per inviare stdout/stderr a journald (default systemd) e validare `journalctl -u act-runner -o json` - [ ] In B4: configurare service unit per inviare stdout/stderr a journald (default systemd) e validare `journalctl -u act-runner -o json`
- [ ] Documentare query journald utili in `docs/RUNBOOK.md` - [ ] Documentare query journald utili in `docs/RUNBOOK.md`
**Hook futuri Fase C**: log strutturati facilitano correlazione job ↔ backend. **Hook futuri Fase D**: log strutturati facilitano correlazione job ↔ backend.
**Test / validazione**: **Test / validazione**:
@@ -818,7 +823,7 @@ systemd (Linux) senza sessione utente interattiva.
- [ ] Implementare backend `keyring` file-based come opzione `KeyringFileBackend(vault_path, age_key_path)` se serve - [ ] Implementare backend `keyring` file-based come opzione `KeyringFileBackend(vault_path, age_key_path)` se serve
- [ ] Test pytest che simulano contesto headless (mock `keyring.get_credential` ritorna `None` → fallback a file vault) - [ ] Test pytest che simulano contesto headless (mock `keyring.get_credential` ritorna `None` → fallback a file vault)
**Hook futuri Fase C**: stesso `CredentialStore` userà credenziali **Hook futuri Fase D**: stesso `CredentialStore` userà credenziali
vSphere — mantenere API generica. vSphere — mantenere API generica.
**Test / validazione**: **Test / validazione**:
@@ -852,7 +857,7 @@ Linux + Python).
- [ ] Aggiornare `AGENTS.md`: sezione "Python development" + nota errore #12 N/A in Python - [ ] Aggiornare `AGENTS.md`: sezione "Python development" + nota errore #12 N/A in Python
- [ ] Aggiornare `README.md`: quick-start Python + Linux - [ ] Aggiornare `README.md`: quick-start Python + Linux
**Hook futuri Fase C**: lasciare placeholder "Backend ESXi (futuro)" in **Hook futuri Fase D**: lasciare placeholder "Backend ESXi (futuro)" in
`docs/ARCHITECTURE.md` e `docs/HOST-SETUP.md`. `docs/ARCHITECTURE.md` e `docs/HOST-SETUP.md`.
**Test / validazione**: **Test / validazione**:
@@ -868,7 +873,7 @@ Linux + Python).
- [ ] Link interni validi - [ ] Link interni validi
- [ ] Quick-start testato da operatore esterno - [ ] Quick-start testato da operatore esterno
## 4. Hook architetturali per Fase C ## 4. Hook architetturali per Fase D
Punti di design da rispettare durante A e B per non bloccare un futuro Punti di design da rispettare durante A e B per non bloccare un futuro
backend ESXi senza implementarlo: backend ESXi senza implementarlo:
@@ -955,7 +960,7 @@ Ogni voce: **Rischio** — Fase / Severità / Mitigazione / Owner action item.
- Mitigazione: strategia shim minimizza la finestra; `lint.yml` - Mitigazione: strategia shim minimizza la finestra; `lint.yml`
dual-stack. dual-stack.
- Owner: X1 attività complete. - Owner: X1 attività complete.
- **Astrazione `VmBackend` over-engineered se Fase C non parte mai** - **Astrazione `VmBackend` over-engineered se Fase D non parte mai**
- Fase: A1 — Severità: Bassa - Fase: A1 — Severità: Bassa
- Mitigazione: 1 implementazione concreta + Protocol = ~50 LOC extra; - Mitigazione: 1 implementazione concreta + Protocol = ~50 LOC extra;
costo trascurabile. costo trascurabile.
@@ -1050,7 +1055,7 @@ Ogni voce: **Rischio** — Fase / Severità / Mitigazione / Owner action item.
Domande di auto-verifica a cui il documento risponde "sì": Domande di auto-verifica a cui il documento risponde "sì":
- **Ogni voce della checklist master compare almeno una volta come `- [ ]` dentro lo step corrispondente?** Sì: voci `[A1]…[A5]` mappate alle attività in §1, `[B1]…[B8]` in §2, `[X1]…[X4]` in §3. - **Ogni voce della checklist master compare almeno una volta come `- [ ]` dentro lo step corrispondente?** Sì: voci `[A1]…[A5]` mappate alle attività in §1, `[B1]…[B8]` in §2, `[X1]…[X4]` in §3.
- **Ogni step `A<n>`/`B<n>`/`X<n>` ha tutte le sottosezioni richieste?** Sì: Obiettivo, Input/dipendenze, Attività, Hook futuri Fase C, Test/validazione, Rollback, Definizione di fatto presenti per ogni step (B*: in più rischi specifici). - **Ogni step `A<n>`/`B<n>`/`X<n>` ha tutte le sottosezioni richieste?** Sì: Obiettivo, Input/dipendenze, Attività, Hook futuri Fase D, Test/validazione, Rollback, Definizione di fatto presenti per ogni step (B*: in più rischi specifici).
- **I 12 errori frequenti di `AGENTS.md` sono stati indirizzati o dichiarati non applicabili?** - **I 12 errori frequenti di `AGENTS.md` sono stati indirizzati o dichiarati non applicabili?**
- #1 (sintassi PS 7+): si applica solo agli shim PS residui in A2/A3 — vincolo PS 5.1 mantenuto - #1 (sintassi PS 7+): si applica solo agli shim PS residui in A2/A3 — vincolo PS 5.1 mantenuto
- #2 (`$LASTEXITCODE` non controllato): N/A in Python (`subprocess.returncode` esplicito) - #2 (`$LASTEXITCODE` non controllato): N/A in Python (`subprocess.returncode` esplicito)
@@ -1072,7 +1077,8 @@ Domande di auto-verifica a cui il documento risponde "sì":
- [plans/ideas-overview.md](ideas-overview.md) — razionale ordine fasi, criteri "fase completata", rollback - [plans/ideas-overview.md](ideas-overview.md) — razionale ordine fasi, criteri "fase completata", rollback
- [plans/idea-1-python-rewrite.md](idea-1-python-rewrite.md) — Fase A: design, mappa traduzione, step A1A5, layout repo, rischi - [plans/idea-1-python-rewrite.md](idea-1-python-rewrite.md) — Fase A: design, mappa traduzione, step A1A5, layout repo, rischi
- [plans/idea-2-linux-host.md](idea-2-linux-host.md) — Fase B: hypervisor, mappa adattamento, step B1B8, rischi - [plans/idea-2-linux-host.md](idea-2-linux-host.md) — Fase B: hypervisor, mappa adattamento, step B1B8, rischi
- [plans/idea-3-esxi-support.md](idea-3-esxi-support.md) — Fase C: §2 architettura, §3 backend pyVmomi (solo per hook) - [plans/idea-3-powershell-removal.md](idea-3-powershell-removal.md) — Fase C: eliminazione `pwsh` dall'host Linux
- [plans/idea-3-esxi-support.md](idea-3-esxi-support.md) — Fase D: §2 architettura, §3 backend pyVmomi (solo per hook)
- [docs/ARCHITECTURE.md](../docs/ARCHITECTURE.md) — layout attuale del sistema - [docs/ARCHITECTURE.md](../docs/ARCHITECTURE.md) — layout attuale del sistema
- [docs/CI-FLOW.md](../docs/CI-FLOW.md) — flusso job CI corrente - [docs/CI-FLOW.md](../docs/CI-FLOW.md) — flusso job CI corrente
- [docs/HOST-SETUP.md](../docs/HOST-SETUP.md) — setup host Windows attuale - [docs/HOST-SETUP.md](../docs/HOST-SETUP.md) — setup host Windows attuale