feat(b6): add Phase B user checklist for CI migration to Linux Mint
This commit is contained in:
@@ -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 `<TOKEN>`):
|
||||
|
||||
```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 <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`).
|
||||
Reference in New Issue
Block a user