diff --git a/plans/PhaseB-user-checklist.md b/plans/PhaseB-user-checklist.md new file mode 100644 index 0000000..00a1c53 --- /dev/null +++ b/plans/PhaseB-user-checklist.md @@ -0,0 +1,484 @@ +# Fase B — Checklist finale per l'utente + +La Fase B è la migrazione del runner CI dall'host Windows attuale a un +nuovo host **Linux Mint LTS** con VMware Workstation Pro Linux. + +> **Stato repo**: solo lo step **B5** (unit `systemd` per i task +> periodici) è già committato in `deploy/systemd/` sul branch +> `feature/python-rewrite-phase-a` (commit `50d37b5`). +> Tutti gli altri step (B1–B4, B6–B8) sono **operazioni hardware** +> sull'host Linux nuovo e devono essere eseguiti dall'utente. + +> **Pre-requisito**: la Fase A deve essere `done` (vedi +> `plans/PhaseA-user-checklist.md` Passo 9, merge + tag). +> B1, B2, B3 possono partire in parallelo a A3/A4/A5; B4–B8 sono +> sequenziali e iniziano solo dopo "A done". + +> **Tempo stimato totale**: 1–2 giorni di lavoro distribuiti su una +> finestra di 1–2 settimane (per consentire il burn-in tra B6 e B8). + +--- + +## Passo 1 — Setup host Linux Mint (B1) + +**Obiettivo**: hardware target con Linux Mint LTS, VMware Workstation +Pro Linux, layout storage e venv Python pronti. + +- [ ] Installare Linux Mint LTS sull'hardware target. +- [ ] `sudo apt update && sudo apt full-upgrade -y && sudo reboot` +- [ ] Scaricare e installare VMware Workstation Pro Linux (bundle + `.bundle` da Broadcow): + + ```bash + sudo bash VMware-Workstation-Full-*.bundle + vmrun -T ws --version # deve ritornare versione coerente + ``` + +- [ ] Smoke test Workstation (UI): creare VM trivia, clone, start, + stop, delete. +- [ ] Configurare `vmnet8` NAT range `192.168.79.0/24` (allineato a + Windows) editando `/etc/vmware/vmnet8/dhcpd/dhcpd.conf` o via + `vmware-netcfg`. +- [ ] Creare utente di servizio `ci-runner`: + + ```bash + sudo useradd -r -m -s /bin/bash ci-runner + ``` + +- [ ] Creare layout storage: + + ```bash + sudo mkdir -p /var/lib/ci/{build-vms,artifacts,templates,keys} + sudo chown -R ci-runner:ci-runner /var/lib/ci + sudo chmod 750 /var/lib/ci /var/lib/ci/* + sudo setfacl -d -m u:ci-runner:rwX /var/lib/ci/build-vms + ``` + +- [ ] Installare Python 3.11+ e creare venv produzione: + + ```bash + sudo apt install -y python3.11 python3.11-venv git + sudo mkdir -p /opt/ci + sudo python3.11 -m venv /opt/ci/venv + sudo chown -R ci-runner:ci-runner /opt/ci + ``` + +- [ ] Clonare il repo e installare il package nel venv: + + ```bash + sudo -u ci-runner git clone https://gitea.emulab.it/Simone/local-ci-cd-system.git /opt/ci/local-ci-cd-system + sudo -u ci-runner /opt/ci/venv/bin/pip install -e /opt/ci/local-ci-cd-system + sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator --help + ``` + + Atteso: lista degli 11 sub-comandi. + +- [ ] Installare PowerShell Core (richiesto da `Invoke-RetentionPolicy.ps1` + e `Backup-CITemplate.ps1`): + + ```bash + sudo apt install -y wget apt-transport-https software-properties-common + source /etc/os-release + wget -q https://packages.microsoft.com/config/ubuntu/${VERSION_ID}/packages-microsoft-prod.deb + sudo dpkg -i packages-microsoft-prod.deb + sudo apt update && sudo apt install -y powershell + pwsh --version + ``` + +--- + +## Passo 2 — Trasferimento template VM (B2) + +**Obiettivo**: copiare i template VMware da `F:\CI\Templates\` su +`/var/lib/ci/templates/` mantenendo gli snapshot. + +> ⚠️ AGENTS.md errore #9: i template devono essere **fully +> powered-off** prima della copia. Verificare assenza di `*.vmem` / +> `*.vmsn` di runtime. + +- [ ] Sull'host Windows: + + ```powershell + Get-ChildItem 'F:\CI\Templates' -Recurse -Include *.vmem,*.vmsn + # atteso: nessun risultato + ``` + +- [ ] Sull'host Linux, eseguire rsync via SSH dall'host Windows + (richiede OpenSSH Server attivo su Windows o, in alternativa, + `scp -r` lanciato da Windows verso Linux): + + ```bash + sudo -u ci-runner rsync -av --progress \ + user@windows-host:/cygdrive/f/CI/Templates/ \ + /var/lib/ci/templates/ + ``` + +- [ ] Validare integrità snapshot: + + ```bash + find /var/lib/ci/templates -name '*.vmx' -exec vmrun -T ws listSnapshots {} \; + ``` + + Atteso: `BaseClean` su `WinBuild2025.vmx` e `WinBuild2022.vmx`, + `BaseClean-Linux` su `LinuxBuild2404.vmx`. + +- [ ] Aprire ciascun `.vmx` su Workstation Linux per registrarli; + al prompt rispondere "**I copied it**". +- [ ] Smoke test pipeline VM: + + ```bash + sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator vm new \ + --template /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx \ + --snapshot BaseClean --name smoke-b2-win + sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator wait-ready \ + --vmx /var/lib/ci/build-vms/smoke-b2-win/smoke-b2-win.vmx \ + --guest-os windows --timeout 180 + sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator vm remove \ + --vmx /var/lib/ci/build-vms/smoke-b2-win/smoke-b2-win.vmx --force + ``` + + Ripetere per `LinuxBuild2404` (snapshot `BaseClean-Linux`, + `--guest-os linux`). + +--- + +## Passo 3 — Trasferimento credenziali e chiavi (B3) + +**Obiettivo**: chiavi SSH e credenziali guest disponibili al user +`ci-runner` headless. + +- [ ] Copiare le chiavi SSH guest Linux: + + ```bash + sudo mkdir -p /etc/ci/keys + sudo scp user@windows-host:/cygdrive/f/CI/keys/ci_linux /etc/ci/keys/ + sudo scp user@windows-host:/cygdrive/f/CI/keys/ci_linux.pub /etc/ci/keys/ + sudo chown ci-runner:ci-runner /etc/ci/keys/* + sudo chmod 600 /etc/ci/keys/ci_linux + sudo chmod 644 /etc/ci/keys/ci_linux.pub + ``` + +- [ ] Re-store credenziale guest Windows (sostituire la password al + prompt — **NON** inserirla in chat o issue): + + ```bash + sudo -u ci-runner secret-tool store --label='BuildVMGuest' service ci target BuildVMGuest + ``` + +- [ ] Re-store Gitea PAT: + + ```bash + sudo -u ci-runner secret-tool store --label='GiteaPAT' service ci target GiteaPAT + ``` + +- [ ] Validare lettura interattiva: + + ```bash + sudo -u ci-runner /opt/ci/venv/bin/python -c \ + "import keyring; print(keyring.get_credential('BuildVMGuest', None))" + ``` + +- [ ] **PoC headless** (critico): verificare lettura keyring da + contesto systemd (no D-Bus user session): + + ```bash + sudo systemd-run --uid=ci-runner --pipe \ + /opt/ci/venv/bin/python -c \ + "import keyring; print(keyring.get_credential('BuildVMGuest', None))" + ``` + + Se fallisce → implementare backend keyring file-based con `age` o + `sops` come fallback. Documentare la scelta finale in + `docs/HOST-SETUP.md` prima di proseguire. + +--- + +## Passo 4 — Setup act_runner come systemd service (B4) + +**Obiettivo**: act_runner Linux registrato verso Gitea, gestito da +systemd. + +- [ ] Scaricare il binario act_runner Linux ≥ v1.0.2: + + ```bash + sudo mkdir -p /opt/ci/act_runner + sudo wget -O /opt/ci/act_runner/act_runner \ + https://gitea.com/gitea/act_runner/releases/download/v1.0.2/act_runner-1.0.2-linux-amd64 + sudo chmod +x /opt/ci/act_runner/act_runner + sudo chown -R ci-runner:ci-runner /opt/ci/act_runner + ``` + +- [ ] Generare token registrazione su Gitea (Admin → Runners → Create new runner). +- [ ] Registrare il runner (sostituire ``): + + ```bash + sudo -u ci-runner mkdir -p /var/lib/ci/runner + cd /var/lib/ci/runner + sudo -u ci-runner /opt/ci/act_runner/act_runner register \ + --no-interactive \ + --instance https://gitea.emulab.it \ + --token \ + --name ci-linux \ + --labels windows-build:host,linux-build:host + ``` + + > ⚠️ Lasciare il runner in stato **paused** lato Gitea UI fino al + > cutover (Passo 6), per non intercettare job di produzione. + +- [ ] Creare `/etc/systemd/system/act-runner.service`: + + ```ini + [Unit] + Description=Gitea Act Runner + After=network-online.target + Wants=network-online.target + + [Service] + Type=simple + User=ci-runner + WorkingDirectory=/var/lib/ci/runner + Environment="PYTHONIOENCODING=utf-8" + Environment="CI_ROOT=/var/lib/ci" + Environment="CI_TEMPLATES=/var/lib/ci/templates" + Environment="CI_BUILD_VMS=/var/lib/ci/build-vms" + Environment="CI_ARTIFACTS=/var/lib/ci/artifacts" + Environment="CI_KEYS=/etc/ci/keys" + ExecStart=/opt/ci/act_runner/act_runner daemon + Restart=on-failure + RestartSec=10 + + [Install] + WantedBy=multi-user.target + ``` + +- [ ] Creare `/etc/ci/environment` (letto dalle unit dei task periodici + di B5; vedi `deploy/systemd/README.md`): + + ```bash + sudo tee /etc/ci/environment <<'EOF' + PYTHONIOENCODING=utf-8 + CI_ROOT=/var/lib/ci + CI_TEMPLATES=/var/lib/ci/templates + CI_BUILD_VMS=/var/lib/ci/build-vms + CI_ARTIFACTS=/var/lib/ci/artifacts + CI_KEYS=/etc/ci/keys + EOF + sudo chmod 644 /etc/ci/environment + ``` + +- [ ] Abilitare e avviare: + + ```bash + sudo systemctl daemon-reload + sudo systemctl enable --now act-runner.service + sudo systemctl status act-runner + sudo journalctl -u act-runner -f # Ctrl+C dopo conferma OK + ``` + +- [ ] Smoke job: triggerare manualmente `self-test.yml` selezionando + il runner Linux (mettere temporaneamente in pausa quello Windows + o usare label distinte). Atteso: PASS. + +--- + +## Passo 5 — Installare i timer systemd (B5) + +**Obiettivo**: attivare le coppie `.service`+`.timer` già committate +in `deploy/systemd/` per replicare i task periodici di +`Register-CIScheduledTasks.ps1`. + +- [ ] Copiare le unit: + + ```bash + cd /opt/ci/local-ci-cd-system + sudo cp deploy/systemd/ci-*.service deploy/systemd/ci-*.timer /etc/systemd/system/ + sudo systemctl daemon-reload + ``` + +- [ ] Abilitare e avviare tutti i timer: + + ```bash + for t in ci-cleanup-orphans ci-retention-policy \ + ci-watch-disk-space ci-watch-runner-health \ + ci-backup-template; do + sudo systemctl enable --now "${t}.timer" + done + ``` + +- [ ] Verificare lo schedule: + + ```bash + systemctl list-timers --all 'ci-*' + ``` + + Atteso: 5 timer in stato `active`. + +- [ ] Trigger manuale di ciascun service per validare l'esecuzione + one-shot: + + ```bash + for s in ci-cleanup-orphans ci-watch-disk-space ci-watch-runner-health; do + sudo systemctl start "${s}.service" + sudo systemctl status "${s}.service" --no-pager + done + ``` + + > `ci-retention-policy` e `ci-backup-template` chiamano `pwsh`: + > eseguirli solo dopo aver verificato che `pwsh --version` funzioni + > sotto user `ci-runner`. + +- [ ] Per maggiori dettagli (mapping Windows→Linux, troubleshooting, + rollback) vedi `deploy/systemd/README.md`. + +--- + +## Passo 6 — Cutover (B6) + +**Obiettivo**: spostare la produzione dall'host Windows a Linux in una +finestra di manutenzione concordata. + +> ⚠️ Eseguire solo dopo che i Passi 1–5 sono tutti `[x]` PASS. + +- [ ] Annunciare la finestra di manutenzione (durata stimata: 30–60 min). +- [ ] Verificare nessun job in coda lato Gitea (Admin → Actions → Tasks). +- [ ] **Stop** act_runner sull'host Windows: + + ```powershell + Stop-Service actions-runner + Get-Service actions-runner # atteso: Stopped + ``` + +- [ ] **Disabilitare** scheduled task Windows: + + ```powershell + Get-ScheduledTask -TaskName 'CI-*' | Unregister-ScheduledTask -Confirm:$false + ``` + +- [ ] Rsync incrementale finale degli artifact: + + ```bash + sudo -u ci-runner rsync -av --delete \ + user@windows-host:/cygdrive/f/CI/Artifacts/ \ + /var/lib/ci/artifacts/ + ``` + +- [ ] Sbloccare il runner Linux su Gitea UI (rimuovere `paused` o + ripristinare le label di produzione `windows-build:host,linux-build:host`). +- [ ] Verificare runner Linux online su Gitea UI. +- [ ] Smoke trigger: + - [ ] `self-test.yml` → PASS dal runner Linux + - [ ] `build-nsInnoUnp.yml` matrix Win+Linux → PASS dal runner Linux +- [ ] Monitorare per ≥30 min: + + ```bash + sudo journalctl -u act-runner -f --since "30min ago" + ``` + + Nessun errore di severità critica atteso. + +> **Rollback (entro 30 min se PASS critico fallisce)**: +> 1. `sudo systemctl stop act-runner` su Linux +> 2. `Start-Service actions-runner` su Windows +> 3. Re-registrare scheduled task con `scripts\Register-CIScheduledTasks.ps1` +> 4. Documentare incidente in `TODO.md` e tornare a B1–B5 per fix + +--- + +## Passo 7 — Capacity burn-in (B7) + +**Obiettivo**: validare il carico target con tempi paragonabili al +baseline Windows (entro ±20%). + +- [ ] Burn-in 4 job concorrenti × 10 round su `WinBuild2025` + (lo script `Test-CapacityBurnIn.ps1` ora delega via shim alla CLI + Python `job` e gira anche da `pwsh` su Linux): + + ```bash + pwsh /opt/ci/local-ci-cd-system/scripts/Test-CapacityBurnIn.ps1 \ + -Concurrency 4 -Rounds 10 -Template /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx + ``` + +- [ ] Burn-in 4 × 10 su `LinuxBuild2404` (analogo, `--Template` + sul VMX Linux). +- [ ] Misurare: + - [ ] Tempo medio per job, confronto con baseline A5 + - [ ] Tutti i 80 job (2 × 4 × 10) PASS + - [ ] Zero VM orfane in `/var/lib/ci/build-vms/`: + + ```bash + sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator vm cleanup --dry-run + ``` + + - [ ] Spazio disco `/var/lib/ci/build-vms/` torna al baseline post-cleanup +- [ ] Documentare i risultati in `docs/RUNBOOK.md` (sezione "Linux + host baseline"). +- [ ] Se delta > 20% vs baseline Windows: aprire issue in `TODO.md` + con dettagli per profiling (probabile candidato: filesystem ext4 + vs NTFS — valutare XFS/BTRFS). + +--- + +## Passo 8 — Stabilità ≥1 settimana (gate per B8) + +**Obiettivo**: verificare ≥1 settimana di esercizio Linux senza +incidenti critici prima di dismettere l'host Windows. + +- [ ] Esercizio normale per ≥7 giorni con runner Linux primario. +- [ ] Verifica giornaliera (bastano 2 minuti): + + ```bash + sudo systemctl --failed # nessun service in failed + systemctl list-timers --all 'ci-*' # tutti gli ultimi run OK + sudo journalctl -u act-runner --since "24h ago" -p err + ``` + +- [ ] Nessun rollback effettuato durante la settimana. + +--- + +## Passo 9 — Decommissioning host Windows (B8, opzionale) + +> ⚠️ Procedere solo dopo Passo 8 `[x]`. L'host Windows va lasciato +> spento ma intatto per ≥1 mese come rollback. + +- [ ] Backup finale di `F:\CI\` su archivio esterno: + + ```powershell + $stamp = Get-Date -Format 'yyyyMMdd' + $archive = "E:\Backup\CI-$stamp.tar" + & 'C:\Program Files\Git\usr\bin\tar.exe' -cf $archive 'F:\CI\' + Get-FileHash $archive -Algorithm SHA256 | Tee-Object "$archive.sha256" + ``` + +- [ ] Verifica integrità (estrazione di prova in tmp): + + ```powershell + $test = "$env:TEMP\ci-restore-test" + & 'C:\Program Files\Git\usr\bin\tar.exe' -tf $archive | Select-Object -First 20 + ``` + +- [ ] Spegnere host Windows (`shutdown /s /t 0`). +- [ ] Lasciare hardware integro e spento per ≥1 mese. +- [ ] Aggiornare `docs/RUNBOOK.md` con la procedura di riaccensione + + ri-registrazione scheduled task come rollback. +- [ ] Dopo 1 mese senza rollback: riallocare hardware. + +--- + +## Tracciamento globale + +| Passo | Step | Descrizione | Stato | +| ----- | ---- | -------------------------------------------------- | ----- | +| 1 | B1 | Setup host Linux Mint (OS, Workstation, venv, ACL) | [ ] | +| 2 | B2 | Trasferimento template VM + smoke `vm new` | [ ] | +| 3 | B3 | Chiavi SSH + keyring (PoC headless) | [ ] | +| 4 | B4 | act_runner systemd service registrato | [ ] | +| 5 | B5 | Timer systemd installati e attivi | [ ] | +| 6 | B6 | Cutover (stop Windows, runner Linux primario) | [ ] | +| 7 | B7 | Capacity burn-in 4 × 10 (Win + Linux) | [ ] | +| 8 | — | ≥1 settimana di stabilità senza rollback | [ ] | +| 9 | B8 | Decommissioning host Windows (opzionale) | [ ] | + +Quando tutti i passi sono `[x]`, la **Fase B è chiusa** e si può +valutare l'apertura della Fase C (backend ESXi, vedi +`plans/idea-3-esxi-support.md`).