# Idea 3 — Supporto ESXi per le Build VM > 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. --- ## 1. Obiettivo Permettere a `Invoke-CIJob` di usare un host **ESXi** (o cluster vCenter) come backend di virtualizzazione, mantenendo: - 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 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. --- ## 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 ` | `VirtualMachine.PowerOn()` (Task) | | Stop VM | `vmrun stop hard` | `VirtualMachine.PowerOff()` (Task) | | Delete VM | `vmrun deleteVM ` | `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 ``` ┌──────────────┐ ┌─────────────────────────────┐ │ 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)│ └─────┬────────────┘ │ WinRM/SSH (network L3 ammessa) ▼ 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. --- ## 3. Stima volumi / sforzo (relativa) | 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 | --- ## 4. Pro / Contro ### 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. --- ## 5. Sinergia con altre idee - **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. --- ## 6. Decision checklist Procedere **solo se** almeno 3 dei seguenti sono veri: - [ ] È 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. Se la concorrenza richiesta è ≤4 job e l'hardware attuale (i9 + 64GB) regge, **l'investimento ESXi non si ripaga** rispetto a Workstation locale. --- ## 7. Path incrementale "minimo": ESXi opzionale Anziché migrazione totale, supportare **entrambi** i backend in parallelo: - 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.