diff --git a/deploy/mission-control-2.service b/deploy/mission-control-2.service index 21a26c6..c8e5528 100644 --- a/deploy/mission-control-2.service +++ b/deploy/mission-control-2.service @@ -20,7 +20,10 @@ Environment=MC_CONFIG_PATH=/etc/llama-swap/config.yaml Environment=MC_MODELS_DIR=/srv/models # Geteiltes Gedächtnis = die bestehende v1-DB (Kontinuität bis/über Cutover). Environment=MC_MEMORY_DB=/srv/models/mission-control-memory.db -Environment=MC_ENGINE_UPDATE_CMD=/usr/local/bin/update-llamacpp +# KEIN MC_ENGINE_UPDATE_CMD-Override mehr: Das alte /usr/local/bin/update-llamacpp zog den +# ROCm-Build nach /opt/llamacpp (totes Rollback-Dir) statt des aktiven Vulkan-Builds → Updates +# liefen ins Leere ("DONE", aber nichts passierte). Ohne Override nutzt das Backend den Default +# `sudo bash /deploy/update-engine.sh` (Vulkan, mit Backup/Stack-Check/Auto-Rollback). Restart=on-failure RestartSec=3 diff --git a/deploy/update-engine.sh b/deploy/update-engine.sh index 7e6931f..16395c4 100644 --- a/deploy/update-engine.sh +++ b/deploy/update-engine.sh @@ -1,24 +1,38 @@ #!/usr/bin/env bash -# Aktualisiert den Vulkan-llama.cpp-Build auf den neuesten ggml-org-Release. -# Wird vom MC2-„Engine Update"-Button via `sudo bash …` als ROOT aufgerufen -# (deshalb KEIN internes sudo). Startet llama-swap neu, VERIFIZIERT den Stack -# (stack-postcheck.sh) und ROLLT bei Fehler automatisch auf den vorherigen Build zurück. +# Aktualisiert den Vulkan-llama.cpp-Build (ggml-org) auf den neuesten Release. +# Wird vom MC2-„Engine Update"-Button via `sudo bash …` als ROOT aufgerufen (kein internes sudo). +# +# Wichtig: llama-swap wird VOR dem Datei-Austausch gestoppt — sonst ist die laufende llama-server- +# Binary „Text file busy" und die mmap'ten .so-Libs dürfen nicht unter dem laufenden Prozess +# getauscht werden. Danach Stack-Check (echte Inferenz); bei Fehler Auto-Rollback. # # Exit 0 = neuer Build verifiziert · 1 = fehlgeschlagen, Rollback ok (alter Build läuft) # · 2 = Update UND Rollback fehlgeschlagen (Stack evtl. kaputt — bitte prüfen) -set -euo pipefail +set -uo pipefail # bewusst KEIN -e: bei Fehlern kontrolliert zurückrollen statt hart abbrechen VULKAN_DIR=/opt/llamacpp-vulkan -BAK_DIR=/opt/llamacpp-vulkan.bak # „letzter funktionierender Build" für Auto-Rollback +BAK_DIR=/opt/llamacpp-vulkan.bak # „letzter funktionierender Build" für Auto-Rollback SRC_DIR="$(cd "$(dirname "$0")" && pwd)" -PIN_BUILD="${MC_ENGINE_BUILD:-}" # leer = neuester Release +PIN_BUILD="${MC_ENGINE_BUILD:-}" # leer = neuester Release +die(){ echo "$1" >&2; exit 1; } +start_swap(){ systemctl start llama-swap || systemctl restart llama-swap; } + +# Inhalte von $1 nach $VULKAN_DIR spiegeln (Dir vorher leeren → sauberer Austausch). +replace_dir(){ + rm -rf "${VULKAN_DIR:?}" && mkdir -p "$VULKAN_DIR" || return 1 + cp -a "$1/." "$VULKAN_DIR"/ || return 1 + ln -sfn "$VULKAN_DIR/llama-server" /usr/local/bin/llama-server + [ -x "$VULKAN_DIR/llama-server" ] +} + +# 1. Release ermitteln + laden (vor jedem Eingriff am laufenden System) if [ -n "$PIN_BUILD" ]; then TAG="$PIN_BUILD" else TAG="$(curl -s https://api.github.com/repos/ggml-org/llama.cpp/releases/latest | jq -r .tag_name)" fi -[ -n "$TAG" ] && [ "$TAG" != "null" ] || { echo "Konnte neuesten Release-Tag nicht ermitteln"; exit 1; } +[ -n "$TAG" ] && [ "$TAG" != "null" ] || die "Konnte neuesten Release-Tag nicht ermitteln" ASSET="llama-${TAG}-bin-ubuntu-vulkan-x64.tar.gz" URL="https://github.com/ggml-org/llama.cpp/releases/download/${TAG}/${ASSET}" @@ -26,42 +40,39 @@ TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT echo "Lade Engine ${TAG} …" -curl -fsSL -o "$TMP/v.tgz" "$URL" -tar xzf "$TMP/v.tgz" -C "$TMP" +curl -fsSL -o "$TMP/v.tgz" "$URL" || die "Download fehlgeschlagen" +tar xzf "$TMP/v.tgz" -C "$TMP" || die "Entpacken fehlgeschlagen" +NEWDIR="$(echo "$TMP"/llama-*/)" # Tarball entpackt nach llama-/ +[ -x "${NEWDIR}llama-server" ] || die "llama-server im Archiv nicht gefunden (${NEWDIR})" -# Sicherung des aktuellen (funktionierenden) Builds VOR dem Überschreiben → Auto-Rollback. -if [ -d "$VULKAN_DIR" ]; then - echo "Sichere aktuellen Build → ${BAK_DIR}" - rm -rf "$BAK_DIR" - cp -a "$VULKAN_DIR" "$BAK_DIR" +# 2. Aktuellen (funktionierenden) Build sichern → Auto-Rollback +echo "Sichere aktuellen Build → ${BAK_DIR}" +rm -rf "$BAK_DIR" +cp -a "$VULKAN_DIR" "$BAK_DIR" || die "Backup fehlgeschlagen" + +# 3. llama-swap stoppen (gibt Binary/Libs frei), austauschen, wieder starten +echo "Stoppe llama-swap für den Austausch…" +systemctl stop llama-swap +if replace_dir "${NEWDIR%/}"; then + start_swap + echo "Engine auf ${TAG} aktualisiert — verifiziere Stack…" + if bash "$SRC_DIR/stack-postcheck.sh"; then + echo "Engine-Update ${TAG} erfolgreich verifiziert." + exit 0 + fi + echo "!! Stack-Check fehlgeschlagen — ROLLBACK auf vorherigen Build." +else + echo "!! Datei-Austausch fehlgeschlagen — ROLLBACK auf vorherigen Build." fi -mkdir -p "$VULKAN_DIR" -cp -rf "$TMP"/llama-*/. "$VULKAN_DIR"/ -test -x "$VULKAN_DIR/llama-server" -ln -sfn "$VULKAN_DIR/llama-server" /usr/local/bin/llama-server -systemctl restart llama-swap - -echo "Engine auf ${TAG} aktualisiert — verifiziere Stack…" -if bash "$SRC_DIR/stack-postcheck.sh"; then - echo "Engine-Update ${TAG} erfolgreich verifiziert." - exit 0 -fi - -# --- Auto-Rollback auf den gesicherten Build --- -echo "!! Stack-Check fehlgeschlagen — ROLLBACK auf vorherigen Build." -if [ -d "$BAK_DIR" ]; then - rm -rf "$VULKAN_DIR" - cp -a "$BAK_DIR" "$VULKAN_DIR" - ln -sfn "$VULKAN_DIR/llama-server" /usr/local/bin/llama-server - systemctl restart llama-swap - echo "Vorheriger Build wiederhergestellt — prüfe Stack erneut…" +# 4. Auto-Rollback auf den gesicherten Build +systemctl stop llama-swap +if replace_dir "$BAK_DIR"; then + start_swap if bash "$SRC_DIR/stack-postcheck.sh"; then echo "Rollback erfolgreich: vorheriger Build läuft wieder. (Update ${TAG} NICHT angewendet.)" exit 1 fi - echo "!!! Rollback-Check ebenfalls fehlgeschlagen — Stack möglicherweise kaputt!" - exit 2 fi -echo "!!! Kein Backup vorhanden — Rollback nicht möglich!" +echo "!!! Rollback fehlgeschlagen — Stack möglicherweise kaputt! Backup liegt unter ${BAK_DIR}." exit 2 diff --git a/deploy/update-swap.sh b/deploy/update-swap.sh index 5a9c81f..52d1864 100755 --- a/deploy/update-swap.sh +++ b/deploy/update-swap.sh @@ -1,24 +1,28 @@ #!/usr/bin/env bash # Aktualisiert den llama-swap-Router (mostlygeek/llama-swap) auf den neuesten Release. -# Wird vom MC2-„Router Update"-Button via `sudo bash …` als ROOT aufgerufen -# (deshalb KEIN internes sudo). Ersetzt die Binary, startet llama-swap neu, VERIFIZIERT -# den Stack (stack-postcheck.sh) und ROLLT bei Fehler automatisch auf die alte Binary zurück. +# Wird vom MC2-„Router Update"-Button via `sudo bash …` als ROOT aufgerufen (kein internes sudo). +# +# Wichtig: llama-swap wird VOR dem Binary-Tausch gestoppt — sonst ist die laufende Binary +# „Text file busy". Danach Stack-Check (echte Inferenz); bei Fehler Auto-Rollback. # # Exit 0 = neue Version verifiziert · 1 = fehlgeschlagen, Rollback ok (alte Version läuft) # · 2 = Update UND Rollback fehlgeschlagen (Stack evtl. kaputt — bitte prüfen) -set -euo pipefail +set -uo pipefail # bewusst KEIN -e: bei Fehlern kontrolliert zurückrollen statt hart abbrechen SWAP_BIN="${MC_SWAP_BIN:-/usr/local/bin/llama-swap}" -BAK="${SWAP_BIN}.bak" # „letzte funktionierende Version" für Auto-Rollback +BAK="${SWAP_BIN}.bak" # „letzte funktionierende Version" für Auto-Rollback SRC_DIR="$(cd "$(dirname "$0")" && pwd)" -PIN_VER="${MC_SWAP_VERSION:-}" # leer = neuester Release +PIN_VER="${MC_SWAP_VERSION:-}" # leer = neuester Release + +die(){ echo "$1" >&2; exit 1; } +start_swap(){ systemctl start llama-swap || systemctl restart llama-swap; } if [ -n "$PIN_VER" ]; then TAG="$PIN_VER" else TAG="$(curl -s https://api.github.com/repos/mostlygeek/llama-swap/releases/latest | jq -r .tag_name)" fi -[ -n "$TAG" ] && [ "$TAG" != "null" ] || { echo "Konnte neuesten Release-Tag nicht ermitteln"; exit 1; } +[ -n "$TAG" ] && [ "$TAG" != "null" ] || die "Konnte neuesten Release-Tag nicht ermitteln" # Asset-Name nutzt die nackte Nummer (z.B. v230 -> 230): llama-swap_230_linux_amd64.tar.gz NUM="${TAG#v}" @@ -28,35 +32,37 @@ TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT echo "Lade llama-swap ${TAG} …" -curl -fsSL -o "$TMP/s.tgz" "$URL" -tar xzf "$TMP/s.tgz" -C "$TMP" +curl -fsSL -o "$TMP/s.tgz" "$URL" || die "Download fehlgeschlagen" +tar xzf "$TMP/s.tgz" -C "$TMP" || die "Entpacken fehlgeschlagen" NEW="$(find "$TMP" -type f -name llama-swap | head -1)" -[ -n "$NEW" ] || { echo "llama-swap-Binary im Archiv nicht gefunden"; exit 1; } +[ -n "$NEW" ] || die "llama-swap-Binary im Archiv nicht gefunden" -# Sicherung der aktuellen (funktionierenden) Binary VOR dem Überschreiben → Auto-Rollback. -[ -x "$SWAP_BIN" ] && cp -a "$SWAP_BIN" "$BAK" -install -m 0755 "$NEW" "$SWAP_BIN" -test -x "$SWAP_BIN" -systemctl restart llama-swap +# Sicherung der aktuellen (funktionierenden) Binary → Auto-Rollback +[ -x "$SWAP_BIN" ] && { cp -a "$SWAP_BIN" "$BAK" || die "Backup fehlgeschlagen"; } -echo "Router auf ${TAG} aktualisiert — verifiziere Stack…" -if bash "$SRC_DIR/stack-postcheck.sh"; then - echo "Router-Update ${TAG} erfolgreich verifiziert." - exit 0 +# llama-swap stoppen (gibt die laufende Binary frei), tauschen, wieder starten +echo "Stoppe llama-swap für den Binary-Tausch…" +systemctl stop llama-swap +if install -m 0755 "$NEW" "$SWAP_BIN" && [ -x "$SWAP_BIN" ]; then + start_swap + echo "Router auf ${TAG} aktualisiert — verifiziere Stack…" + if bash "$SRC_DIR/stack-postcheck.sh"; then + echo "Router-Update ${TAG} erfolgreich verifiziert." + exit 0 + fi + echo "!! Stack-Check fehlgeschlagen — ROLLBACK auf vorherige Version." +else + echo "!! Binary-Tausch fehlgeschlagen — ROLLBACK auf vorherige Version." fi -# --- Auto-Rollback auf die gesicherte Binary --- -echo "!! Stack-Check fehlgeschlagen — ROLLBACK auf vorherige Version." -if [ -x "$BAK" ]; then - cp -a "$BAK" "$SWAP_BIN" - systemctl restart llama-swap - echo "Vorherige Binary wiederhergestellt — prüfe Stack erneut…" +# Auto-Rollback auf die gesicherte Binary +systemctl stop llama-swap +if [ -x "$BAK" ] && install -m 0755 "$BAK" "$SWAP_BIN"; then + start_swap if bash "$SRC_DIR/stack-postcheck.sh"; then echo "Rollback erfolgreich: vorherige llama-swap-Version läuft wieder. (Update ${TAG} NICHT angewendet.)" exit 1 fi - echo "!!! Rollback-Check ebenfalls fehlgeschlagen — Stack möglicherweise kaputt!" - exit 2 fi -echo "!!! Kein Backup vorhanden — Rollback nicht möglich!" +echo "!!! Rollback fehlgeschlagen — Stack möglicherweise kaputt! Backup liegt unter ${BAK}." exit 2