chore(plans): archive completed Phase B docs
Phase B is closed (checklist Passi 1–9 [x], benchmark matrix §6–§14 recorded). Move the two finished working docs into the dated archive: plans/PhaseB-user-checklist.md → plans/archived/2026-06-07/ plans/benchmark-windows-host.md → plans/archived/2026-06-07/ plans/ now holds only the forward-looking plans (idea-3 Phase C pwsh removal, idea-4 Phase D ESXi, ideas-overview). Fixed the live links that pointed at the moved/relocated files: idea-3 §4, idea-2 §8 (relative path), and ideas-overview (idea-1/idea-2 now under archived/, Phase A+B marked ✅). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,602 @@
|
||||
# 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-and-linux-migration` (commit `50d37b5`).
|
||||
> Tutti gli altri step (B1–B4, B6–B8) sono **operazioni hardware**
|
||||
> sull'host Linux nuovo e devono essere eseguiti dall'utente.
|
||||
>
|
||||
> **Avanzamento**: B1 ✅ B2 ✅ B3 ✅ B4 ✅ — in corso: **B5** (timer systemd).
|
||||
|
||||
> **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.
|
||||
|
||||
- [x] Installare Linux Mint LTS sull'hardware target.
|
||||
- [x] `sudo apt update && sudo apt full-upgrade -y && sudo reboot`
|
||||
- [x] 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
|
||||
```
|
||||
|
||||
- [x] Smoke test Workstation (UI): creare VM trivia, clone, start,
|
||||
stop, delete.
|
||||
- [x] Configurare `vmnet8` NAT range `192.168.79.0/24` (allineato a
|
||||
Windows) editando `/etc/vmware/vmnet8/dhcpd/dhcpd.conf` o via
|
||||
`vmware-netcfg`.
|
||||
- [x] Creare utente di servizio `ci-runner`:
|
||||
|
||||
```bash
|
||||
sudo useradd -r -m -s /bin/bash ci-runner
|
||||
```
|
||||
|
||||
- [x] Eseguire `setup-host-linux.sh` (copre mount disco, layout, Python venv,
|
||||
clone repo, PowerShell Core):
|
||||
|
||||
```bash
|
||||
# Clonare il repo prima di eseguire lo script
|
||||
git clone https://gitea.emulab.it/Simone/local-ci-cd-system.git /tmp/local-ci-cd-system
|
||||
|
||||
sudo bash /tmp/local-ci-cd-system/setup-host-linux.sh -d /dev/sdf1
|
||||
```
|
||||
|
||||
Lo script:
|
||||
- Monta `/dev/sdf1` su `/var/lib/ci` via fstab (boot automatico).
|
||||
Se la partizione ha una sottocartella `ci/`, ne sposta i contenuti
|
||||
alla root della partizione prima del mount definitivo.
|
||||
- Crea il layout `build-vms/`, `artifacts/`, `templates/`, `keys/`,
|
||||
`logs/`, `runner/` con permessi e ACL corretti.
|
||||
- Installa Python 3.11, crea `/opt/ci/venv`, clona il repo in
|
||||
`/opt/ci/local-ci-cd-system` e installa il package.
|
||||
- Installa PowerShell Core.
|
||||
|
||||
Flag utili se alcune dipendenze sono già presenti:
|
||||
```bash
|
||||
sudo bash setup-host-linux.sh -d /dev/sdf1 --skip-pwsh --skip-clone
|
||||
```
|
||||
|
||||
Atteso a fine script: `ci_orchestrator --help` lista gli 11 sub-comandi.
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
|
||||
- [x] Sull'host Windows:
|
||||
|
||||
```powershell
|
||||
Get-ChildItem 'F:\CI\Templates' -Recurse -Include *.vmem,*.vmsn
|
||||
# atteso: nessun risultato
|
||||
```
|
||||
|
||||
- [x] 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/
|
||||
```
|
||||
|
||||
- [x] 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`.
|
||||
|
||||
- [x] Aprire ciascun `.vmx` su Workstation Linux per registrarli;
|
||||
al prompt rispondere "**I copied it**".
|
||||
- [x] **Prerequisito smoke test Windows**: il keyring file-based deve essere
|
||||
configurato e la credenziale `BuildVMGuest` deve essere presente
|
||||
**prima** di eseguire `wait-ready` (che prova WinRM). Questo è
|
||||
formalmente il Passo 3 (B3), ma il minimo indispensabile per lo
|
||||
smoke test è:
|
||||
|
||||
```bash
|
||||
# Configurare il backend file keyring per ci-runner (una sola volta)
|
||||
sudo -u ci-runner mkdir -p ~/.local/share/python_keyring
|
||||
sudo -u ci-runner bash -c "cat > ~/.local/share/python_keyring/keyringrc.cfg << 'EOF'
|
||||
[backend]
|
||||
default-keyring=keyrings.alt.file.PlaintextKeyring
|
||||
EOF"
|
||||
sudo -u ci-runner /opt/ci/venv/bin/pip install keyrings.alt -q
|
||||
|
||||
# Salvare la credenziale guest Windows
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python /opt/ci/local-ci-cd-system/tools/ci-cred-set.py BuildVMGuest "WINBUILD-2025\\ci_build"
|
||||
|
||||
# Verificare
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python /opt/ci/local-ci-cd-system/tools/ci-cred-check.py BuildVMGuest
|
||||
# atteso: OK (file) username='WINBUILD-2025\ci_build' password=****
|
||||
```
|
||||
|
||||
> Il setup completo delle credenziali (chiavi SSH, GiteaPAT,
|
||||
> PoC headless systemd) è nel Passo 3.
|
||||
|
||||
- [x] Smoke test pipeline VM:
|
||||
|
||||
```bash
|
||||
# Windows smoke
|
||||
CLONE_VMX=$(sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator vm new \
|
||||
--template /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx \
|
||||
--snapshot BaseClean \
|
||||
--clone-base-dir /var/lib/ci/build-vms \
|
||||
--job-id smoke-b2-win \
|
||||
--start)
|
||||
echo "Clone VMX: $CLONE_VMX"
|
||||
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator wait-ready \
|
||||
--vmx "$CLONE_VMX" --guest-os windows --timeout 300
|
||||
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator vm remove \
|
||||
--vmx "$CLONE_VMX" --force
|
||||
```
|
||||
|
||||
Ripetere per `LinuxBuild2404` (snapshot `BaseClean-Linux`,
|
||||
`--guest-os linux`, `--job-id smoke-b2-linux`).
|
||||
|
||||
---
|
||||
|
||||
## Passo 3 — Trasferimento credenziali e chiavi (B3)
|
||||
|
||||
**Obiettivo**: chiavi SSH e credenziali guest disponibili al user
|
||||
`ci-runner` headless.
|
||||
|
||||
- [x] Chiavi SSH guest Linux già presenti in `/var/lib/ci/keys/` (copiate
|
||||
insieme ai template). Correggere solo i permessi:
|
||||
|
||||
```bash
|
||||
sudo chown ci-runner:ci-runner /var/lib/ci/keys/ci_linux /var/lib/ci/keys/ci_linux.pub
|
||||
sudo chmod 600 /var/lib/ci/keys/ci_linux
|
||||
sudo chmod 644 /var/lib/ci/keys/ci_linux.pub
|
||||
# verifica
|
||||
ls -la /var/lib/ci/keys/
|
||||
```
|
||||
|
||||
- [x] Credenziale guest Windows `BuildVMGuest` già salvata nel
|
||||
prerequisito del Passo 2 con `keyrings.alt.file.PlaintextKeyring`
|
||||
(schema a due entry — `secret-tool` scartato perché non funziona
|
||||
headless senza D-Bus session).
|
||||
|
||||
Per riscrivere la credenziale se necessario:
|
||||
|
||||
```bash
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python /opt/ci/local-ci-cd-system/tools/ci-cred-set.py BuildVMGuest "WINBUILD-2025\\ci_build"
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python /opt/ci/local-ci-cd-system/tools/ci-cred-check.py BuildVMGuest
|
||||
```
|
||||
|
||||
- [x] Re-store Gitea PAT con lo stesso schema:
|
||||
|
||||
```bash
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python /opt/ci/local-ci-cd-system/tools/ci-cred-set.py GiteaPAT ci-runner-linux
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python /opt/ci/local-ci-cd-system/tools/ci-cred-check.py GiteaPAT
|
||||
```
|
||||
|
||||
- [x] **PoC headless**: il backend `PlaintextKeyring` non usa D-Bus —
|
||||
funziona già da `sudo -u ci-runner` e funzionerà da
|
||||
`act-runner.service`. Verificato durante smoke test Passo 2.
|
||||
|
||||
---
|
||||
|
||||
## Passo 4 — Setup act_runner come systemd service (B4)
|
||||
|
||||
**Obiettivo**: act_runner Linux registrato verso Gitea, gestito da
|
||||
systemd.
|
||||
|
||||
- [x] Scaricare il binario act_runner Linux ≥ v1.0.4:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/ci/act_runner
|
||||
sudo wget -O /opt/ci/act_runner/act_runner \
|
||||
https://gitea.com/gitea/runner/releases/download/v1.0.4/gitea-runner-1.0.4-linux-amd64
|
||||
sudo chmod +x /opt/ci/act_runner/act_runner
|
||||
sudo chown -R ci-runner:ci-runner /opt/ci/act_runner
|
||||
```
|
||||
|
||||
- [x] Generare token registrazione su Gitea (Admin → Runners → Create new runner).
|
||||
- [x] 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.
|
||||
|
||||
- [x] 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 --config /var/lib/ci/runner/config.yaml
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
- [x] 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
|
||||
```
|
||||
|
||||
- [x] 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
|
||||
```
|
||||
|
||||
- [x] Generare e configurare `config.yaml` del runner:
|
||||
|
||||
```bash
|
||||
# 1. Generare il file di default (conserva la registrazione in .runner)
|
||||
sudo -u ci-runner /opt/ci/act_runner/act_runner generate-config \
|
||||
| sudo -u ci-runner tee /var/lib/ci/runner/config.yaml > /dev/null
|
||||
|
||||
# 2. Sostituire i label Docker generati di default con quelli host corretti
|
||||
# (generate-config scrive label ubuntu-*:docker:// che fanno cercare Docker)
|
||||
sudo -u ci-runner sed -i \
|
||||
-e 's| - "ubuntu-latest:docker://.*"| - "windows-build:host"|' \
|
||||
-e '/ubuntu-24.04:docker:\/\//d' \
|
||||
-e '/ubuntu-22.04:docker:\/\//d' \
|
||||
/var/lib/ci/runner/config.yaml
|
||||
sudo -u ci-runner sed -i \
|
||||
'/ - "windows-build:host"/a\ - "linux-build:host"' \
|
||||
/var/lib/ci/runner/config.yaml
|
||||
|
||||
# 3. Sostituire le variabili di esempio nella sezione runner.envs con le variabili CI
|
||||
# (generate-config scrive due righe A_TEST_ENV_NAME_* come placeholder)
|
||||
sudo -u ci-runner sed -i \
|
||||
-e 's/ A_TEST_ENV_NAME_1: a_test_env_value_1/ CI_PYTHON_LAUNCHER: \/opt\/ci\/venv\/bin\/python/' \
|
||||
-e 's/ A_TEST_ENV_NAME_2: a_test_env_value_2/ GITEA_CI_TEMPLATE_PATH: \/var\/lib\/ci\/templates\/WinBuild2025\/WinBuild2025.vmx\n GITEA_CI_LINUX_TEMPLATE_PATH: \/var\/lib\/ci\/templates\/LinuxBuild2404\/LinuxBuild2404.vmx/' \
|
||||
/var/lib/ci/runner/config.yaml
|
||||
|
||||
# 4. Verificare
|
||||
grep -A3 'labels:' /var/lib/ci/runner/config.yaml | head -5
|
||||
grep -A4 'envs:' /var/lib/ci/runner/config.yaml
|
||||
```
|
||||
|
||||
Atteso:
|
||||
```yaml
|
||||
labels:
|
||||
- "windows-build:host"
|
||||
- "linux-build:host"
|
||||
envs:
|
||||
CI_PYTHON_LAUNCHER: /opt/ci/venv/bin/python
|
||||
GITEA_CI_TEMPLATE_PATH: /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx
|
||||
GITEA_CI_LINUX_TEMPLATE_PATH: /var/lib/ci/templates/LinuxBuild2404/LinuxBuild2404.vmx
|
||||
```
|
||||
|
||||
> Le variabili di sistema (`CI_ROOT`, `PYTHONIOENCODING`, ecc.) restano
|
||||
> nel service unit. `runner.envs` è per la configurazione specifica
|
||||
> del runner CI (path template, launcher Python).
|
||||
|
||||
```bash
|
||||
# 5. Ricaricare e riavviare
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart act-runner.service
|
||||
sudo journalctl -u act-runner -n 20 # confermare avvio OK — nessun errore Docker
|
||||
```
|
||||
|
||||
- [x] Smoke job: triggerare manualmente `self-test.yml` selezionando
|
||||
il runner Linux (mettere temporaneamente in pausa quello Windows
|
||||
o usare label distinte). Atteso: PASS.
|
||||
|
||||
> ⚠️ Prerequisito: le variabili `GITEA_CI_TEMPLATE_PATH` e
|
||||
> `GITEA_CI_LINUX_TEMPLATE_PATH` devono essere presenti nel service
|
||||
> unit **prima** di avviare lo smoke test, altrimenti il job fallisce
|
||||
> con "Got unexpected extra argument".
|
||||
|
||||
---
|
||||
|
||||
## 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`.
|
||||
|
||||
> **Nota**: `ci-retention-policy` e `ci-backup-template` sono stati portati
|
||||
> in Python puro (`retention run` / `template backup`) — **pwsh non è
|
||||
> richiesto**. I backup template vengono compressi con `7z -mx=1` in
|
||||
> `/var/lib/ci/backups/`. `ci-watch-runner-health` usa `--service-name
|
||||
> act-runner` (nome Linux, non Windows).
|
||||
|
||||
> **Prerequisiti creati sull'host**:
|
||||
> ```bash
|
||||
> sudo mkdir -p /var/log/ci /var/lib/ci/backups
|
||||
> sudo chown ci-runner:ci-runner /var/log/ci
|
||||
> ```
|
||||
|
||||
- [x] 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
|
||||
```
|
||||
|
||||
- [x] 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
|
||||
```
|
||||
|
||||
- [x] Verificare lo schedule:
|
||||
|
||||
```bash
|
||||
systemctl list-timers --all 'ci-*'
|
||||
```
|
||||
|
||||
Atteso: 5 timer in stato `active`. ✅ PASS
|
||||
|
||||
- [x] Trigger manuale di ciascun service per validare l'esecuzione
|
||||
one-shot:
|
||||
|
||||
```bash
|
||||
for s in ci-cleanup-orphans ci-retention-policy \
|
||||
ci-watch-disk-space ci-watch-runner-health \
|
||||
ci-backup-template; do
|
||||
sudo systemctl start "${s}.service"
|
||||
sudo systemctl status "${s}.service" --no-pager
|
||||
done
|
||||
```
|
||||
|
||||
✅ Tutti e 5 PASS.
|
||||
|
||||
- [x] Per maggiori dettagli (mapping Windows→Linux, troubleshooting,
|
||||
rollback) vedi `deploy/systemd/README.md`.
|
||||
|
||||
---
|
||||
|
||||
## Passo 6 — Cutover (B6)
|
||||
|
||||
**Obiettivo**: passare all'uso normale di Linux come OS primario di
|
||||
produzione CI. Il cutover è un semplice riavvio — i due sistemi non
|
||||
coesistono mai.
|
||||
|
||||
> ⚠️ Eseguire solo dopo che i Passi 1–5 sono tutti `[x]` PASS.
|
||||
|
||||
- [x] Verificare nessun job in coda lato Gitea (Admin → Actions → Tasks).
|
||||
- [x] Attendere la fine di eventuali job in esecuzione su Windows.
|
||||
- [x] Sbloccare il runner Linux su Gitea UI (rimuovere `paused`).
|
||||
- [x] Riavviare la macchina in Linux.
|
||||
- [x] Verificare runner Linux online su Gitea UI e act-runner attivo:
|
||||
|
||||
```bash
|
||||
sudo systemctl status act-runner
|
||||
sudo journalctl -u act-runner -n 20
|
||||
```
|
||||
|
||||
- [x] Smoke trigger:
|
||||
- [x] `self-test.yml` → PASS dal runner Linux
|
||||
- [x] `build-ns7zip.yml` matrix Win+Linux → PASS dal runner Linux
|
||||
- [x] Monitorare per ≥30 min:
|
||||
|
||||
```bash
|
||||
sudo journalctl -u act-runner -f
|
||||
```
|
||||
|
||||
> **Rollback**: riavviare in Windows — il runner Windows riprende
|
||||
> automaticamente. Mettere in pausa il runner Linux su Gitea UI,
|
||||
> documentare l'incidente in `TODO.md`.
|
||||
|
||||
---
|
||||
|
||||
## Passo 7 — Capacity burn-in (B7)
|
||||
|
||||
**Obiettivo**: validare il carico target con tempi paragonabili al
|
||||
baseline Windows (entro ±20%). I due burn-in sono sequenziali
|
||||
(dual-boot: un OS alla volta).
|
||||
|
||||
> **Eseguire come `ci-runner`** (utente di produzione — ha già accesso
|
||||
> a `/var/lib/ci/`, keyring e ip-pool; evita i perm-hack del path `simone`).
|
||||
> Verificato 2026-06-07.
|
||||
>
|
||||
> **Prerequisiti una-tantum**:
|
||||
> - Repo `burnin-dummy` esistente in Gitea (`Simone/burnin-dummy`,
|
||||
> privato — l'auth del clone in-VM usa il PAT da keyring `GiteaPAT`).
|
||||
> Deve contenere `build.ps1` + `build.sh`. Push iniziale:
|
||||
> ```bash
|
||||
> cd /opt/ci/local-ci-cd-system/gitea/burnin-dummy
|
||||
> git init && git add . && git commit -m "initial"
|
||||
> git remote add origin http://10.10.20.11:3100/Simone/burnin-dummy.git
|
||||
> git push -u origin main
|
||||
> ```
|
||||
> - **ip-pool pulito** prima di ogni burn-in: un run precedente killato
|
||||
> può lasciare lease stale (il pool NON si auto-riconcilia, vedi
|
||||
> RUNBOOK §9). Con `build-vms/` vuoto, resettare:
|
||||
> ```bash
|
||||
> sudo -u ci-runner /opt/ci/venv/bin/python -c \
|
||||
> "import pathlib; pathlib.Path('/var/lib/ci/ip-pool.json').write_text('{}\n')"
|
||||
> ```
|
||||
>
|
||||
> **(Path alternativo `simone`)**: se proprio si vuole girare come `simone`,
|
||||
> oltre a group `ci-runner` + copia keyring serve anche
|
||||
> `sudo chmod g+w /var/lib/ci` (la **root**, non solo
|
||||
> `artifacts/`+`build-vms/` — `ip-pool.tmp` è scritto lì). Sconsigliato.
|
||||
|
||||
- [x] **Avviato in Linux** — burn-in 4 job concorrenti × 10 round su
|
||||
`WinBuild2025` (esito: 40/40 PASS, round ~78.6 s):
|
||||
|
||||
```bash
|
||||
sudo -u ci-runner -H pwsh /opt/ci/local-ci-cd-system/scripts/Test-CapacityBurnIn.ps1 \
|
||||
-Parallelism 4 -Rounds 10 \
|
||||
-TemplatePath /var/lib/ci/templates/WinBuild2025/WinBuild2025.vmx \
|
||||
-RepoUrl 'http://10.10.20.11:3100/Simone/burnin-dummy.git' \
|
||||
-CloneBaseDir /var/lib/ci/build-vms/ \
|
||||
-ArtifactBaseDir /var/lib/ci/artifacts/ \
|
||||
-VmrunPath /usr/bin/vmrun \
|
||||
-BuildCommand 'powershell -ExecutionPolicy Bypass -File .\build.ps1'
|
||||
```
|
||||
|
||||
- [x] **Avviato in Linux** — burn-in 4 × 10 su `LinuxBuild2404` (esito:
|
||||
40/40 PASS, round ~70.2 s):
|
||||
|
||||
```bash
|
||||
sudo -u ci-runner -H pwsh /opt/ci/local-ci-cd-system/scripts/Test-CapacityBurnIn.ps1 \
|
||||
-Parallelism 4 -Rounds 10 \
|
||||
-TemplatePath /var/lib/ci/templates/LinuxBuild2404/LinuxBuild2404.vmx \
|
||||
-SnapshotName BaseClean-Linux \
|
||||
-RepoUrl 'http://10.10.20.11:3100/Simone/burnin-dummy.git' \
|
||||
-CloneBaseDir /var/lib/ci/build-vms/ \
|
||||
-ArtifactBaseDir /var/lib/ci/artifacts/ \
|
||||
-VmrunPath /usr/bin/vmrun \
|
||||
-GuestOS Linux \
|
||||
-BuildCommand 'bash build.sh'
|
||||
```
|
||||
> **Nota**: `-SnapshotName BaseClean-Linux` è **obbligatorio** — il default
|
||||
> dello script è `BaseClean` (Windows); senza, fallisce con
|
||||
> `Error: Invalid snapshot name 'BaseClean'`.
|
||||
- [x] Misurare:
|
||||
- [x] Tempo medio per round, vs baseline §6–§8 — round near-deterministico
|
||||
(σ < 1.5 s), in linea con static-IP floor (RUNBOOK §9)
|
||||
- [x] Tutti i 80 job (2 × 4 × 10) PASS
|
||||
- [x] Zero VM orfane in `/var/lib/ci/build-vms/`:
|
||||
|
||||
```bash
|
||||
sudo -u ci-runner /opt/ci/venv/bin/python -m ci_orchestrator vm cleanup --what-if
|
||||
```
|
||||
|
||||
- [x] Spazio disco `/var/lib/ci/build-vms/` torna al baseline post-cleanup
|
||||
- [x] Documentare i risultati in `docs/RUNBOOK.md` (§9 — Concurrent
|
||||
capacity burn-in).
|
||||
- [ ] Se delta > 20% vs baseline Windows: aprire issue in `TODO.md`
|
||||
con dettagli per profiling — **N/A**: nessun delta, burn-in PASS.
|
||||
|
||||
---
|
||||
|
||||
## Passo 8 — Stabilità ≥1 settimana
|
||||
|
||||
**Obiettivo**: verificare ≥1 settimana di esercizio con la macchina
|
||||
avviata abitualmente in Linux senza incidenti critici.
|
||||
|
||||
> **Esito 2026-06-07**: host live dal cutover B6 (~24 mag) → >2 settimane
|
||||
> di esercizio. Salute al 7 giu: `systemctl --failed` vuoto, tutti i timer
|
||||
> `ci-*` con ultimo run OK, nessun errore reale in `act-runner` (solo
|
||||
> `NamedPipeIPC_ServerListenerError` cosmetici su exit dei processi pwsh).
|
||||
> Nessun rollback. Le sessioni del 6 giu sono state hardening template
|
||||
> Linux (no-IP/DHCP), non instabilità dell'host.
|
||||
|
||||
- [x] Esercizio normale per ≥7 giorni con boot in Linux.
|
||||
- [x] 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
|
||||
```
|
||||
|
||||
- [x] Nessun rollback effettuato durante la settimana.
|
||||
|
||||
---
|
||||
|
||||
## Passo 9 — Gestione dual-boot
|
||||
|
||||
> La macchina è **dual-boot**: Windows e Linux coesistono sullo stesso
|
||||
> hardware, non girano mai contemporaneamente. Non c'è dismissione —
|
||||
> Windows resta pienamente funzionale e si usa riavviando nel boot
|
||||
> entry corrispondente.
|
||||
|
||||
- [x] Aggiornare `docs/RUNBOOK.md` con la procedura dual-boot: vedi
|
||||
**RUNBOOK §15** (switch Linux⇄Windows, verifica post-boot per
|
||||
entrambi gli OS, tweak GRUB opzionale).
|
||||
- [x] (Facoltativo) GRUB verificato: `GRUB_DEFAULT=0`, `GRUB_TIMEOUT=0`,
|
||||
`GRUB_TIMEOUT_STYLE=hidden` → boot diretto in Linux (intenzionale:
|
||||
la macchina torna host Linux dopo ogni reboot unattended). Per
|
||||
switch a Windows: tasto Esc al boot, oppure `grub-reboot` con
|
||||
`GRUB_DEFAULT=saved`. Tweak documentato in RUNBOOK §15, **non
|
||||
applicato** (default Linux voluto).
|
||||
|
||||
```bash
|
||||
sudo nano /etc/default/grub # GRUB_DEFAULT, GRUB_TIMEOUT
|
||||
sudo update-grub
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tracciamento globale
|
||||
|
||||
| Passo | Step | Descrizione | Stato |
|
||||
| ----- | ---- | -------------------------------------------------- | ----- |
|
||||
| 1 | B1 | Setup host Linux Mint (OS, Workstation, venv, ACL) | [x] |
|
||||
| 2 | B2 | Trasferimento template VM + smoke `vm new` | [x] |
|
||||
| 3 | B3 | Chiavi SSH + keyring (PoC headless) | [x] |
|
||||
| 4 | B4 | act_runner systemd service + `self-test.yml` PASS | [x] |
|
||||
| 5 | B5 | Timer systemd installati e attivi | [x] |
|
||||
| 6 | B6 | Cutover (riavvio in Linux, runner Linux attivo) | [x] |
|
||||
| 7 | B7 | Capacity burn-in 4 × 10 (Win + Linux, sequenziale) | [x] |
|
||||
| 8 | — | ≥1 settimana di stabilità (boot Linux abituale) | [x] |
|
||||
| 9 | — | Gestione dual-boot + RUNBOOK aggiornato (§15) | [x] |
|
||||
|
||||
> **Architettura**: la macchina è **dual-boot** (stesso hardware).
|
||||
> Avviata in Linux → runner Linux attivo. Avviata in Windows → runner
|
||||
> Windows attivo. I due sistemi non girano mai contemporaneamente.
|
||||
|
||||
Quando i passi 1-8 sono `[x]`, la **Fase B è chiusa** (B8 annullato per
|
||||
vincolo) e si può valutare l'apertura della Fase C (eliminazione `pwsh`
|
||||
dall'host Linux, vedi `plans/idea-3-powershell-removal.md`). La Fase D
|
||||
(backend ESXi, `plans/idea-3-esxi-support.md`) viene dopo.
|
||||
@@ -0,0 +1,151 @@
|
||||
# Plan — Windows-host benchmarks (comparable to Linux-host §6–§10)
|
||||
|
||||
> **Scopo**: la macchina è dual-boot (Windows ⇄ Linux, stesso hardware).
|
||||
> Le baseline RUNBOOK §6–§10 sono quasi tutte sul **Linux host**. Questo
|
||||
> plan raccoglie i numeri mancanti sul **Windows host** per chiudere la
|
||||
> matrice host × guest × IP-mode e rendere il confronto Linux-vs-Windows
|
||||
> completo e simmetrico.
|
||||
>
|
||||
> **Prerequisito**: riavviare la macchina nel boot entry **Windows**.
|
||||
> Tutto gira su Windows PowerShell 5.1 o pwsh 7; usare la stessa
|
||||
> `Measure-CIBenchmark.ps1` / `Test-CapacityBurnIn.ps1` del repo (sono
|
||||
> cross-platform, i default path passano a `F:\CI\...` quando `$IsWindows`).
|
||||
|
||||
---
|
||||
|
||||
## 1. Cosa esiste già e cosa manca
|
||||
|
||||
| RUNBOOK § | Host | Guest | IP mode | Stato |
|
||||
| --------- | ----- | -------------- | --------------------- | ------------ |
|
||||
| §6 | Win | WinBuild2025 | DHCP | ✓ 2026-05-17 |
|
||||
| §7 | Linux | WinBuild2025 | DHCP | ✓ |
|
||||
| §8 | Linux | WinBuild2025 | static | ✓ |
|
||||
| §9 | Linux | Win + Linux | burn-in (static pool) | ✓ |
|
||||
| §10 | Linux | LinuxBuild2404 | DHCP | ✓ |
|
||||
|
||||
**Mancanti sul Windows host** (target di questo plan):
|
||||
|
||||
| Nuovo § | Host | Guest | IP mode | Pair-with |
|
||||
| ------- | ---- | -------------- | ------------ | --------- |
|
||||
| §11 | Win | WinBuild2025 | static | §8 |
|
||||
| §12 | Win | LinuxBuild2404 | DHCP | §10 |
|
||||
| §13 | Win | Win + Linux | burn-in 4×10 | §9 |
|
||||
|
||||
§6 copre già Win×Win×DHCP. Opzionale: ri-eseguirlo nella stessa sessione per
|
||||
coerenza (stesso disco/fragmentazione del momento).
|
||||
|
||||
---
|
||||
|
||||
## 2. Prerequisiti sul Windows host
|
||||
|
||||
- [x] Boot in Windows; verificare VMware Workstation + `vmrun.exe` in
|
||||
`C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe`.
|
||||
- [x] Template fully powered-off con snapshot integri:
|
||||
```powershell
|
||||
& 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' -T ws listSnapshots 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx'
|
||||
& 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' -T ws listSnapshots 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx'
|
||||
```
|
||||
Attesi: `BaseClean` e `BaseClean-Linux`. ✓ (anche `PostInstall` su Win)
|
||||
- [x] Credenziali in **Windows Credential Manager** (non keyring file):
|
||||
target `BuildVMGuest` (guest WinRM, user `ci_build`) e `GiteaPAT`
|
||||
(user `Simone`). Verificato.
|
||||
- [x] Chiave SSH guest Linux presente: `F:\CI\keys\ci_linux` (per §12/§13
|
||||
lato LinuxBuild2404).
|
||||
- [x] Gitea raggiungibile (`http://10.10.20.11:3100`, HTTP 200) e repo
|
||||
`Simone/burnin-dummy` con `build.ps1` + `build.sh` (verificato via API).
|
||||
- [x] `F:\CI\BuildVMs\` privo di cloni orfani e `F:\CI\ip-pool.json` assente
|
||||
(pulito). Reset se serve:
|
||||
```powershell
|
||||
Set-Content -Path 'F:\CI\ip-pool.json' -Value '{}' -NoNewline
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. §11 — WinBuild2025 static IP (pair §8)
|
||||
|
||||
```powershell
|
||||
.\scripts\Measure-CIBenchmark.ps1 `
|
||||
-TemplatePath 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' `
|
||||
-SnapshotName BaseClean `
|
||||
-StaticIP 192.168.79.200 -Netmask 255.255.255.0 `
|
||||
-Iterations 10
|
||||
```
|
||||
- [x] 10 iter completate, tabella per-fase stampata. **Boot total avg 29.75 s.**
|
||||
- [x] Confronto vs §8 (Linux host static): IP-floor confermato host-independent
|
||||
(22.81 s vs 21.77 s, +5 %). Penalità host: clone +58 % (NTFS), Ready +4.7 s
|
||||
(WinRM re-bind dopo NIC reconfig), destroy +82 % (bimodale), boot +24 %.
|
||||
Vedi RUNBOOK §11. **Nota**: primo tentativo fallito (timeout 300 s/iter) —
|
||||
template Windows privo dell'agent `ci-static-ip`; risolto copiando i
|
||||
template dal Linux host (parità template).
|
||||
|
||||
## 4. §12 — LinuxBuild2404 DHCP (pair §10)
|
||||
|
||||
```powershell
|
||||
.\scripts\Measure-CIBenchmark.ps1 `
|
||||
-TemplatePath 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' `
|
||||
-SnapshotName BaseClean-Linux `
|
||||
-GuestOS Linux `
|
||||
-Iterations 10
|
||||
```
|
||||
- [x] 10 iter completate. **Boot total avg 13.51 s.**
|
||||
- [x] Confronto vs §10 (Linux host, 8.82 s): **+53 %** host-side — clone +191 %
|
||||
(NTFS), IP-acquire +52 % (NAT vmnet8 Windows + guestinfo). Guest Linux resta
|
||||
deterministico (IP σ ≈ 0.05 s). Vedi RUNBOOK §12.
|
||||
|
||||
## 5. §13 — Concurrent burn-in 4×10 (pair §9)
|
||||
|
||||
```powershell
|
||||
# WinBuild2025
|
||||
.\scripts\Test-CapacityBurnIn.ps1 `
|
||||
-Parallelism 4 -Rounds 10 `
|
||||
-TemplatePath 'F:\CI\Templates\WinBuild2025\WinBuild2025.vmx' `
|
||||
-RepoUrl 'http://10.10.20.11:3100/Simone/burnin-dummy.git' `
|
||||
-CloneBaseDir 'F:\CI\BuildVMs\' `
|
||||
-ArtifactBaseDir 'F:\CI\Artifacts\' `
|
||||
-VmrunPath 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' `
|
||||
-BuildCommand 'powershell -ExecutionPolicy Bypass -File .\build.ps1'
|
||||
|
||||
# LinuxBuild2404 (snapshot OBBLIGATORIO, default è BaseClean=Windows)
|
||||
.\scripts\Test-CapacityBurnIn.ps1 `
|
||||
-Parallelism 4 -Rounds 10 `
|
||||
-TemplatePath 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' `
|
||||
-SnapshotName BaseClean-Linux `
|
||||
-RepoUrl 'http://10.10.20.11:3100/Simone/burnin-dummy.git' `
|
||||
-CloneBaseDir 'F:\CI\BuildVMs\' `
|
||||
-ArtifactBaseDir 'F:\CI\Artifacts\' `
|
||||
-VmrunPath 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe' `
|
||||
-GuestOS Linux `
|
||||
-BuildCommand 'bash build.sh'
|
||||
```
|
||||
- [~] **Linux 40/40 PASS (10/10 round). Windows 36/40 (7/10 round).** I 4 fail
|
||||
Windows = fault WinRM transitori (round 6–8: connect-timeout 5986 +
|
||||
WSManFault "shell not found") sotto 4× concorrenza; auto-recuperati (slot IP
|
||||
rilasciati, 0 cloni orfani, round 9–10 di nuovo puliti). Linux/SSH 0 fault.
|
||||
- [x] Round avg vs §9 (Win ~78.6 s, Lin ~70.2 s): Windows host Win ~91.6 s
|
||||
(round PASS) **+16 %** + instabilità WinRM; Lin 96.4 s **+37 %**.
|
||||
Vedi RUNBOOK §13. **Pre-req scoperti**: (1) parità template, (2) prod venv
|
||||
F:\CI\python\venv stale (pre-`ip_pool`) → reinstallato `pip install .`,
|
||||
(3) `CI_VENV_PYTHON` da settare (bug shim `$IsWindows` su PS 5.1+StrictMode).
|
||||
|
||||
---
|
||||
|
||||
## 6. Output e documentazione
|
||||
|
||||
- Tutti i run appendono a `F:\CI\Logs\benchmark.jsonl` (single-job) e
|
||||
stampano summary (burn-in).
|
||||
- [x] Risultati aggiunti a `docs/RUNBOOK.md` §11–§13 (+ §14 matrice completa),
|
||||
con confronto host Linux-vs-Windows per ciascuna coppia.
|
||||
- [x] Pulizia post-run: `F:\CI\BuildVMs\` vuoto, artifact `burnin-*`
|
||||
rimossi, `F:\CI\ip-pool.json` reset.
|
||||
|
||||
---
|
||||
|
||||
## 7. Matrice finale attesa (dopo questo plan)
|
||||
|
||||
| Host \ (Guest, mode) | Win/DHCP | Win/static | Lin/DHCP | burn-in 4×10 |
|
||||
| -------------------- | -------- | ---------- | -------- | ------------ |
|
||||
| **Linux** | §7 | §8 | §10 | §9 |
|
||||
| **Windows** | §6 | §11 | §12 | §13 |
|
||||
|
||||
Confronto colonna-per-colonna = **effetto host** a guest+mode costanti.
|
||||
Confronto riga-per-riga = **effetto guest/IP-mode** a host costante.
|
||||
Reference in New Issue
Block a user