Files

488 lines
10 KiB
Bash

#!/bin/bash
set -euo pipefail
# ==================================================
# Konfiguration
# ==================================================
BASE="/opt"
CURRENT="/opt/iventoy"
PERSIST="/srv/iventoy"
ISO_DIR="${PERSIST}/iso"
CONFIG_DIR="${PERSIST}/config"
CONFIG_FILE="${CONFIG_DIR}/config.dat"
SERVICE="iventoy"
TMP="/tmp/iventoy-update"
GITHUB_REPO="ventoy/PXE"
MAX_CONFIG_BACKUPS=10
KEEP_VERSIONS=3
# ==================================================
# Ausgabe
# ==================================================
echo "=========================================="
echo " iVentoy Update"
echo "=========================================="
echo
# ==================================================
# Root Check
# ==================================================
if [ "$(id -u)" -ne 0 ]; then
echo "ERROR: Dieses Script muss als root laufen."
exit 1
fi
# ==================================================
# Abhängigkeiten
# ==================================================
apt-get update -qq
apt-get install -y -qq curl tar iproute2 >/dev/null
# ==================================================
# Persistente Verzeichnisse
# ==================================================
mkdir -p "$ISO_DIR"
mkdir -p "$CONFIG_DIR"
# ==================================================
# Aktuelle Version online ermitteln
# ==================================================
echo "Ermittle aktuelle iVentoy-Version..."
LATEST_TAG=$(
curl -fsSL \
-o /dev/null \
-w '%{url_effective}' \
"https://github.com/${GITHUB_REPO}/releases/latest" \
| awk -F/ '{print $NF}'
)
VERSION="${LATEST_TAG#v}"
if [ -z "$VERSION" ]; then
echo "ERROR: Konnte aktuelle Version nicht ermitteln."
exit 1
fi
TARGET="${BASE}/iventoy-${VERSION}"
echo "Neueste Version: $VERSION"
# ==================================================
# Bereits aktuell?
# ==================================================
if [ -L "$CURRENT" ]; then
CURRENT_TARGET=$(readlink -f "$CURRENT" || true)
if [ "$CURRENT_TARGET" = "$TARGET" ]; then
echo
echo "=========================================="
echo " iVentoy ist bereits aktuell"
echo "=========================================="
echo
echo "Aktive Version: $VERSION"
echo "Installation: $CURRENT -> $TARGET"
echo
exit 0
fi
fi
# ==================================================
# Bestehende Config erstmalig übernehmen
# ==================================================
if [ ! -f "$CONFIG_FILE" ]; then
if [ -f "${CURRENT}/data/config.dat" ]; then
echo
echo "Übernehme bestehende iVentoy Config..."
cp -a "${CURRENT}/data/config.dat" "$CONFIG_FILE"
else
echo
echo "WARNUNG: Keine bestehende config.dat gefunden."
fi
fi
# ==================================================
# Config Backup
# ==================================================
if [ -f "$CONFIG_FILE" ]; then
BACKUP="${CONFIG_FILE}.bak-$(date +%Y%m%d-%H%M%S)"
echo
echo "Sichere Config:"
echo " $BACKUP"
cp -a "$CONFIG_FILE" "$BACKUP"
# ----------------------------------------------
# Backup Rotation
# ----------------------------------------------
echo "Behalte maximal ${MAX_CONFIG_BACKUPS} Config-Backups..."
find "$CONFIG_DIR" \
-maxdepth 1 \
-type f \
-name 'config.dat.bak-*' \
-printf '%T@ %p\n' \
| sort -nr \
| tail -n +"$((MAX_CONFIG_BACKUPS + 1))" \
| cut -d' ' -f2- \
| xargs -r rm -f
fi
# ==================================================
# Download / Entpacken
# ==================================================
if [ -d "$TARGET" ]; then
echo
echo "Version $VERSION ist bereits vorhanden:"
echo " $TARGET"
else
rm -rf "$TMP"
mkdir -p "$TMP"
ARCHIVE="iventoy-${VERSION}-linux-x86_64-free.tar.gz"
URL="https://github.com/${GITHUB_REPO}/releases/download/v${VERSION}/${ARCHIVE}"
echo
echo "Lade herunter:"
echo " $URL"
curl -fL "$URL" -o "${TMP}/${ARCHIVE}"
echo
echo "Entpacke iVentoy..."
tar -xzf "${TMP}/${ARCHIVE}" -C "$TMP"
EXTRACTED="${TMP}/iventoy-${VERSION}"
if [ ! -d "$EXTRACTED" ]; then
echo "ERROR: Erwartetes Verzeichnis wurde nicht gefunden:"
echo " $EXTRACTED"
exit 1
fi
mv "$EXTRACTED" "$TARGET"
fi
# ==================================================
# ISO Symlink
# ==================================================
echo
echo "Setze ISO-Symlink..."
rm -rf "${TARGET}/iso"
ln -s "$ISO_DIR" "${TARGET}/iso"
# ==================================================
# Config Symlink
# ==================================================
if [ -f "$CONFIG_FILE" ]; then
echo "Setze Config-Symlink..."
rm -f "${TARGET}/data/config.dat"
ln -s \
"$CONFIG_FILE" \
"${TARGET}/data/config.dat"
fi
# ==================================================
# iVentoy stoppen
# ==================================================
echo
echo "Stoppe iVentoy..."
systemctl stop "$SERVICE" 2>/dev/null || true
sleep 2
# ==================================================
# Alte direkte Installation migrieren
# ==================================================
#
# Falls /opt/iventoy beim ersten Lauf noch ein
# echtes Verzeichnis statt eines Symlinks ist.
#
if [ -e "$CURRENT" ] && [ ! -L "$CURRENT" ]; then
OLD="${BASE}/iventoy-old-$(date +%Y%m%d-%H%M%S)"
echo
echo "Bestehende Installation wird verschoben:"
echo " $CURRENT -> $OLD"
mv "$CURRENT" "$OLD"
fi
# ==================================================
# Current Symlink atomar umschalten
# ==================================================
echo
echo "Aktiviere iVentoy $VERSION..."
ln -sfn "$TARGET" "${CURRENT}.new"
mv -Tf "${CURRENT}.new" "$CURRENT"
# ==================================================
# Service starten
# ==================================================
echo
echo "Starte iVentoy..."
systemctl start "$SERVICE"
sleep 4
# ==================================================
# Healthcheck
# ==================================================
echo
echo "Führe Healthcheck aus..."
FAILED=0
# Service
if systemctl is-active --quiet "$SERVICE"; then
echo "OK: iVentoy systemd service is active"
else
echo "ERROR: iVentoy systemd service is NOT active"
FAILED=1
fi
# TCP 26000
if ss -lntH | awk '{print $4}' | grep -Eq '[:.]26000$'; then
echo "OK: TCP 26000 is listening"
else
echo "ERROR: TCP 26000 is NOT listening"
FAILED=1
fi
# TCP 16000
if ss -lntH | awk '{print $4}' | grep -Eq '[:.]16000$'; then
echo "OK: TCP 16000 is listening"
else
echo "ERROR: TCP 16000 is NOT listening"
FAILED=1
fi
# UDP 69
if ss -lnuH | awk '{print $4}' | grep -Eq '[:.]69$'; then
echo "OK: UDP 69 is listening"
else
echo "ERROR: UDP 69 is NOT listening"
FAILED=1
fi
# UDP 4011
if ss -lnuH | awk '{print $4}' | grep -Eq '[:.]4011$'; then
echo "OK: UDP 4011 is listening"
else
echo "ERROR: UDP 4011 is NOT listening"
FAILED=1
fi
# UDP 67
if ss -lnuH | awk '{print $4}' | grep -Eq '[:.]67$'; then
echo "OK: UDP 67 is listening"
else
echo "ERROR: UDP 67 is NOT listening"
FAILED=1
fi
# Web GUI
if curl -fsS \
--max-time 5 \
http://127.0.0.1:26000/ \
>/dev/null 2>&1; then
echo "OK: Web GUI responds"
else
echo "ERROR: Web GUI does NOT respond"
FAILED=1
fi
# PXE HTTP Bind-IP bestimmen
PXE_BIND=$(ss -lntH | awk '$4 ~ /:16000$/ {print $4; exit}')
if [ -n "$PXE_BIND" ]; then
PXE_IP="${PXE_BIND%:16000}"
PXE_IP="${PXE_IP#[}"
PXE_IP="${PXE_IP%]}"
if [[ "$PXE_IP" == "*" || \
"$PXE_IP" == "0.0.0.0" || \
"$PXE_IP" == "::" ]]; then
PXE_IP="127.0.0.1"
fi
if curl -sS \
--max-time 5 \
-o /dev/null \
"http://${PXE_IP}:16000/" \
>/dev/null 2>&1; then
echo "OK: PXE HTTP service on ${PXE_IP}:16000 responds"
else
echo "ERROR: PXE HTTP service on ${PXE_IP}:16000 does NOT respond"
FAILED=1
fi
else
echo "ERROR: Could not determine PXE HTTP bind address"
FAILED=1
fi
# ==================================================
# Healthcheck fehlgeschlagen
# ==================================================
if [ "$FAILED" -ne 0 ]; then
echo
echo "=========================================="
echo " UPDATE FEHLGESCHLAGEN"
echo "=========================================="
echo
if [ -f "${CURRENT}/log/log.txt" ]; then
echo "Letzte iVentoy Log-Einträge:"
echo
tail -n 50 "${CURRENT}/log/log.txt" || true
fi
echo
echo "Alte iVentoy-Versionen wurden NICHT gelöscht."
echo "Damit ist ein manueller Rollback weiterhin möglich."
exit 1
fi
# ==================================================
# Alte Versionen aufräumen
# ==================================================
echo
echo "Räume alte iVentoy-Versionen auf..."
echo "Behalte maximal ${KEEP_VERSIONS} Versionen."
ACTIVE_TARGET=$(readlink -f "$CURRENT")
mapfile -t VERSION_DIRS < <(
find "$BASE" \
-maxdepth 1 \
-mindepth 1 \
-type d \
-name 'iventoy-[0-9]*' \
-printf '%T@ %p\n' \
| sort -nr \
| cut -d' ' -f2-
)
COUNT=0
for DIR in "${VERSION_DIRS[@]}"; do
# Aktive Version niemals löschen
if [ "$(readlink -f "$DIR")" = "$ACTIVE_TARGET" ]; then
COUNT=$((COUNT + 1))
continue
fi
COUNT=$((COUNT + 1))
if [ "$COUNT" -gt "$KEEP_VERSIONS" ]; then
echo "Lösche alte Version:"
echo " $DIR"
rm -rf "$DIR"
fi
done
# ==================================================
# Temp-Dateien aufräumen
# ==================================================
rm -rf "$TMP"
# ==================================================
# Abschluss
# ==================================================
echo
echo "=========================================="
echo " Update erfolgreich"
echo "=========================================="
echo
echo "Aktive Version:"
echo " $VERSION"
echo
echo "Installation:"
echo " $CURRENT -> $TARGET"
echo
echo "Config:"
echo " ${CURRENT}/data/config.dat -> $CONFIG_FILE"
echo
echo "ISO:"
echo " ${CURRENT}/iso -> $ISO_DIR"
echo
echo "Config-Backups:"
echo " maximal $MAX_CONFIG_BACKUPS"
echo
echo "Installierte iVentoy-Versionen:"
echo " maximal $KEEP_VERSIONS"
echo