espo-deploy/rmm-tasks/ESPO-12-Snapshot-wiederherstellen.sh
Gordon Zimm e63d1b432b ESPO-12 belegt, dass der Snapshot verbraucht ist
Beim Zusammenfuehren verbraucht LVM den Snapshot; bleibt er stehen, wurde das
Zusammenfuehren auf die naechste Aktivierung verschoben und der Stand ist noch
nicht zurueckgenommen. Das Skript sagt jetzt welches von beidem eingetreten ist
und zeigt am Ende die freien Extents - wie ESPO-11 es tut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-24 17:15:23 +02:00

101 lines
5.0 KiB
Bash
Executable File

#!/bin/bash
# ESPO-12-Snapshot-wiederherstellen - setzt die Instanz auf den Stand vor dem Update zurueck.
# Aufruf: ohne Argumente. Verwendet den Snapshot, den ESPO-10 angelegt hat.
#
# Der Snapshot wird dabei VERBRAUCHT: Nach dem Zusammenfuehren existiert er nicht mehr, ein zweiter
# Rueckweg ist dann nicht moeglich. Zurueckgenommen wird ganz /srv - also auch die gerenderte Compose
# mit dem alten Image-Tag. Deshalb startet die Instanz danach von selbst wieder auf dem alten Stand.
set -u
echo "ESPO-12-Snapshot-wiederherstellen, Skriptstand 2026-09-24"
VG=ubuntu-vg
SNAPSHOT=srv-vor-update
COMPOSE=/srv/espo/docker-compose.yml
WARTE_MAX=900
fehler() { echo "FEHLER: $*"; echo "ESPO12_ERGEBNIS: FEHLER"; exit 1; }
# Bringt den Dienst wieder hoch, wenn der Rueckweg abgebrochen wird - eine stehende Instanz
# ist das schlechteste aller Ergebnisse.
dienst_zurueck() {
mountpoint -q /srv || mount /srv 2>/dev/null || true
[ -f "$COMPOSE" ] && docker compose -f "$COMPOSE" up -d --quiet-pull >/dev/null 2>&1 || true
}
# 1. Vorbedingungen.
[ "$(id -u)" -eq 0 ] || fehler "nicht als root gestartet"
command -v lvconvert >/dev/null || fehler "LVM-Werkzeuge fehlen"
command -v docker >/dev/null && docker info >/dev/null 2>&1 || fehler "Docker laeuft nicht"
# 2. Der Snapshot muss da und gueltig sein. Ein 'I' im Attributfeld heisst vollgelaufen und verworfen -
# dann traegt der Rueckweg nicht mehr, und ein Versuch waere schlimmer als ein ehrlicher Abbruch.
lvs --noheadings -o lv_name "$VG" 2>/dev/null | grep -qw "$SNAPSHOT" \
|| fehler "kein Snapshot '$SNAPSHOT' vorhanden - es gibt nichts zurueckzunehmen"
ATTR="$(lvs --noheadings -o lv_attr "$VG/$SNAPSHOT" 2>/dev/null | tr -d ' ')"
case "$ATTR" in
*I*) fehler "Snapshot '$SNAPSHOT' ist ungueltig (vollgelaufen) - der Rueckweg traegt nicht mehr" ;;
esac
echo "--- Snapshot"
lvs -o lv_name,lv_attr,origin,lv_size,data_percent "$VG/$SNAPSHOT" 2>/dev/null | sed 's/^/ /'
# 3. Stack anhalten. Solange Container laufen, haelt Docker /srv offen.
echo "--- Stack anhalten"
docker compose -f "$COMPOSE" down 2>&1 | tail -n 5
# 4. /srv aushaengen. Ist der Ursprung geoeffnet, verschiebt LVM das Zusammenfuehren auf die naechste
# Aktivierung - also auf einen Neustart. Wir wollen es hier, jetzt und nachpruefbar.
if ! umount /srv 2>/dev/null; then
echo "--- /srv ist belegt von:"
{ command -v fuser >/dev/null && fuser -vm /srv 2>&1 | head -n 20; } || echo " (fuser nicht verfuegbar)"
dienst_zurueck
fehler "/srv liess sich nicht aushaengen - es wurde nichts zurueckgenommen, der Dienst laeuft wieder"
fi
# 5. Zusammenfuehren.
if ! lvconvert --merge "$VG/$SNAPSHOT" >/dev/null 2>&1; then
dienst_zurueck
fehler "Zusammenfuehren fehlgeschlagen - Stand unveraendert, der Dienst laeuft wieder"
fi
echo "Snapshot zusammengefuehrt - /srv steht auf dem Stand vor dem Update."
# 5b. Nachweis: Beim Zusammenfuehren verbraucht LVM den Snapshot, er verschwindet also. Bleibt er stehen,
# hat LVM das Zusammenfuehren auf die naechste Aktivierung verschoben - dann ist /srv noch NICHT zurueck.
if lvs --noheadings -o lv_name "$VG" 2>/dev/null | grep -qw "$SNAPSHOT"; then
echo "HINWEIS: '$SNAPSHOT' besteht noch - LVM hat das Zusammenfuehren verschoben."
echo " Der Stand ist erst nach dem naechsten Neustart zurueckgenommen."
else
echo "Snapshot '$SNAPSHOT' ist verbraucht und nicht mehr vorhanden."
fi
# 6. Wieder einhaengen und mit der ebenfalls zurueckgenommenen Compose starten.
mount /srv || fehler "/srv liess sich nicht wieder einhaengen - Handarbeit noetig"
[ -f "$COMPOSE" ] || fehler "$COMPOSE fehlt nach dem Zurueckrollen - Handarbeit noetig"
START_AUSGABE="$(docker compose -f "$COMPOSE" up -d --quiet-pull 2>&1)" || {
echo "$START_AUSGABE" | tail -n 20
fehler "Start nach dem Zurueckrollen fehlgeschlagen"
}
# 7. Auf die Anwendung warten.
ENDE=$(( SECONDS + WARTE_MAX ))
while [ "$SECONDS" -lt "$ENDE" ]; do
[ "$(docker inspect -f '{{.State.Health.Status}}' espocrm 2>/dev/null)" = "healthy" ] && break
sleep 10
done
[ "$(docker inspect -f '{{.State.Health.Status}}' espocrm 2>/dev/null)" = "healthy" ] \
|| fehler "espocrm nach ${WARTE_MAX}s nicht gesund - 'docker logs espocrm' ansehen"
# 8. Ergebnis zeigen.
echo "--- Container"
docker compose -f "$COMPOSE" ps --format 'table {{.Name}}\t{{.Status}}'
echo "--- Instanz nach dem Rueckweg"
IMAGE="$(docker inspect -f '{{.Config.Image}}' espocrm 2>/dev/null)"
echo "Image: $IMAGE"
echo "Version: $(docker exec espocrm php -r '$v=""; foreach (["/var/www/html/application/Espo/Resources/defaults/config.php","/var/www/html/data/config.php","/var/www/html/data/config-internal.php"] as $f) { $a=@include $f; if (is_array($a) && !empty($a["version"])) { $v=$a["version"]; } } echo $v;' 2>/dev/null)"
echo "--- Platz"
vgs --units g -o vg_name,vg_size,vg_free "$VG" 2>/dev/null | sed 's/^/ /'
echo "--- Hinweis"
echo "Der Snapshot ist verbraucht. Ein erneuter Rueckweg ist erst nach einem neuen ESPO-10 moeglich."
echo "Ursache des gescheiterten Updates klaeren, bevor es wiederholt wird."
echo "ESPO12_ERGEBNIS: OK"