feat: add setup-host-linux.sh script for CI host bootstrap and update Phase B checklist
This commit is contained in:
@@ -10,6 +10,7 @@ secrets/
|
||||
# Log e output temporanei
|
||||
logs/
|
||||
*.log
|
||||
*.swp
|
||||
|
||||
# Artifact di build (storti su F:\CI\Artifacts, non nel repo)
|
||||
artifacts/
|
||||
|
||||
Executable
+200
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env bash
|
||||
# fix-ci-storage-layout.sh — Normalizza il layout /var/lib/ci dopo migrazione da Windows
|
||||
#
|
||||
# Il disco conteneva già i dati CI con nomi Windows (BuildVMs, Templates, ecc.).
|
||||
# setup-host-linux.sh ha creato le versioni lowercase Linux (build-vms, templates, ecc.).
|
||||
# Questo script unisce i duplicati e rinomina le directory Windows-only.
|
||||
#
|
||||
# MODALITÀ DRY-RUN per default: mostra cosa farebbe senza toccare nulla.
|
||||
# Usa --apply per eseguire le modifiche.
|
||||
#
|
||||
# Uso:
|
||||
# sudo bash fix-ci-storage-layout.sh [--apply] [--root /var/lib/ci]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CI_ROOT="/var/lib/ci"
|
||||
DRY_RUN=true
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN} ✓${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW} !${NC} $*"; }
|
||||
plan() { echo -e "${CYAN} →${NC} $*"; }
|
||||
die() { echo -e "${RED}ERRORE: $*${NC}" >&2; exit 1; }
|
||||
|
||||
run() {
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
plan "[DRY-RUN] $*"
|
||||
else
|
||||
eval "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Parse args ────────────────────────────────────────────────────────────────
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--apply) DRY_RUN=false; shift ;;
|
||||
--root) CI_ROOT="$2"; shift 2 ;;
|
||||
*) echo "Uso: sudo bash $0 [--apply] [--root <path>]"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ $EUID -ne 0 ]] && die "Eseguire come root: sudo bash $0 ..."
|
||||
[[ ! -d "$CI_ROOT" ]] && die "$CI_ROOT non esiste"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════╗"
|
||||
echo "║ DRY-RUN — nessuna modifica verrà apportata ║"
|
||||
echo "║ Riesegui con --apply per applicare le fix ║"
|
||||
echo "╚══════════════════════════════════════════════════╝"
|
||||
else
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════╗"
|
||||
echo "║ APPLICAZIONE MODIFICHE ║"
|
||||
echo "╚══════════════════════════════════════════════════╝"
|
||||
fi
|
||||
echo " CI_ROOT: $CI_ROOT"
|
||||
echo ""
|
||||
|
||||
# ── Funzione merge: sposta contenuto di SRC in DST ───────────────────────────
|
||||
# Gestisce conflitti a livello top-level (non ricorsivo: i subdir ci/sono distinti)
|
||||
merge_into() {
|
||||
local src="$CI_ROOT/$1"
|
||||
local dst="$CI_ROOT/$2"
|
||||
local had_conflict=false
|
||||
|
||||
echo "── Merge: $1/ → $2/"
|
||||
if [[ ! -d "$src" ]]; then
|
||||
warn "$1/ non presente — skip"
|
||||
return
|
||||
fi
|
||||
|
||||
shopt -s dotglob nullglob
|
||||
local items=("$src"/*)
|
||||
shopt -u dotglob nullglob
|
||||
|
||||
if [[ ${#items[@]} -eq 0 ]]; then
|
||||
warn "$1/ è vuota — rimuovo solo la directory"
|
||||
run "rmdir '$src'"
|
||||
return
|
||||
fi
|
||||
|
||||
for item in "${items[@]}"; do
|
||||
local name
|
||||
name=$(basename "$item")
|
||||
if [[ -e "$dst/$name" ]]; then
|
||||
warn " CONFLITTO: $name già esiste in $2/ — skip (controlla manualmente)"
|
||||
had_conflict=true
|
||||
else
|
||||
run "mv '$item' '$dst/'"
|
||||
info " $1/$name → $2/$name"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$had_conflict" == false ]]; then
|
||||
run "rmdir '$src'"
|
||||
info " Rimossa: $1/ (vuota dopo merge)"
|
||||
else
|
||||
warn " $1/ NON rimossa: contiene ancora file in conflitto"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── Funzione rename: rinomina directory Windows-only ─────────────────────────
|
||||
rename_dir() {
|
||||
local src="$CI_ROOT/$1"
|
||||
local dst="$CI_ROOT/$2"
|
||||
|
||||
echo "── Rinomina: $1/ → $2/"
|
||||
if [[ ! -d "$src" ]]; then
|
||||
warn "$1/ non presente — skip"
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
if [[ -d "$dst" ]]; then
|
||||
warn "$2/ esiste già — usa merge invece di rename"
|
||||
merge_into "$1" "$2"
|
||||
return
|
||||
fi
|
||||
run "mv '$src' '$dst'"
|
||||
info "$1/ → $2/"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── Funzione remove: rimuove directory non necessaria su Linux ────────────────
|
||||
remove_dir() {
|
||||
local target="$CI_ROOT/$1"
|
||||
local reason="$2"
|
||||
|
||||
echo "── Rimuovi: $1/ ($reason)"
|
||||
if [[ ! -d "$target" ]]; then
|
||||
warn "$1/ non presente — skip"
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
local count
|
||||
count=$(find "$target" -mindepth 1 | wc -l)
|
||||
if [[ "$count" -gt 0 ]]; then
|
||||
warn "$1/ contiene $count file/dir — rimozione manuale consigliata"
|
||||
warn " Esegui: sudo rm -rf '$target'"
|
||||
else
|
||||
run "rmdir '$target'"
|
||||
info "Rimossa: $1/ (vuota)"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 1. MERGE: directory con doppio (Windows uppercase + Linux lowercase)
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
echo "━━━ FASE 1: Merge duplicati (Windows → Linux) ━━━"
|
||||
echo ""
|
||||
merge_into "Artifacts" "artifacts"
|
||||
merge_into "BuildVMs" "build-vms"
|
||||
merge_into "Logs" "logs"
|
||||
merge_into "Templates" "templates"
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 2. RINOMINA: directory Windows-only utili su Linux
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
echo "━━━ FASE 2: Rinomina directory Windows-only ━━━"
|
||||
echo ""
|
||||
rename_dir "ISO" "iso"
|
||||
rename_dir "Cache" "cache"
|
||||
rename_dir "State" "state" # stato orchestrator — potrebbe contenere dati utili
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 3. RIMUOVI: directory non necessarie su Linux
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
echo "━━━ FASE 3: Directory non necessarie su Linux ━━━"
|
||||
echo ""
|
||||
# RunnerWork: working dir di act_runner su Windows; su Linux è /var/lib/ci/runner/
|
||||
remove_dir "RunnerWork" "working dir act_runner Windows — su Linux è runner/"
|
||||
# python: venv Windows (F:\CI\python\venv); su Linux è /opt/ci/venv
|
||||
remove_dir "python" "venv Python Windows — su Linux è /opt/ci/venv"
|
||||
# act_runner: binario act_runner Windows; su Linux è /opt/ci/act_runner/
|
||||
remove_dir "act_runner" "binario act_runner Windows — su Linux è /opt/ci/act_runner/"
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# 4. RIEPILOGO
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
echo "━━━ Layout atteso dopo fix ━━━"
|
||||
echo ""
|
||||
echo " /var/lib/ci/"
|
||||
for d in build-vms artifacts templates keys logs runner iso cache state; do
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
[[ -d "$CI_ROOT/$d" ]] && echo " ├── $d/" || echo " ├── $d/ ← MANCANTE"
|
||||
else
|
||||
echo " ├── $d/"
|
||||
fi
|
||||
done
|
||||
echo " ├── config.toml"
|
||||
echo " └── lost+found (lasciato intatto)"
|
||||
echo ""
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
echo "Riesegui con --apply per applicare tutte le modifiche."
|
||||
else
|
||||
echo "Fix completato. Verifica con: sudo ls -la $CI_ROOT/"
|
||||
fi
|
||||
@@ -24,9 +24,9 @@ nuovo host **Linux Mint LTS** con VMware Workstation Pro Linux.
|
||||
**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
|
||||
- [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
|
||||
@@ -34,56 +34,43 @@ Pro Linux, layout storage e venv Python pronti.
|
||||
vmrun -T ws --version # deve ritornare versione coerente
|
||||
```
|
||||
|
||||
- [ ] Smoke test Workstation (UI): creare VM trivia, clone, start,
|
||||
- [x] Smoke test Workstation (UI): creare VM trivia, clone, start,
|
||||
stop, delete.
|
||||
- [ ] Configurare `vmnet8` NAT range `192.168.79.0/24` (allineato a
|
||||
- [x] 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`:
|
||||
- [x] Creare utente di servizio `ci-runner`:
|
||||
|
||||
```bash
|
||||
sudo useradd -r -m -s /bin/bash ci-runner
|
||||
```
|
||||
|
||||
- [ ] Creare layout storage:
|
||||
- [x] Eseguire `setup-host-linux.sh` (copre mount disco, layout, Python venv,
|
||||
clone repo, PowerShell Core):
|
||||
|
||||
```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
|
||||
# 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
|
||||
```
|
||||
|
||||
- [ ] Installare Python 3.11+ e creare venv produzione:
|
||||
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 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
|
||||
sudo bash setup-host-linux.sh -d /dev/sdf1 --skip-pwsh --skip-clone
|
||||
```
|
||||
|
||||
- [ ] 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
|
||||
```
|
||||
Atteso a fine script: `ci_orchestrator --help` lista gli 11 sub-comandi.
|
||||
|
||||
---
|
||||
|
||||
@@ -103,7 +90,7 @@ Pro Linux, layout storage e venv Python pronti.
|
||||
# atteso: nessun risultato
|
||||
```
|
||||
|
||||
- [ ] Sull'host Linux, eseguire rsync via SSH dall'host Windows
|
||||
- [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):
|
||||
|
||||
@@ -113,7 +100,7 @@ Pro Linux, layout storage e venv Python pronti.
|
||||
/var/lib/ci/templates/
|
||||
```
|
||||
|
||||
- [ ] Validare integrità snapshot:
|
||||
- [x] Validare integrità snapshot:
|
||||
|
||||
```bash
|
||||
find /var/lib/ci/templates -name '*.vmx' -exec vmrun -T ws listSnapshots {} \;
|
||||
@@ -122,7 +109,7 @@ Pro Linux, layout storage e venv Python pronti.
|
||||
Atteso: `BaseClean` su `WinBuild2025.vmx` e `WinBuild2022.vmx`,
|
||||
`BaseClean-Linux` su `LinuxBuild2404.vmx`.
|
||||
|
||||
- [ ] Aprire ciascun `.vmx` su Workstation Linux per registrarli;
|
||||
- [x] Aprire ciascun `.vmx` su Workstation Linux per registrarli;
|
||||
al prompt rispondere "**I copied it**".
|
||||
- [ ] Smoke test pipeline VM:
|
||||
|
||||
@@ -466,7 +453,7 @@ vedi Passo 9: host Windows mantenuto in permanenza.)
|
||||
|
||||
| Passo | Step | Descrizione | Stato |
|
||||
| ----- | ---- | -------------------------------------------------- | ----- |
|
||||
| 1 | B1 | Setup host Linux Mint (OS, Workstation, venv, ACL) | [ ] |
|
||||
| 1 | B1 | Setup host Linux Mint (OS, Workstation, venv, ACL) | [x] |
|
||||
| 2 | B2 | Trasferimento template VM + smoke `vm new` | [ ] |
|
||||
| 3 | B3 | Chiavi SSH + keyring (PoC headless) | [ ] |
|
||||
| 4 | B4 | act_runner systemd service registrato | [ ] |
|
||||
|
||||
Executable
+277
@@ -0,0 +1,277 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup-host-linux.sh — Bootstrap CI host Linux Mint (Fase B, Step B1)
|
||||
#
|
||||
# Equivalente di Setup-Host.ps1 per l'host Linux.
|
||||
# Eseguire come root: sudo bash setup-host-linux.sh -d /dev/sdf1 [opzioni]
|
||||
#
|
||||
# Cosa fa:
|
||||
# 1. Crea l'utente di servizio ci-runner
|
||||
# 2. Monta la partizione CI su /var/lib/ci via fstab (boot automatico)
|
||||
# Se la partizione ha già una sottocartella ci/, la riorganizza
|
||||
# portando i contenuti alla root della partizione (nessun dato perso)
|
||||
# 3. Crea il layout directory e permessi
|
||||
# 4. Installa Python 3.11+ e crea venv produzione in /opt/ci/venv
|
||||
# 5. (Opzionale) Installa PowerShell Core
|
||||
# 6. (Opzionale) Clona il repo e installa il package nel venv
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Defaults ─────────────────────────────────────────────────────────────────
|
||||
CI_DISK=""
|
||||
CI_ROOT="/var/lib/ci"
|
||||
CI_USER="ci-runner"
|
||||
OPT_CI="/opt/ci"
|
||||
REPO_URL="https://gitea.emulab.it/Simone/local-ci-cd-system.git"
|
||||
|
||||
SKIP_PYTHON=false
|
||||
SKIP_PWSH=false
|
||||
SKIP_CLONE=false
|
||||
|
||||
# ── Colori ───────────────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN}==>${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW} ! $*${NC}"; }
|
||||
die() { echo -e "${RED}ERROR: $*${NC}" >&2; exit 1; }
|
||||
|
||||
# ── Uso ──────────────────────────────────────────────────────────────────────
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Uso: sudo bash $(basename "$0") -d <disco> [opzioni]
|
||||
|
||||
Obbligatorio:
|
||||
-d <disco> Partizione CI (es. /dev/sdf1 o /dev/sdf)
|
||||
|
||||
Opzionali:
|
||||
-r <path> CI root (default: /var/lib/ci)
|
||||
-u <utente> Utente di servizio (default: ci-runner)
|
||||
--skip-python Salta installazione Python/venv
|
||||
--skip-pwsh Salta installazione PowerShell Core
|
||||
--skip-clone Salta clone repo + pip install
|
||||
|
||||
Esempi:
|
||||
sudo bash setup-host-linux.sh -d /dev/sdf1
|
||||
sudo bash setup-host-linux.sh -d /dev/sdf1 --skip-pwsh --skip-clone
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ── Parse args ───────────────────────────────────────────────────────────────
|
||||
[[ $# -eq 0 ]] && usage
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-d) CI_DISK="$2"; shift 2 ;;
|
||||
-r) CI_ROOT="$2"; shift 2 ;;
|
||||
-u) CI_USER="$2"; shift 2 ;;
|
||||
--skip-python) SKIP_PYTHON=true; shift ;;
|
||||
--skip-pwsh) SKIP_PWSH=true; shift ;;
|
||||
--skip-clone) SKIP_CLONE=true; shift ;;
|
||||
-h|--help) usage ;;
|
||||
*) die "Parametro sconosciuto: $1"; ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$CI_DISK" ]] && die "-d <disco> è obbligatorio"
|
||||
[[ $EUID -ne 0 ]] && die "Eseguire come root: sudo bash $0 ..."
|
||||
[[ ! -b "$CI_DISK" ]] && die "$CI_DISK non è un block device"
|
||||
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════╗"
|
||||
echo "║ CI Host Setup — Linux Mint (Fase B / B1) ║"
|
||||
echo "╚══════════════════════════════════════════════════════╝"
|
||||
echo " Disco CI : $CI_DISK"
|
||||
echo " CI root : $CI_ROOT"
|
||||
echo " Utente : $CI_USER"
|
||||
echo ""
|
||||
|
||||
# ── Step 1: utente di servizio ────────────────────────────────────────────────
|
||||
info "[1/6] Utente di servizio $CI_USER"
|
||||
if id "$CI_USER" &>/dev/null; then
|
||||
warn "Utente $CI_USER esiste già — skip"
|
||||
else
|
||||
useradd -r -m -s /bin/bash "$CI_USER"
|
||||
echo " Creato utente $CI_USER"
|
||||
fi
|
||||
|
||||
# ── Step 2: mount partizione CI ───────────────────────────────────────────────
|
||||
info "[2/6] Mount $CI_DISK → $CI_ROOT"
|
||||
|
||||
if mountpoint -q "$CI_ROOT" 2>/dev/null; then
|
||||
warn "$CI_ROOT già montato — skip riorganizzazione e fstab"
|
||||
else
|
||||
# Recupera UUID e filesystem
|
||||
UUID=$(blkid -s UUID -o value "$CI_DISK" 2>/dev/null)
|
||||
FS_TYPE=$(blkid -s TYPE -o value "$CI_DISK" 2>/dev/null)
|
||||
[[ -z "$UUID" ]] && die "Impossibile determinare UUID di $CI_DISK"
|
||||
[[ -z "$FS_TYPE" ]] && die "Impossibile determinare filesystem di $CI_DISK"
|
||||
echo " UUID=$UUID TYPE=$FS_TYPE"
|
||||
|
||||
# Mount temporaneo per eventuale riorganizzazione
|
||||
TMP_MNT=$(mktemp -d /mnt/ci-setup-XXXXXX)
|
||||
mount "$CI_DISK" "$TMP_MNT"
|
||||
|
||||
if [[ -d "$TMP_MNT/ci" ]]; then
|
||||
echo " Trovata sottocartella ci/ — riorganizzazione in corso..."
|
||||
# Sposta tutto il contenuto di ci/ alla root della partizione
|
||||
shopt -s dotglob nullglob
|
||||
for item in "$TMP_MNT/ci/"*; do
|
||||
name=$(basename "$item")
|
||||
if [[ -e "$TMP_MNT/$name" ]]; then
|
||||
warn " Conflitto: $name già esiste alla root — skip spostamento"
|
||||
else
|
||||
mv "$item" "$TMP_MNT/"
|
||||
echo " Spostato: ci/$name → /"
|
||||
fi
|
||||
done
|
||||
shopt -u dotglob nullglob
|
||||
if [[ -z "$(ls -A "$TMP_MNT/ci" 2>/dev/null)" ]]; then
|
||||
rmdir "$TMP_MNT/ci"
|
||||
echo " Rimossa cartella ci/ vuota"
|
||||
else
|
||||
warn " ci/ non è vuota dopo lo spostamento — controlla manualmente"
|
||||
fi
|
||||
else
|
||||
echo " Nessuna sottocartella ci/ trovata — nessuna riorganizzazione necessaria"
|
||||
fi
|
||||
|
||||
umount "$TMP_MNT"
|
||||
rmdir "$TMP_MNT"
|
||||
|
||||
# Mount point e fstab
|
||||
mkdir -p "$CI_ROOT"
|
||||
if grep -q "UUID=$UUID" /etc/fstab; then
|
||||
warn "Entry fstab per UUID=$UUID già presente — skip"
|
||||
else
|
||||
echo "UUID=$UUID $CI_ROOT $FS_TYPE defaults,nofail 0 2" >> /etc/fstab
|
||||
echo " Aggiunta entry fstab"
|
||||
fi
|
||||
|
||||
mount -a
|
||||
mountpoint -q "$CI_ROOT" || die "mount -a fallito per $CI_ROOT"
|
||||
echo " Montato OK: $(df -h "$CI_ROOT" | tail -1)"
|
||||
fi
|
||||
|
||||
# ── Step 3: layout directory e permessi ───────────────────────────────────────
|
||||
info "[3/6] Layout directory e permessi"
|
||||
|
||||
# Installa acl se mancante
|
||||
if ! command -v setfacl &>/dev/null; then
|
||||
echo " Installazione pacchetto acl..."
|
||||
apt-get install -y acl -qq
|
||||
fi
|
||||
|
||||
mkdir -p \
|
||||
"$CI_ROOT"/{build-vms,artifacts,templates,keys,logs,runner} \
|
||||
"$OPT_CI" \
|
||||
/etc/ci/keys
|
||||
|
||||
chown -R "$CI_USER:$CI_USER" "$CI_ROOT" "$OPT_CI"
|
||||
chmod 750 "$CI_ROOT" "$OPT_CI"
|
||||
for d in build-vms artifacts templates keys logs runner; do
|
||||
chmod 750 "$CI_ROOT/$d"
|
||||
done
|
||||
chmod 700 /etc/ci/keys
|
||||
|
||||
# ACL di default su build-vms (ci-runner eredita rwX sui nuovi file)
|
||||
setfacl -d -m "u:$CI_USER:rwX" "$CI_ROOT/build-vms"
|
||||
echo " Layout OK — ACL default su build-vms applicata"
|
||||
|
||||
# ── Step 4: Python 3.11+ e venv ──────────────────────────────────────────────
|
||||
if [[ "$SKIP_PYTHON" == false ]]; then
|
||||
info "[4/6] Python 3.11+ e venv produzione"
|
||||
|
||||
# Cerca la prima versione di Python >= 3.11 già installata
|
||||
PYTHON_BIN=""
|
||||
for cmd in python3 python3.13 python3.12 python3.11; do
|
||||
if command -v "$cmd" &>/dev/null; then
|
||||
ver=$("$cmd" -c 'import sys; v=sys.version_info; print(v.major*100+v.minor)' 2>/dev/null)
|
||||
if [[ "${ver:-0}" -ge 311 ]]; then
|
||||
PYTHON_BIN="$cmd"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n "$PYTHON_BIN" ]]; then
|
||||
echo " Python >= 3.11 già presente: $($PYTHON_BIN --version) ($PYTHON_BIN)"
|
||||
apt-get install -y "python3-venv" git -qq 2>/dev/null || true
|
||||
else
|
||||
echo " Nessun Python >= 3.11 trovato — installazione python3.11..."
|
||||
apt-get install -y python3.11 python3.11-venv git -qq
|
||||
PYTHON_BIN="python3.11"
|
||||
fi
|
||||
|
||||
if [[ -d "$OPT_CI/venv" ]]; then
|
||||
warn "venv $OPT_CI/venv già esistente — skip"
|
||||
else
|
||||
"$PYTHON_BIN" -m venv "$OPT_CI/venv"
|
||||
chown -R "$CI_USER:$CI_USER" "$OPT_CI/venv"
|
||||
echo " venv creato in $OPT_CI/venv ($($PYTHON_BIN --version))"
|
||||
fi
|
||||
else
|
||||
info "[4/6] Python/venv — SKIPPED"
|
||||
fi
|
||||
|
||||
# ── Step 5: Clone repo e pip install ─────────────────────────────────────────
|
||||
if [[ "$SKIP_CLONE" == false ]]; then
|
||||
info "[5/6] Clone repo e pip install"
|
||||
REPO_DIR="$OPT_CI/local-ci-cd-system"
|
||||
if [[ -d "$REPO_DIR/.git" ]]; then
|
||||
warn "Repo già presente in $REPO_DIR — skip clone (eseguire git pull manualmente)"
|
||||
else
|
||||
echo " Clone repo..."
|
||||
sudo -u "$CI_USER" git clone "$REPO_URL" "$REPO_DIR"
|
||||
fi
|
||||
echo " pip install..."
|
||||
sudo -u "$CI_USER" "$OPT_CI/venv/bin/pip" install -q -e "$REPO_DIR"
|
||||
verify_out=$(sudo -u "$CI_USER" "$OPT_CI/venv/bin/python" -m ci_orchestrator --help 2>&1) \
|
||||
|| die "ci_orchestrator non importabile"
|
||||
echo " Verifica OK: ${verify_out%%$'\n'*}"
|
||||
else
|
||||
info "[5/6] Clone repo — SKIPPED"
|
||||
fi
|
||||
|
||||
# ── Step 6: PowerShell Core ───────────────────────────────────────────────────
|
||||
if [[ "$SKIP_PWSH" == false ]]; then
|
||||
info "[6/6] PowerShell Core"
|
||||
if command -v pwsh &>/dev/null; then
|
||||
warn "pwsh già installato: $(pwsh --version) — skip"
|
||||
else
|
||||
echo " Installazione PowerShell Core..."
|
||||
apt-get install -y wget apt-transport-https software-properties-common -qq
|
||||
# Linux Mint riporta la propria versione in VERSION_ID; serve quella Ubuntu base
|
||||
if [[ -f /etc/upstream-release/lsb-release ]]; then
|
||||
UBUNTU_VER=$(grep DISTRIB_RELEASE /etc/upstream-release/lsb-release | cut -d= -f2)
|
||||
else
|
||||
source /etc/os-release
|
||||
UBUNTU_VER="$VERSION_ID"
|
||||
fi
|
||||
wget -q "https://packages.microsoft.com/config/ubuntu/${UBUNTU_VER}/packages-microsoft-prod.deb" \
|
||||
-O /tmp/ms-prod.deb
|
||||
dpkg -i /tmp/ms-prod.deb
|
||||
apt-get update -qq 2>&1 || true # ignora errori di repo terzi (es. chiavi GPG scadute)
|
||||
apt-get install -y powershell -qq
|
||||
rm /tmp/ms-prod.deb
|
||||
echo " Installato: $(pwsh --version)"
|
||||
fi
|
||||
else
|
||||
info "[6/6] PowerShell Core — SKIPPED"
|
||||
fi
|
||||
|
||||
# ── Riepilogo ─────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════╗"
|
||||
echo "║ Setup completato ║"
|
||||
echo "╚══════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo " CI_ROOT : $CI_ROOT ($(df -h "$CI_ROOT" | awk 'NR==2{print $4}') liberi)"
|
||||
echo " CI_USER : $CI_USER"
|
||||
echo " venv : $OPT_CI/venv"
|
||||
echo ""
|
||||
echo "Passi successivi (manuali):"
|
||||
echo " B2 — Validare template VM in $CI_ROOT/templates/"
|
||||
echo " find $CI_ROOT/templates -name '*.vmx' -exec vmrun -T ws listSnapshots {} \\;"
|
||||
echo " B3 — Copiare chiavi SSH in /etc/ci/keys/ e configurare keyring"
|
||||
echo " B4 — Installare act_runner come systemd service"
|
||||
echo " B5 — Installare timer systemd da deploy/systemd/"
|
||||
echo ""
|
||||
echo "Vedi plans/PhaseB-user-checklist.md per i dettagli."
|
||||
Reference in New Issue
Block a user