Add unified implementation plan for Phase A and Phase B in Markdown format

- Create a new document `plans/implementation-plan-A-B.md` that consolidates the implementation plans for the Python rewrite (Phase A) and the migration to Linux Mint (Phase B).
- The document includes detailed sections such as executive summary, checklist, prerequisites, step-by-step activities, architectural hooks for future phases, risk matrix, and references.
- Ensure the plan is self-contained, adhering to specified structure and style guidelines, and does not introduce new technologies or modify existing files.
This commit is contained in:
2026-05-13 10:49:10 +02:00
parent 081f7e1d16
commit 770ac1edf8
6 changed files with 1683 additions and 522 deletions
+136 -161
View File
@@ -1,204 +1,179 @@
# Idea 3 — Supporto ESXi per le Build VM
# Fase C — Supporto ESXi per le Build VM (futuro)
> Stato: **proposta / valutazione**.
> Modello: host CI (Windows o Linux) continua a fare orchestrazione ma le
> build VM girano su un **server ESXi remoto** invece che in VMware
> Workstation locale.
> **Stato**: **piano differito**, da rivalutare dopo che Fase A
> ([rewrite Python](idea-1-python-rewrite.md)) e Fase B
> ([host Linux](idea-2-linux-host.md)) sono stabili in produzione.
> Vedi [overview](ideas-overview.md).
>
> Questo documento esiste per:
> 1. Garantire che il design di Fase A abbia gli hook corretti
> (astrazione `VmBackend`).
> 2. Avere un piano pronto se/quando si decide di scalare oltre i limiti
> dell'host singolo Workstation Pro.
---
## 1. Obiettivo
## 1. Quando attivare Fase C
Permettere a `Invoke-CIJob` di usare un host **ESXi** (o cluster vCenter)
come backend di virtualizzazione, mantenendo:
Fase C ha senso **solo se** si verifica almeno uno di:
- workflow YAML invariati (eventualmente con nuovo label `windows-build:esxi`)
- transport WinRM/SSH verso i guest invariato
- formato artifact e flusso `clone → start → wait → build → collect → destroy` identico
- Saturazione della concorrenza locale (>4 job paralleli regolarmente)
- Necessità di disaccoppiare hardware CI control plane (ufficio) dal hardware
build (rack/datacenter)
- Disponibilità di hardware ESXi + licenza vSphere Essentials o superiore
- Richiesta di QoS / resource pool per i job CI vs altri carichi
Cambia: come si fa clone/start/stop/delete della VM, dove vivono i dischi,
come si determina l'IP del guest, come si autenticano i comandi di management.
Se nessuno è vero a 6-12 mesi dal completamento Fase B, **non aprire Fase C**:
Workstation Pro su Linux copre il caso d'uso e l'overhead operativo di un
secondo backend non è giustificato.
---
## 2. Fattibilità
### 2.1 API di management ESXi
| Opzione | Pro | Contro | Verdetto |
| ---------------------------------------- | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------- |
| **A. pyVmomi** (Python SDK ufficiale) | API completa (cloni, snapshot, power ops, GuestOps); supportata; va anche contro singolo host ESXi senza vCenter. | Solo Python. Curva di apprendimento (managed object reference, task tracking). | **Raccomandata se si va Python (Idea 1).** |
| **B. PowerCLI** (`VMware.PowerCLI` PSGallery) | Idiomatica per PowerShell; comandi `New-VM`, `Get-Snapshot`, ecc. molto leggibili. | Modulo grosso (~2 GB), Windows-friendly ma installazione richiede `Install-Module`. Performance avvio cmdlet non sempre rapida. | Buona se si **resta in PowerShell**. |
| C. `ovftool` + REST API ESXi (vSphere API REST) | Standard moderno; copre la maggior parte delle operazioni in vSphere 7+. | API REST single-host ha gap rispetto a SOAP/pyVmomi; complicata gestione task. | Sconsigliata come strato unico. |
| D. `govc` (VMware/govmomi CLI) | Binario Go portabile, scriptabile da shell qualsiasi. | Meno espressivo per logiche complesse (loop, error handling); diventa un "second-class" tooling. | Buona per script ad-hoc, non per orchestratore. |
Le due strade realistiche sono **A (pyVmomi)** o **B (PowerCLI)**, in funzione
dell'esito dell'Idea 1.
### 2.2 Mappa di adattamento
| Operazione | Workstation oggi | ESXi domani (pyVmomi) |
| ----------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------- |
| Linked clone | `vmrun clone ... linked -snapshot=BaseClean` | `vim.VirtualMachineCloneSpec` con `linkedClone=True` e snapshot ref |
| Start VM | `vmrun start <vmx>` | `VirtualMachine.PowerOn()` (Task) |
| Stop VM | `vmrun stop <vmx> hard` | `VirtualMachine.PowerOff()` (Task) |
| Delete VM | `vmrun deleteVM <vmx>` | `VirtualMachine.Destroy_Task()` |
| List snapshots | `vmrun listSnapshots` | `VirtualMachine.snapshot.rootSnapshotList` (tree) |
| Get guest IP | `vmrun getGuestIPAddress` (errore #10) | `VirtualMachine.guest.ipAddress` (richiede VMware Tools attivi) |
| Test running | `vmrun list` + path search | `VirtualMachine.runtime.powerState == 'poweredOn'` |
| Trasferimento file pre-WinRM/SSH | non usato | GuestOperationsManager (FileManager + ProcessManager) — opzionale, oggi non serve |
Il transport `_Transport.psm1` (SSH) e le sessioni WinRM **non cambiano**:
una volta che la VM è up con IP raggiungibile, l'host CI parla direttamente
col guest come oggi.
### 2.3 Architettura proposta
## 2. Architettura prevista
```
┌──────────────┐ ┌─────────────────────────────┐
│ Gitea │ │ ESXi host(s) │
│ act_runner │ │ ├─ Template Windows (snap BaseClean) │
│ │ ├─ Template Linux (snap BaseClean-Linux) │
└──────┬───────┘ │ └─ Datastore: ci-builds │
└──────────▲──────────────────┘
orchestrate │ vSphere API (443)
┌──────────────────┐
CI orchestrator │──────────────┘
(host Win o Lin)
│ act_runner │ │ ├─ Template Windows (snap BaseClean)
(Linux Mint) │ │ ├─ Template Linux (snap BaseClean-Linux)
│ │ │ └─ Datastore: ci-builds │
└──────┬───────┘ └──────────▲──────────────────┘
│ vSphere API (443)
▼ │
┌──────────────────┐ │
ci_orchestrator │───────────┘
(Python, Linux)
│ ↳ EsxiBackend │
└─────┬────────────┘
│ WinRM/SSH (network L3 ammessa)
│ WinRM/SSH
Build VM efimera su ESXi
```
L'host CI continua a esistere come "control plane". Può essere lo stesso
hardware di oggi (Windows 11) oppure migrato a Linux (Idea 2). Le build VM
non girano più localmente.
### 2.4 Nuove configurazioni richieste
- **ESXi host** raggiungibile da host CI sulla 443/TCP.
- Account di servizio ESXi (`ci-runner@vsphere.local` o `local user` con
ruolo custom): permessi minimi su datastore, folder, snapshot, power ops.
- Datastore dedicato (SSD/NVMe) per cloni e template; quota / monitoring.
- Resource pool dedicato `ci-builds` con CPU/memory limits.
- Portgroup di rete con DHCP raggiungibile (o assegnazione IP statica via
cloud-init / Sysprep).
- Snapshot dei template **identico** al setup attuale (`BaseClean` /
`BaseClean-Linux`) — convertire VMX→VMX-su-ESXi via OVF (`ovftool`).
### 2.5 Rischi specifici
| Rischio | Severità | Mitigazione |
| --------------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------- |
| Linked clone su ESXi standalone (senza vCenter) ha limitazioni rispetto a Workstation | Alta | Validare in PoC: alcune versioni ESXi free non supportano `CloneVM_Task` via API senza license. |
| Licenza ESXi: la versione free **non espone le API write** (solo read-only) — bug noto vSphere | **Critica** | Serve almeno **vSphere Essentials** o licenza valutativa. Verificare PRIMA di pianificare. |
| Throughput linked clone su NFS/iSCSI datastore inferiore a SSD locale Workstation | Media | Datastore VMFS su NVMe locale o vSAN; benchmark con `Test-CapacityBurnIn`. |
| Tempo medio "clone → IP raggiungibile" più alto rispetto a Workstation locale | Media | Misurare con `Measure-CIBenchmark`; ottimizzare warm pool template (`Backup-CITemplate` non più utile, sostituire con template VM in folder dedicata). |
| Gestione concorrente cloni: race su nome VM o snapshot revert | Media | Lock per `JobId` lato orchestrator; oppure naming con suffisso UUID. |
| Determinazione IP: VMware Tools deve essere attivo e DHCP funzionante | Bassa | Già un prerequisito attuale (`Wait-VMReady`). Documentare in `AGENTS.md` nuova versione. |
| Errore #11 (machine-id identico sui clone Linux) si ripropone identico su ESXi | Bassa | Stessa fix: reset machine-id pre-snapshot. Documentato. |
| Sicurezza: credenziali vCenter/ESXi nello stesso store delle credenziali guest | Media | Target Credential Manager separato (`ESXiServiceAccount`) o keyring + ACL. |
| Cleanup VM orfane più costoso (richiede chiamata API per ogni VM in folder) | Bassa | Riscrivere `Cleanup-OrphanedBuildVMs` per usare folder-scoped query. |
### 2.6 Sequenza di implementazione consigliata
1. **PoC manuale**: clonare manualmente un template su ESXi via UI/PowerCLI,
avviare, fare WinRM da host CI. Misurare tempi.
2. **PoC scriptato**: una versione minimale di `New-BuildVM-ESXi.ps1` (o
`new_build_vm_esxi.py`) che fa clone+start. Validare race conditions.
3. **Astrazione `IVmBackend`**: introdurre nei moduli `_Common` /
`vmrun.py` un'interfaccia a 2 implementazioni (`Workstation`, `ESXi`),
selezionata via env var (`GITEA_CI_VM_BACKEND=workstation|esxi`).
In questo modo si può fare canary deploy job-per-job.
4. Migrazione template (export OVF da Workstation, import su ESXi datastore).
5. Workflow YAML aggiornati con label `windows-build:esxi` accanto a
`windows-build:host`.
6. Capacity burn-in concorrente sull'host ESXi.
L'host CI Linux (Fase B) continua a esistere come control plane.
Le build VM girano su ESXi remoto. Il transport WinRM/SSH al guest non
cambia.
---
## 3. Stima volumi / sforzo (relativa)
## 3. Implementazione: nuovo backend pyVmomi
| Area | Indicatori dimensione | Complessità |
| -------------------------------------------------------------------------- | ---------------------------------------- | ----------- |
| Setup hardware/licenze ESXi | 1 host fisico + licenza Essentials | Variabile (acquisto) |
| PoC clone/start/stop via pyVmomi o PowerCLI | ~200 righe | Media |
| Astrazione backend (`IVmBackend` con 2 impl) | refactor di `_Common`, `New-BuildVM`, `Remove-BuildVM`, `Wait-VMReady` | Media |
| Export OVF dei template + import ESXi + ri-validazione snapshot | 3 template | Media |
| Riconfigurazione network/DHCP per build VM su ESXi | 1 portgroup + DHCP scope | Media |
| Adattamento `Cleanup-OrphanedBuildVMs`, `Watch-DiskSpace` (datastore-aware) | ~300 righe | Bassa |
| Documentazione (`HOST-SETUP.md` nuovo capitolo ESXi, `OPTIMIZATION.md`) | 2-3 file md | Bassa |
| Validazione e2e + benchmark vs Workstation | piano test esistente esteso | Alta |
Sfruttando l'astrazione `VmBackend` introdotta in Fase A:
```python
# src/ci_orchestrator/backends/esxi.py
class EsxiBackend(VmBackend):
def __init__(self, host: str, user: str, password: str, datastore: str, folder: str): ...
def clone_linked(self, template: str, snapshot: str, name: str) -> VmHandle: ...
def start(self, vm: VmHandle) -> None: ...
def stop(self, vm: VmHandle, hard: bool = True) -> None: ...
def delete(self, vm: VmHandle) -> None: ...
def get_ip(self, vm: VmHandle, timeout: float) -> str: ...
```
Selezione backend via env / config:
```toml
[backend]
type = "esxi" # oppure "workstation"
[backend.esxi]
host = "esxi.lab.local"
user = "ci-runner@vsphere.local"
datastore = "ci-builds"
folder = "ci"
```
---
## 4. Pro / Contro
## 4. Mappa operazioni Workstation → ESXi
### Pro
- **Scalabilità**: un ESXi con CPU/RAM adeguate ospita facilmente 8-16 job concorrenti
vs ~4 con Workstation locale (limite testato in `Test-CapacityBurnIn`).
- Disaccoppia host CI (control plane) da hardware di build (data plane).
- Resource pool / shares / reservation: QoS per i job CI.
- Backup template / DR via snapshot ESXi nativi o appliance Veeam.
- Permette di avere host CI Linux (Mint) senza dover usare KVM (Idea 2 + Idea 3 sinergiche).
- Multi-runner futuro più semplice (più host CI puntano allo stesso ESXi).
### Contro
- **Costo licenza** vSphere (la free non basta per le API write).
- Hardware aggiuntivo dedicato (o ri-uso di un server esistente).
- Latenza di rete in più rispetto a in-process locale.
- Throughput clone dipende da datastore; può essere peggio se non si ha SSD locale ESXi.
- Backup VMDK template (`Backup-CITemplate.ps1`) va riprogettato (usare
snapshot ESXi nativi o export OVF schedulato).
- Disaster scenario: se ESXi è giù, **tutte** le pipeline si fermano. Con
Workstation locale il guasto era confinato all'host CI.
| Operazione | Workstation (oggi) | ESXi (Fase C, pyVmomi) |
| ----------------------------- | --------------------------------------------- | ----------------------------------------------------------------------- |
| Linked clone | `vmrun clone ... linked -snapshot=BaseClean` | `vim.VirtualMachineCloneSpec(linkedClone=True, snapshot=ref)` |
| Start VM | `vmrun start <vmx>` | `VirtualMachine.PowerOn()` (Task) |
| Stop VM | `vmrun stop <vmx> hard` | `VirtualMachine.PowerOff()` (Task) |
| Delete VM | `vmrun deleteVM <vmx>` | `VirtualMachine.Destroy_Task()` |
| List snapshots | `vmrun listSnapshots` | `VirtualMachine.snapshot.rootSnapshotList` |
| Get guest IP | `vmrun getGuestIPAddress` | `VirtualMachine.guest.ipAddress` (richiede VMware Tools nei guest) |
| Test running | `vmrun list` | `VirtualMachine.runtime.powerState == 'poweredOn'` |
---
## 5. Sinergia con altre idee
## 5. Setup ESXi richiesto (Step C0)
- **Idea 1 (Python)**: forte sinergia. `pyVmomi` è Python-only; restando in
PowerShell si è costretti a `VMware.PowerCLI`, che ha overhead di
caricamento e dimensioni notevoli.
- **Idea 2 (host Linux)**: complementare. Idea 3 sposta il "dove girano le VM"
ma non vincola il "dove gira l'orchestrator". Si può:
- **Win host + ESXi backend**: minima migrazione lato CI script (resta PS).
- **Linux host + ESXi backend**: massima modernizzazione, ma somma i rischi
delle due migrazioni. Solo dopo Idee 1+2 stabilizzate.
- Con Idea 3 implementata, l'utilità di Idea 2 (host Linux con KVM locale)
cala: la VM locale serve solo per debug, non più per CI in production.
Prerequisiti hardware/licenza da verificare PRIMA di pianificare:
- **Licenza**: ESXi free **non basta** (le API write sono bloccate dal 2020).
Serve almeno **vSphere Essentials** o licenza valutativa rinnovabile.
- **Hardware**: server con CPU che supporti la versione ESXi target,
RAM ≥64 GB, NVMe locale per datastore.
- **Network**: portgroup dedicato per le build VM, DHCP raggiungibile.
- **Account**: user dedicato con ruolo custom (datastore, folder, snapshot,
power, network — minimo set richiesto da `clone_linked`/`destroy`).
---
## 6. Decision checklist
## 6. Sequenza implementativa
Procedere **solo se** almeno 3 dei seguenti sono veri:
### C1 — Validazione ambiente
- Setup hardware ESXi + licenza
- Account vSphere dedicato
- Test manuale clone+start+stop via UI vSphere
- Misurazione tempi di clone (baseline)
- [ ] È disponibile (o pianificato) hardware ESXi + licenza Essentials.
- [ ] Si prevede di superare i 4 job concorrenti regolarmente.
- [ ] Si vuole disaccoppiare hardware CI da hardware build (es. CI in ufficio,
build in rack).
- [ ] Si è pianificata l'Idea 1 (Python) o si è disposti a usare PowerCLI.
- [ ] Disaster recovery / backup datastore è un requisito esplicito.
### C2 — Implementazione `EsxiBackend`
- `pip install pyvmomi` aggiunto al `pyproject.toml`
- `src/ci_orchestrator/backends/esxi.py` implementato
- Test pytest con `pyvmomi` mock + un test di integrazione
opzionale che gira solo se env `CI_TEST_ESXI_HOST` è settata
Se la concorrenza richiesta è ≤4 job e l'hardware attuale (i9 + 64GB) regge,
**l'investimento ESXi non si ripaga** rispetto a Workstation locale.
### C3 — Migrazione template
- Export OVF dei template Workstation: `ovftool ... template.vmx template.ovf`
- Import su datastore ESXi: `ovftool template.ovf vi://...`
- Verifica WinRM/SSH raggiungibili dal control plane verso le VM ESXi
- Snapshot `BaseClean` / `BaseClean-Linux` ricreati lato ESXi
### C4 — Canary deploy
- Workflow di test dedicato con label `windows-build:esxi` o
config override `backend=esxi`
- Eseguito quotidianamente per ≥1 settimana
- Confronto metriche (tempo totale, success rate) vs Workstation backend
### C5 — Rollout selettivo
- Workflow di produzione spostati uno a uno su backend ESXi
- Monitoring tempi via `Measure-CIBenchmark` equivalente Python
- Workstation backend resta disponibile come fallback (basta cambiare config)
### C6 — Adattamenti tooling secondari
- `Cleanup-OrphanedBuildVMs` esteso per query ESXi folder-scoped
- `Watch-DiskSpace` esteso a query datastore via API
- `Backup-CITemplate` sostituito da snapshot ESXi nativi o `ovftool` schedulato
---
## 7. Path incrementale "minimo": ESXi opzionale
## 7. Rischi specifici Fase C
Anziché migrazione totale, supportare **entrambi** i backend in parallelo:
| Rischio | Severità | Mitigazione |
| -------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------- |
| Licenza ESXi free blocca API write (`CloneVM_Task` non autorizzata) | **Critica** | Verificare licenza in C1 prima di qualsiasi sviluppo. Procurare vSphere Essentials. |
| Linked clone su ESXi standalone (no vCenter) ha gap funzionali | Alta | PoC manuale in C1; se gap rilevante, valutare full clone vs linked. |
| Tempo clone+poweron+IP > Workstation locale per latenza rete + overhead vSphere | Media | Misurare in C1; possibile mitigazione: pool di VM "warm" pre-clonate. |
| VMware Tools nel guest non sempre rapide a riportare IP via API | Bassa | Stesso problema oggi (`AGENTS.md` errore #10). Fallback: parse DHCP lease su ESXi via API. |
| Concorrenza: race condition su naming VM o folder | Media | Lock per JobId lato orchestrator; suffisso UUID nel nome VM. |
| Cleanup VM orfane più costoso (API call per ogni VM in folder) | Bassa | Riscrivere cleanup come query folder-scoped, non scan globale. |
| Single point of failure: ESXi giù = tutta la CI giù | Media | Documentare procedura fallback su backend Workstation locale (basta cambio config). |
| Errore #11 `AGENTS.md` (machine-id identico clone Linux) si ripropone | Bassa | Stessa fix lato template, già documentata. |
- Lasciare default `windows-build:host` (Workstation locale, situazione attuale).
- Aggiungere label `windows-build:esxi` per job specifici (es. burn-in
pesanti, regression suite notturna).
- Naming dei job e folder ESXi prefissati con `ci-` per filtering.
- Eventuale rollback semplice (basta disabilitare il label).
---
Sforzo ~50% rispetto a migrazione totale, debito tecnico controllato perché
l'astrazione `IVmBackend` è già lì per design.
## 8. Definizione di "fatto" (Fase C)
- [ ] Hardware ESXi + licenza Essentials operativi
- [ ] `EsxiBackend` implementato, testato (unit + integration test)
- [ ] Template Windows e Linux importati e funzionanti su ESXi con snapshot
- [ ] Almeno 1 workflow di produzione in canary su backend ESXi per ≥1 settimana
senza regressioni
- [ ] Documentazione (`docs/HOST-SETUP.md`, `docs/ARCHITECTURE.md`,
`AGENTS.md`) aggiornata con istruzioni multi-backend
- [ ] Procedura di rollback su backend Workstation testata e documentata