install.sh wird update-faehig, update.sh auf Bootstrapper reduziert

install.sh erkennt jetzt selbststaendig eine bestehende Installation
(an sqlite.db) und verhaelt sich entsprechend:
- Keine vorhandene Installation -> normale Frischinstallation (wie
  bisher).
- Vorhanden, SCHEMA_VERSION unveraendert -> einfaches In-Place-Update,
  kein Backup noetig (rsync schliesst sqlite.db ohnehin aus).
- Vorhanden, SCHEMA_VERSION unbekannt/abweichend -> Update MIT
  Sicherheitsnetz: die KOMPLETTE bisherige Installation (Code, venv,
  Datenbank, Schluessel) wird vorher 1:1 nach
  /srv/tesm-backup-pre-migration-<timestamp> kopiert (bewusst nicht nur
  die Datenbank -- ein reines DB-Rollback wuerde beim naechsten Start
  mit dem NEUEN Code sofort denselben Migrationsfehler wiederholen).
  Die eigentliche Schema-Migration uebernimmt danach die App selbst
  beim Start (_ensure_schema() in app.py). Kommt der Dienst
  anschliessend per HTTP-Check auf /login nachweislich NICHT gesund
  hoch, wird automatisch die komplette Sicherung zurueckgespielt und
  bleibt zur manuellen Pruefung erhalten. Kommt er gesund hoch, gilt
  die Migration als erfolgreich und das Backup wird geloescht.

update.sh delegiert diese gesamte /srv/tesm-spezifische Logik jetzt an
install.sh und ist selbst nur noch fuer das Ablösen AELTERER, TESM
vorausgehender Installationsstufen zustaendig (PoE Manager unter
/srv/poe_manager, das urspruengliche reine Bash-Setup) -- bleibt aber
als bequemer Ein-Skript-Bootstrapper (Download + Entpacken + Aufruf von
install.sh) bestehen, wie gewuenscht. install.sh selbst ist dadurch
jetzt auch OHNE update.sh direkt aus einem entpackten Release-Paket
lauffaehig und erkennt ein Update trotzdem korrekt.

VERSION: 1.0.3 (SCHEMA_VERSION unveraendert, 1 -- keine echte Schema-
Aenderung in diesem Release, In-Place-Update-Pfad bleibt der Normalfall).
This commit is contained in:
2026-08-22 10:09:14 +02:00
parent e934c3ff0f
commit e17d91743a
3 changed files with 128 additions and 138 deletions
+89 -2
View File
@@ -1,15 +1,37 @@
#!/bin/bash #!/bin/bash
# ============================================================================ # ============================================================================
# TESM — Installer # TESM — Installer/Updater
# Richtet System-Pakete, die Flask-App (systemd) sowie den Erreichbarkeits- # Richtet System-Pakete, die Flask-App (systemd) sowie den Erreichbarkeits-
# Check-Dienst (systemd + Timer) ein. Auszuführen als root, nachdem dieses # Check-Dienst (systemd + Timer) ein. Auszuführen als root, nachdem dieses
# Repo z.B. nach /root/tesm geklont wurde. # Repo/Release-Paket z.B. nach /root/tesm entpackt wurde.
#
# Erkennt selbstständig, ob unter /srv/tesm bereits eine Installation
# existiert (an sqlite.db), und verhält sich entsprechend:
#
# - Keine vorhandene Installation -> normale Frischinstallation.
# - Vorhanden, SCHEMA_VERSION unverändert -> einfaches In-Place-Update
# (Code/Templates/Abhängigkeiten aktualisieren; sqlite.db bleibt
# unangetastet -- rsync schließt sie ohnehin aus). Kein Backup nötig,
# da sich am Datenbank-Schema nichts ändert.
# - Vorhanden, SCHEMA_VERSION unbekannt oder abweichend -> Update MIT
# Sicherheitsnetz: die komplette bisherige Installation (Code, venv,
# Datenbank, Schlüssel) wird vorher 1:1 nach /srv/tesm-backup-pre-
# migration-<timestamp> kopiert. Die eigentliche Schema-Migration
# übernimmt danach die App selbst beim Start (siehe _ensure_schema()
# in app.py). Kommt der Dienst anschließend nachweislich NICHT gesund
# hoch (HTTP-Check auf /login), wird automatisch die komplette
# Sicherung zurückgespielt (alter Code + alte Datenbank zusammen --
# ein reines DB-Rollback allein würde denselben Migrationsfehler beim
# nächsten Start mit dem neuen Code sofort wiederholen) und das
# Backup bleibt zur manuellen Prüfung erhalten. Kommt er gesund hoch,
# gilt die Migration als erfolgreich und das Backup wird gelöscht.
# ============================================================================ # ============================================================================
set -e set -e
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' NC='\033[0m'
print_status() { echo -e "${GREEN}${NC} ${1} completed."; } print_status() { echo -e "${GREEN}${NC} ${1} completed."; }
@@ -23,6 +45,41 @@ step() { echo -e "${RED}→${NC} ${1}..." | tee -a /var/log/tesm-install
# nie fatal. # nie fatal.
clear 2>/dev/null || true clear 2>/dev/null || true
# ---- Bestehende Installation erkennen ----
EXISTING_INSTALL=0
[ -f /srv/tesm/sqlite.db ] && EXISTING_INSTALL=1
NEEDS_MIGRATION_GUARD=0
BACKUP_DIR=""
if [ "$EXISTING_INSTALL" -eq 1 ]; then
OLD_SCHEMA_VERSION=""
[ -f /srv/tesm/SCHEMA_VERSION ] && OLD_SCHEMA_VERSION="$(tr -d '[:space:]' < /srv/tesm/SCHEMA_VERSION)"
NEW_SCHEMA_VERSION=""
[ -f "$REPO_DIR/srv/tesm/SCHEMA_VERSION" ] && NEW_SCHEMA_VERSION="$(tr -d '[:space:]' < "$REPO_DIR/srv/tesm/SCHEMA_VERSION")"
step "Stopping tesm.service for update"
systemctl stop tesm.service tesm-check.service tesm-check-restart.timer 2>/dev/null || true
print_status "Service stopped"
if [ -n "$OLD_SCHEMA_VERSION" ] && [ -n "$NEW_SCHEMA_VERSION" ] && [ "$OLD_SCHEMA_VERSION" == "$NEW_SCHEMA_VERSION" ]; then
echo -e "${GREEN}Bestehende Installation erkannt, Datenbank-Schema unverändert (Version ${OLD_SCHEMA_VERSION}):${NC} einfaches In-Place-Update, kein Backup nötig."
else
if [ -n "$OLD_SCHEMA_VERSION" ] && [ -n "$NEW_SCHEMA_VERSION" ]; then
reason="Datenbank-Schema hat sich geändert (${OLD_SCHEMA_VERSION} -> ${NEW_SCHEMA_VERSION})"
else
reason="Schema-Version der bestehenden Installation oder dieses Pakets unbekannt"
fi
echo -e "${YELLOW}Bestehende Installation erkannt, ${reason}:${NC}"
echo "Update mit automatischer Migration und Sicherheitsnetz (Rückroll-Backup)."
NEEDS_MIGRATION_GUARD=1
BACKUP_DIR="/srv/tesm-backup-pre-migration-$(date +%Y%m%d-%H%M%S)"
step "Backing up current installation to $BACKUP_DIR before migration"
cp -a /srv/tesm "$BACKUP_DIR"
print_status "Backup created"
fi
fi
# ---- Pakete ---- # ---- Pakete ----
step "Installing system packages" step "Installing system packages"
sudo apt-get update >>/var/log/tesm-install.log 2>&1 && print_status "apt update" sudo apt-get update >>/var/log/tesm-install.log 2>&1 && print_status "apt update"
@@ -107,4 +164,34 @@ sudo systemctl enable --now tesm.service
sudo systemctl enable --now tesm-check.service tesm-check-restart.timer sudo systemctl enable --now tesm-check.service tesm-check-restart.timer
print_status "Services enabled and started" print_status "Services enabled and started"
# ---- Migrations-Sicherheitsnetz prüfen ----
# Nur relevant, wenn oben tatsächlich eine riskante Migration (abweichende/
# unbekannte SCHEMA_VERSION) erkannt wurde -- beim einfachen In-Place-Update
# oder einer Frischinstallation ist BACKUP_DIR leer und dieser Block wird
# komplett übersprungen.
if [ "$NEEDS_MIGRATION_GUARD" -eq 1 ]; then
step "Verifying migrated installation"
HEALTHY=0
for i in $(seq 1 15); do
sleep 2
if curl -fsS -o /dev/null http://127.0.0.1:5000/login 2>/dev/null; then
HEALTHY=1
break
fi
done
if [ "$HEALTHY" -eq 1 ]; then
print_status "Migration verified healthy"
rm -rf "$BACKUP_DIR"
echo -e "${GREEN}${NC} Migration erfolgreich -- Backup wieder entfernt."
else
echo -e "${RED}✖ Migration fehlgeschlagen -- Dienst antwortet nicht gesund. Rolle zurück...${NC}"
sudo systemctl stop tesm.service 2>/dev/null || true
sudo rm -rf /srv/tesm
sudo mv "$BACKUP_DIR" /srv/tesm
sudo systemctl start tesm.service
echo -e "${YELLOW}Zurückgerollt auf den Stand vor dem Update (alter Code + alte Datenbank zusammen).${NC}"
echo "Bitte /var/log/tesm/app.log prüfen oder Export/Import nutzen, bevor erneut aktualisiert wird."
fi
fi
echo -e "${GREEN}${NC} Installation abgeschlossen. Web-App erreichbar auf Port 80 (nginx) bzw. 5000 (Flask direkt)." echo -e "${GREEN}${NC} Installation abgeschlossen. Web-App erreichbar auf Port 80 (nginx) bzw. 5000 (Flask direkt)."
+1 -1
View File
@@ -1 +1 @@
1.0.2 1.0.3
+38 -135
View File
@@ -1,39 +1,26 @@
#!/bin/bash #!/bin/bash
# ============================================================================ # ============================================================================
# TESM — Update/Reinstall # TESM — Update/Reinstall (Bootstrapper)
# Ersetzt eine bestehende Installation -- ganz gleich welche der drei # Lädt ein gepacktes Gitea-Release per HTTP herunter (kein "git clone"
# historischen Stufen dieses Hosts gerade aktiv ist: # nötig) und übergibt die eigentliche Installations-/Update-Logik an
# install.sh aus dem Paket -- das erkennt selbstständig, ob unter
# /srv/tesm schon eine Installation existiert, und aktualisiert sie
# entsprechend (In-Place bei unverändertem Datenbank-Schema, sonst mit
# automatischem Backup + Migrations-Sicherheitsnetz samt Rückroll-
# Möglichkeit -- siehe install.sh für Details).
#
# Dieses Skript selbst ist nur noch für das Ablösen ÄLTERER, TESM
# vorausgehender Installationsstufen auf diesem Host zuständig:
# 1. Das ursprüngliche, reine Bash-Setup aus dem separaten Repo # 1. Das ursprüngliche, reine Bash-Setup aus dem separaten Repo
# https://gitea.int.eertmoed.net/WiS/Aruba-PoE (rpi-check.service + # https://gitea.int.eertmoed.net/WiS/Aruba-PoE (rpi-check.service +
# statische ips.list, keine Datenbank/Web-UI). # statische ips.list, keine Datenbank/Web-UI).
# 2. Die spätere Flask-App "PoE Manager" unter /srv/poe_manager # 2. Die spätere Flask-App "PoE Manager" unter /srv/poe_manager
# (poe_web.service, Vorgänger von TESM in diesem Repo vor der # (poe_web.service, Vorgänger von TESM in diesem Repo vor der
# Umbenennung). # Umbenennung).
# 3. Eine bereits während der Entwicklung ad-hoc gepflegte TESM-Instanz # Beide werden NICHT gelöscht, sondern nur gestoppt/deaktiviert und
# unter /srv/tesm. # (falls vorhanden) beiseite verschoben.
# -- durch eine frische Installation aus einem gepackten Gitea-Release.
# Lädt dafür NUR den Release-Tarball per HTTP herunter (kein "git clone",
# kein Git auf dem Zielsystem nötig).
# #
# /srv/poe_manager (Stufe 2, komplett anderes Schema/App) wird IMMER nur # Auszuführen als root auf dem Zielsystem:
# gestoppt/deaktiviert und beiseite verschoben, nie in-place übernommen.
#
# /srv/tesm (Stufe 3) dagegen wird per SCHEMA_VERSION-Datei verglichen:
# stimmt die Versionsnummer der bereits installierten mit der des neuen
# Release-Pakets überein, hat sich am Datenbank-Schema nichts geändert --
# dann läuft install.sh IN-PLACE gegen das bestehende /srv/tesm (dessen
# rsync schließt sqlite.db/fernet.key/secret.key ohnehin aus), die
# komplette Datenbank (Geräte, Switche, Zugangsdaten, Benutzer,
# Einstellungen, …) bleibt dabei erhalten. Nur bei einer TATSÄCHLICHEN
# Schema-Änderung (oder wenn die alte Installation noch keine
# SCHEMA_VERSION-Datei kennt, also aus der Zeit vor dieser Prüfung stammt)
# wird wie bisher beiseite verschoben und frisch installiert.
#
# Lädt/entpackt das Release-Paket deshalb VOR der Bestätigungsabfrage --
# nur so lässt sich vorher schon ansagen, ob es sich um ein
# datenerhaltendes Update oder eine frische Installation handelt.
#
# Auszuführen als root auf dem Zielsystem (z.B. POETEST):
# sudo ./update.sh # sudo ./update.sh
# Optional übersteuerbar (z.B. für eine bestimmte Version statt "latest"): # Optional übersteuerbar (z.B. für eine bestimmte Version statt "latest"):
# TESM_RELEASE_TAG=v1.0.0 sudo -E ./update.sh # TESM_RELEASE_TAG=v1.0.0 sudo -E ./update.sh
@@ -69,6 +56,21 @@ echo -e "${YELLOW}==============================================================
echo -e "${YELLOW} TESM Update/Reinstall — Release \"${RELEASE_TAG}\"${NC}" echo -e "${YELLOW} TESM Update/Reinstall — Release \"${RELEASE_TAG}\"${NC}"
echo -e "${YELLOW}============================================================================${NC}" echo -e "${YELLOW}============================================================================${NC}"
echo echo
echo "Lädt das Release-Paket herunter und übergibt Installation/Update an"
echo "install.sh daraus -- das erkennt selbst, ob es sich um eine frische"
echo "Installation oder ein Update einer bestehenden handelt, und sichert"
echo "die Datenbank bei einer Schema-Änderung automatisch vorsorglich ab."
echo
echo "Ältere, TESM vorausgehende Installationsstufen (PoE Manager unter"
echo "/srv/poe_manager, das ursprüngliche reine Bash-Setup) werden dabei"
echo "erkannt, gestoppt/deaktiviert und beiseite verschoben (nicht gelöscht)."
echo
read -r -p "Fortfahren? [y/N] " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "Abgebrochen — nichts wurde verändert."
exit 0
fi
echo -e "${RED}${NC} Lade Paket von ${DOWNLOAD_URL}..." echo -e "${RED}${NC} Lade Paket von ${DOWNLOAD_URL}..."
mkdir -p "$WORK_DIR" mkdir -p "$WORK_DIR"
@@ -84,127 +86,28 @@ mkdir -p "$WORK_DIR/pkg"
tar xzf "$PACKAGE_FILE" -C "$WORK_DIR/pkg" --strip-components=1 tar xzf "$PACKAGE_FILE" -C "$WORK_DIR/pkg" --strip-components=1
echo -e "${GREEN}${NC} Paket entpackt." echo -e "${GREEN}${NC} Paket entpackt."
# Schema-Vergleich: nur wenn BEIDE Seiten eine SCHEMA_VERSION kennen UND echo -e "${RED}${NC} Stoppe/deaktiviere ältere Installationsstufen (falls vorhanden)..."
# sie übereinstimmen UND tatsächlich schon eine Datenbank existiert, darf # "|| true" macht nichts kaputt, falls einzelne Units gar nicht vorhanden
# in-place aktualisiert werden. Fehlt die Datei auf einer der beiden # sind. tesm.service selbst wird NICHT hier, sondern von install.sh
# Seiten (ältere Installation/älteres Paket von vor dieser Prüfung), wird # gestoppt -- das entscheidet dort auch gleich, ob ein Backup nötig ist.
# im Zweifel IMMER der sichere, datenerhaltende-per-Backup Weg gewählt.
CURRENT_SCHEMA_VERSION=""
[ -f /srv/tesm/SCHEMA_VERSION ] && CURRENT_SCHEMA_VERSION="$(tr -d '[:space:]' < /srv/tesm/SCHEMA_VERSION)"
NEW_SCHEMA_VERSION=""
[ -f "$WORK_DIR/pkg/srv/tesm/SCHEMA_VERSION" ] && NEW_SCHEMA_VERSION="$(tr -d '[:space:]' < "$WORK_DIR/pkg/srv/tesm/SCHEMA_VERSION")"
IN_PLACE_UPDATE=0
if [ -f /srv/tesm/sqlite.db ] && [ -n "$CURRENT_SCHEMA_VERSION" ] && [ -n "$NEW_SCHEMA_VERSION" ] \
&& [ "$CURRENT_SCHEMA_VERSION" == "$NEW_SCHEMA_VERSION" ]; then
IN_PLACE_UPDATE=1
fi
if [ "$IN_PLACE_UPDATE" -eq 1 ]; then
echo -e "${GREEN}Datenbank-Schema unverändert (Version ${CURRENT_SCHEMA_VERSION}):${NC} dies wird ein"
echo "IN-PLACE-Update. /srv/tesm bleibt bestehen -- Geräte/Switche/Zugangsdaten/"
echo "Benutzer/Einstellungen (sqlite.db) sowie Host-Keys und Verschlüsselungs-"
echo "Schlüssel (fernet.key/secret.key) bleiben unangetastet. Es werden nur"
echo "Anwendungscode, Templates und Abhängigkeiten aktualisiert."
else
if [ -n "$CURRENT_SCHEMA_VERSION" ] && [ -n "$NEW_SCHEMA_VERSION" ]; then
reason="Datenbank-Schema hat sich geändert (${CURRENT_SCHEMA_VERSION}${NEW_SCHEMA_VERSION})"
elif [ -f /srv/tesm/sqlite.db ]; then
reason="Schema-Version der bestehenden Installation oder des neuen Pakets unbekannt (Stand von vor dieser Prüfung)"
else
reason="keine bestehende Installation unter /srv/tesm gefunden"
fi
echo -e "${RED}ACHTUNG:${NC} Dies richtet TESM KOMPLETT NEU ein — frische Datenbank, KEINE"
echo "Geräte/Switche/Zugangsdaten/Benutzer/Einstellungen aus der aktuellen Installation."
echo "Grund: ${reason}."
echo
echo "Alle auf diesem Host ggf. vorhandenen älteren Installationen (/srv/tesm,"
echo "/srv/poe_manager) werden dabei NICHT gelöscht, sondern nach dem Stoppen der"
echo "jeweiligen Dienste nach <Verzeichnis>-backup-${TIMESTAMP} verschoben (bleiben"
echo "vollständig erhalten, inkl. sqlite.db)."
echo
echo -e "${YELLOW}Falls noch nicht geschehen: JETZT abbrechen und zuerst unter${NC}"
echo -e "${YELLOW}Einstellungen -> Im-/Export ein Backup der aktuellen Daten exportieren!${NC}"
echo "Nach dem Update entweder dieses Backup importieren, oder alles manuell neu anlegen."
fi
echo
echo "In jedem Fall gestoppt/deaktiviert werden ältere Dienste, falls noch vorhanden:"
echo " - poe_web.service (Flask-App \"PoE Manager\" unter /srv/poe_manager)"
echo " - rpi-check.service / rpi-check-restart.* (das ursprüngliche reine"
echo " Bash-Setup aus dem Repo WiS/Aruba-PoE, ganz ohne Datenbank/Web-UI)"
echo
read -r -p "Fortfahren? [y/N] " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
echo "Abgebrochen — nichts wurde verändert."
exit 0
fi
echo -e "${RED}${NC} Stoppe und deaktiviere bestehende Dienste..."
# Alle drei historischen Generationen -- je nachdem, was auf diesem Host
# tatsächlich (noch) existiert. "|| true" macht nichts kaputt, falls
# einzelne Units gar nicht vorhanden sind. tesm.service wird auch beim
# In-Place-Update gestoppt (sauberer Neustart mit neuem Code danach über
# install.sh "Enabling services"), NUR /srv/tesm selbst bleibt erhalten.
systemctl stop tesm.service tesm-check.service tesm-check-restart.timer 2>/dev/null || true
systemctl disable tesm.service tesm-check.service tesm-check-restart.timer 2>/dev/null || true
systemctl stop poe_web.service 2>/dev/null || true systemctl stop poe_web.service 2>/dev/null || true
systemctl disable poe_web.service 2>/dev/null || true systemctl disable poe_web.service 2>/dev/null || true
systemctl stop rpi-check.service rpi-check-restart.service rpi-check-restart.timer 2>/dev/null || true systemctl stop rpi-check.service rpi-check-restart.service rpi-check-restart.timer 2>/dev/null || true
systemctl disable rpi-check.service rpi-check-restart.service rpi-check-restart.timer 2>/dev/null || true systemctl disable rpi-check.service rpi-check-restart.service rpi-check-restart.timer 2>/dev/null || true
echo -e "${GREEN}${NC} Dienste gestoppt und deaktiviert."
BACKED_UP_DIRS=()
# /srv/poe_manager ist eine komplett andere App/Schema -- die wird IMMER
# beiseite verschoben, nie in-place übernommen.
if [ -d /srv/poe_manager ]; then if [ -d /srv/poe_manager ]; then
dest="/srv/poe_manager-backup-${TIMESTAMP}" dest="/srv/poe_manager-backup-${TIMESTAMP}"
echo -e "${RED}${NC} Sichere /srv/poe_manager nach ${dest}..." echo -e "${RED}${NC} Sichere /srv/poe_manager nach ${dest}..."
mv /srv/poe_manager "$dest" mv /srv/poe_manager "$dest"
BACKED_UP_DIRS+=("$dest")
echo -e "${GREEN}${NC} Gesichert (nicht gelöscht)."
fi
# /srv/tesm nur beiseite verschieben, wenn KEIN In-Place-Update möglich ist
# (siehe Schema-Vergleich oben) -- sonst bleibt es unangetastet stehen,
# damit install.sh gleich dagegen rsynct und die Datenbank erhalten bleibt.
if [ "$IN_PLACE_UPDATE" -eq 0 ] && [ -d /srv/tesm ]; then
dest="/srv/tesm-backup-${TIMESTAMP}"
echo -e "${RED}${NC} Sichere /srv/tesm nach ${dest}..."
mv /srv/tesm "$dest"
BACKED_UP_DIRS+=("$dest")
echo -e "${GREEN}${NC} Gesichert (nicht gelöscht)." echo -e "${GREEN}${NC} Gesichert (nicht gelöscht)."
fi fi
echo -e "${GREEN}${NC} Ältere Installationsstufen bereinigt."
echo -e "${RED}${NC} Starte install.sh aus dem Paket..." echo -e "${RED}${NC} Starte install.sh aus dem Paket..."
bash "$WORK_DIR/pkg/install.sh" bash "$WORK_DIR/pkg/install.sh"
echo echo
echo -e "${GREEN}============================================================================${NC}" echo -e "${GREEN}============================================================================${NC}"
if [ "$IN_PLACE_UPDATE" -eq 1 ]; then echo -e "${GREEN} TESM Update/Reinstall (Release \"${RELEASE_TAG}\") abgeschlossen.${NC}"
echo -e "${GREEN} TESM-Update (Release \"${RELEASE_TAG}\") abgeschlossen -- Datenbank erhalten.${NC}" echo -e "${GREEN}============================================================================${NC}"
echo -e "${GREEN}============================================================================${NC}" echo "Siehe Ausgabe von install.sh oben für Details (In-Place-Update, frische"
echo echo "Installation, oder Migrationsergebnis inkl. eventuellem Rückroll-Hinweis)."
echo "Alle Geräte/Switche/Zugangsdaten/Benutzer/Einstellungen sind unverändert"
echo "vorhanden -- kein manuelles Neuanlegen oder Re-Import nötig."
else
echo -e "${GREEN} Frische TESM-Installation (Release \"${RELEASE_TAG}\") abgeschlossen.${NC}"
echo -e "${GREEN}============================================================================${NC}"
echo
echo -e "${YELLOW}WICHTIG — dies ist eine FRISCHE Installation ohne die Daten der alten Instanz.${NC}"
echo "Bitte jetzt eines von beidem tun:"
echo " a) Alle Geräte/Switche/Zugangsdaten/Benutzer/Einstellungen manuell neu anlegen, oder"
echo " b) Ein vor dem Update exportiertes Backup unter Einstellungen -> Im-/Export importieren."
echo
if [ "${#BACKED_UP_DIRS[@]}" -gt 0 ]; then
echo "Falls kein Export gemacht wurde: die alte(n) Datenbank(en) liegen unverändert unter:"
for dest in "${BACKED_UP_DIRS[@]}"; do
echo " ${dest}/sqlite.db"
done
echo "und können bei Bedarf manuell ausgelesen werden (z.B. mit sqlite3)."
echo
fi
echo "Hinweis zum Admin-Konto der neuen Installation: siehe Ausgabe von install.sh oben"
echo "(bei einer frischen Datenbank wird dort auf create_admin.py hingewiesen)."
fi