Erkennen verhindert hat
Der Pull meldete "manifest unknown". Das heisst, anders als zuvor: der
Repository-Pfad registry.checkmk.com/enterprise/check-mk-enterprise ist
richtig und die Anmeldung auch - nur das Tag 2.4.0p9 gibt es dort nicht.
Neu "image why [REF]" unterscheidet die drei Faelle anhand der Registry
statt anhand der Fehlermeldung:
401/403 Anmeldung oder Berechtigung
404 Repository gibt es nicht -> image repos
Tag Repository ja, Tag nein -> vorhandene Tags des
Zweigs werden aufgelistet
"up" ruft das von selbst auf, wenn das Starten scheitert und das Image
nicht lokal vorliegt; "image pull" ebenfalls.
Beim Bauen stellte sich heraus, dass die Tag-Pruefung immer "nicht
vorhanden" meldete - auch fuer Tags, die es gibt. Ursache ist eine
Falle, die das ganze Projekt betraf:
printf ... | grep -q muster
"grep -q" endet beim ersten Treffer. Der Erzeuger bekommt dann SIGPIPE,
und unter "set -o pipefail" gilt die ganze Pipe als fehlgeschlagen -
aber nur, wenn er noch am Schreiben war. Bei drei Zeilen faellt das nie
auf, bei 2393 Tags immer. Nachgestellt:
set -euo pipefail; seq 1 500000 | grep -qx 3 -> schlaegt fehl
Betroffen waren zwoelf Stellen, darunter zwei, die ernster sind als die
Tag-Liste: bundle_read prueft mit "tar -tzf ... | grep -qx", ob ein
Backup ein Bundle ist. Bei einem grossen Archiv haette ein gueltiges
Bundle als "kein Bundle" gegolten - also ein stiller Fehler bei Restore
und Import genau dann, wenn das Backup gross ist. Alle zwoelf laufen
jetzt in einer Subshell ohne pipefail.
Der Selbsttest hat dafuer eine eigene Pruefung bekommen, damit die
Schreibweise nicht zurueckkehrt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
472 lines
19 KiB
Bash
Executable File
472 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =====================================================================
|
|
# migrate_creator.sh
|
|
#
|
|
# Wird auf den QUELLSERVER kopiert (klassische Checkmk-/OMD-Direkt-
|
|
# installation auf Bare-Metal oder VM) und dort als root ausgefuehrt.
|
|
#
|
|
# Aufgabe: eine oder mehrere Sites auswaehlen und daraus ein Migrations-
|
|
# Bundle (.tar.gz) erzeugen, das auf dem Zielsystem mit
|
|
# ./scripts/cmk-manage.sh import --file <bundle>
|
|
# in den Checkmk-Container uebernommen wird.
|
|
#
|
|
# Die Agents muessen dabei NICHT neu eingerichtet werden, solange
|
|
# * der Site-Name unveraendert bleibt und
|
|
# * das Zielsystem dieselbe IP-Adresse / denselben DNS-Namen bekommt.
|
|
# Die Site-Zertifikate (Agent-Registrierung) sind im omd-Backup enthalten.
|
|
#
|
|
# Dieses Skript ist bewusst eigenstaendig - es hat ausser bash, tar und
|
|
# omd keine Abhaengigkeiten. Fuer die Oberflaeche wird dialog oder
|
|
# whiptail genutzt, falls vorhanden.
|
|
# =====================================================================
|
|
set -euo pipefail
|
|
|
|
VERSION="1.0"
|
|
BUNDLE_DIRNAME="cmkbundle"
|
|
OUT_DIR="${PWD}"
|
|
declare -a SITES=()
|
|
ALL=""; STOP_SITE=""; ASSUME_YES=""; USE_GUI=""; SCP_TARGET=""; LABEL=""
|
|
declare -a OMD_OPTS=()
|
|
|
|
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
|
|
C_RED=$'\033[31m'; C_GRN=$'\033[32m'; C_YEL=$'\033[33m'
|
|
C_BLU=$'\033[34m'; C_BLD=$'\033[1m'; C_RST=$'\033[0m'
|
|
else
|
|
C_RED=; C_GRN=; C_YEL=; C_BLU=; C_BLD=; C_RST=
|
|
fi
|
|
log() { printf '%s[ INFO ]%s %s\n' "$C_BLU" "$C_RST" "$*"; }
|
|
ok() { printf '%s[ OK ]%s %s\n' "$C_GRN" "$C_RST" "$*"; }
|
|
warn() { printf '%s[ WARN ]%s %s\n' "$C_YEL" "$C_RST" "$*" >&2; }
|
|
err() { printf '%s[FEHLER]%s %s\n' "$C_RED" "$C_RST" "$*" >&2; }
|
|
die() { err "$*"; exit 1; }
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
migrate_creator.sh - Migrations-Bundle einer Checkmk-Direktinstallation erzeugen
|
|
|
|
AUFRUF
|
|
migrate_creator.sh [Optionen]
|
|
|
|
OPTIONEN
|
|
-l, --list vorhandene Sites anzeigen und beenden
|
|
-s, --site SITE Site auswaehlen (mehrfach angebbar)
|
|
-a, --all alle Sites sichern
|
|
-o, --out VERZEICHNIS Zielverzeichnis fuer die .tar.gz-Bundles (Vorgabe: aktuelles)
|
|
--label TEXT Freitext-Kennzeichnung im Dateinamen
|
|
--no-rrds Performance-Daten (RRDs) auslassen -> kleineres Archiv
|
|
--no-logs Logdateien auslassen
|
|
--stop Site waehrend des Backups stoppen (konsistenteste Variante)
|
|
--scp ZIEL Bundle anschliessend per scp uebertragen,
|
|
z.B. --scp root@10.0.0.5:/opt/checkmk-stack/backups/
|
|
-g, --gui ncurses-Oberflaeche (dialog/whiptail)
|
|
-y, --yes keine Rueckfragen
|
|
-h, --help diese Hilfe
|
|
|
|
BEISPIELE
|
|
./migrate_creator.sh --list
|
|
./migrate_creator.sh --gui
|
|
./migrate_creator.sh --site prod --stop --out /var/tmp
|
|
./migrate_creator.sh --all --no-logs --scp root@10.0.0.5:/opt/checkmk-stack/backups/
|
|
EOF
|
|
}
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Hilfsfunktionen
|
|
# ---------------------------------------------------------------------
|
|
human_size() {
|
|
local b="${1:-0}"
|
|
if [ "$b" -ge 1073741824 ] 2>/dev/null; then awk -v b="$b" 'BEGIN{printf "%.1f GiB", b/1073741824}'
|
|
elif [ "$b" -ge 1048576 ] 2>/dev/null; then awk -v b="$b" 'BEGIN{printf "%.1f MiB", b/1048576}'
|
|
elif [ "$b" -ge 1024 ] 2>/dev/null; then awk -v b="$b" 'BEGIN{printf "%.1f KiB", b/1024}'
|
|
else echo "${b} B"; fi
|
|
}
|
|
file_size() { stat -c %s "$1" 2>/dev/null || echo 0; }
|
|
confirm() {
|
|
[ -n "$ASSUME_YES" ] && return 0
|
|
local a; read -r -p "${1:-Fortfahren?} [j/N] " a </dev/tty || return 1
|
|
case "$a" in [jJyY]*) return 0 ;; *) return 1 ;; esac
|
|
}
|
|
primary_ip() {
|
|
ip -4 route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src"){print $(i+1);exit}}' \
|
|
|| hostname -I 2>/dev/null | awk '{print $1}'
|
|
}
|
|
all_ips() { hostname -I 2>/dev/null | tr ' ' '\n' | sed '/^$/d' | paste -sd, - ; }
|
|
|
|
list_sites() { ls -1 /omd/sites 2>/dev/null | sed '/^$/d'; }
|
|
site_version(){ omd version -b "$1" 2>/dev/null | tr -d '\r'; }
|
|
site_state() { local rc=0; omd status --bare "$1" >/dev/null 2>&1 || rc=$?
|
|
case "$rc" in 0) echo laeuft ;; 1) echo teilweise ;; *) echo gestoppt ;; esac; }
|
|
site_size() { du -sb "/omd/sites/$1" 2>/dev/null | awk '{print $1}'; }
|
|
|
|
# ---------------------------------------------------------------------
|
|
# TUI-Helfer
|
|
# ---------------------------------------------------------------------
|
|
ui_init() {
|
|
if command -v dialog >/dev/null 2>&1; then UI_BIN=dialog
|
|
elif command -v whiptail >/dev/null 2>&1; then UI_BIN=whiptail
|
|
else UI_BIN=""; fi
|
|
UI_BACKTITLE="migrate_creator $VERSION - $(hostname)"
|
|
}
|
|
# --- Fenstergroesse berechnen ----------------------------------------
|
|
# Wie im Hauptskript: die Groesse ergibt sich aus Terminal, Textlaenge
|
|
# und Anzahl der Eintraege. Feste Werte fuehrten bei langem Text dazu,
|
|
# dass von der Auswahlliste nur noch eine Zeile sichtbar war.
|
|
# Hier bewusst mit if-Bloecken statt "[ ... ] && VAR=..." - letzteres
|
|
# liefert 1, wenn die Bedingung nicht zutrifft, und beendet unter
|
|
# "set -e" die Funktion.
|
|
ui_term_size() {
|
|
UI_ROWS="$(tput lines 2>/dev/null || true)"
|
|
UI_COLS="$(tput cols 2>/dev/null || true)"
|
|
case "$UI_ROWS" in ''|*[!0-9]*) UI_ROWS=24 ;; esac
|
|
case "$UI_COLS" in ''|*[!0-9]*) UI_COLS=80 ;; esac
|
|
if [ "$UI_ROWS" -lt 10 ]; then UI_ROWS=24; fi
|
|
if [ "$UI_COLS" -lt 40 ]; then UI_COLS=80; fi
|
|
return 0
|
|
}
|
|
|
|
ui_calc() { # text felder_je_eintrag eintraege...
|
|
local text="$1" per="$2"; shift 2
|
|
ui_term_size
|
|
local tl maxw
|
|
tl="$(printf '%s\n' "$text" | wc -l)"
|
|
maxw="$(printf '%s\n' "$text" | awk '{ if (length($0) > m) m = length($0) } END { print m+0 }')"
|
|
local -a args=("$@")
|
|
local i=0 w itemw=0 n=0
|
|
while [ "$i" -lt "${#args[@]}" ]; do
|
|
w=$(( ${#args[$i]} + 4 ))
|
|
if [ $((i+1)) -lt "${#args[@]}" ]; then w=$(( w + ${#args[$((i+1))]} )); fi
|
|
if [ "$w" -gt "$itemw" ]; then itemw="$w"; fi
|
|
i=$(( i + per )); n=$(( n + 1 ))
|
|
done
|
|
if [ "$maxw" -gt "$itemw" ]; then UI_W=$(( maxw + 10 )); else UI_W=$(( itemw + 10 )); fi
|
|
if [ "$UI_W" -lt 60 ]; then UI_W=60; fi
|
|
if [ "$UI_W" -gt $(( UI_COLS - 4 )) ]; then UI_W=$(( UI_COLS - 4 )); fi
|
|
local avail=$(( UI_ROWS - tl - 9 ))
|
|
if [ "$avail" -lt 3 ]; then avail=3; fi
|
|
if [ "$n" -lt "$avail" ]; then UI_MH="$n"; else UI_MH="$avail"; fi
|
|
if [ "$UI_MH" -lt 1 ]; then UI_MH=1; fi
|
|
UI_H=$(( tl + UI_MH + 8 ))
|
|
if [ "$UI_H" -gt $(( UI_ROWS - 2 )) ]; then UI_H=$(( UI_ROWS - 2 )); fi
|
|
if [ "$UI_H" -lt 10 ]; then UI_H=10; fi
|
|
return 0
|
|
}
|
|
|
|
ui_calc_text() { # text zusatzzeilen
|
|
local text="$1" extra="${2:-7}"
|
|
ui_term_size
|
|
local tl maxw
|
|
tl="$(printf '%s\n' "$text" | wc -l)"
|
|
maxw="$(printf '%s\n' "$text" | awk '{ if (length($0) > m) m = length($0) } END { print m+0 }')"
|
|
UI_W=$(( maxw + 10 ))
|
|
if [ "$UI_W" -lt 60 ]; then UI_W=60; fi
|
|
if [ "$UI_W" -gt $(( UI_COLS - 4 )) ]; then UI_W=$(( UI_COLS - 4 )); fi
|
|
UI_H=$(( tl + extra ))
|
|
if [ "$UI_H" -gt $(( UI_ROWS - 2 )) ]; then UI_H=$(( UI_ROWS - 2 )); fi
|
|
if [ "$UI_H" -lt 8 ]; then UI_H=8; fi
|
|
return 0
|
|
}
|
|
|
|
# --- Engstellen: hierueber laufen ALLE Dialoge ------------------------
|
|
_ui_list() { # widget titel text felder_je_eintrag eintraege...
|
|
local widget="$1" t="$2" x="$3" per="$4"; shift 4
|
|
ui_calc "$x" "$per" "$@"
|
|
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$t" \
|
|
"$widget" "$x" "$UI_H" "$UI_W" "$UI_MH" "$@" 3>&1 1>&2 2>&3
|
|
}
|
|
_ui_box() { # widget titel text zusatzzeilen [weitere]
|
|
local widget="$1" t="$2" x="$3" extra="$4"; shift 4
|
|
ui_calc_text "$x" "$extra"
|
|
case "$widget" in
|
|
--inputbox|--passwordbox)
|
|
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$t" \
|
|
"$widget" "$x" "$UI_H" "$UI_W" "$@" 3>&1 1>&2 2>&3 ;;
|
|
*) "$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$t" \
|
|
"$widget" "$x" "$UI_H" "$UI_W" "$@" ;;
|
|
esac
|
|
}
|
|
_ui_file() { # titel datei
|
|
ui_term_size
|
|
"$UI_BIN" --backtitle "$UI_BACKTITLE" --title "$1" --textbox "$2" \
|
|
$(( UI_ROWS - 2 )) $(( UI_COLS - 4 ))
|
|
}
|
|
|
|
ui_menu() { local t="$1" x="$2"; shift 2; _ui_list --menu "$t" "$x" 2 "$@"; }
|
|
ui_checklist() { local t="$1" x="$2"; shift 2; _ui_list --checklist "$t" "$x" 3 "$@"; }
|
|
ui_input() { _ui_box --inputbox "$1" "$2" 10 "${3:-}"; }
|
|
ui_msg() { _ui_box --msgbox "$1" "$2" 7; }
|
|
ui_yesno() { _ui_box --yesno "$1" "$2" 8; }
|
|
ui_info() { _ui_box --infobox "$1" "$2" 5; }
|
|
ui_text() { _ui_file "$1" "$2"; }
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Bundle erzeugen
|
|
# ---------------------------------------------------------------------
|
|
create_bundle() {
|
|
local site="$1"
|
|
local version state ts outfile tmp restarted="" sum size
|
|
|
|
version="$(site_version "$site")"
|
|
[ -n "$version" ] || die "Konnte die Version der Site '$site' nicht ermitteln."
|
|
state="$(site_state "$site")"
|
|
ts="$(date +%Y%m%d-%H%M%S)"
|
|
outfile="$OUT_DIR/cmkmigrate_${site}_${version}${LABEL:+_$LABEL}_${ts}.tar.gz"
|
|
|
|
log "Site '$site' Version $version Status $state Groesse $(human_size "$(site_size "$site")")"
|
|
|
|
if [ -n "$STOP_SITE" ] && [ "$state" != "gestoppt" ]; then
|
|
log "Stoppe Site '$site' ..."
|
|
omd stop "$site" >/dev/null
|
|
restarted=1
|
|
fi
|
|
|
|
tmp="$(mktemp -d)"
|
|
mkdir -p "$tmp/$BUNDLE_DIRNAME/siteinfo"
|
|
|
|
log "Erzeuge omd-Backup ${OMD_OPTS[*]+(${OMD_OPTS[*]})} - das kann dauern ..."
|
|
if ! omd backup ${OMD_OPTS[@]+"${OMD_OPTS[@]}"} "$site" "$tmp/$BUNDLE_DIRNAME/site.tar.gz"; then
|
|
[ -n "$restarted" ] && omd start "$site" >/dev/null || true
|
|
rm -rf "$tmp"
|
|
die "omd backup der Site '$site' ist fehlgeschlagen."
|
|
fi
|
|
|
|
if [ -n "$restarted" ]; then
|
|
log "Starte Site '$site' wieder ..."
|
|
omd start "$site" >/dev/null || warn "Site '$site' konnte nicht wieder gestartet werden."
|
|
fi
|
|
|
|
# --- Zusatzinformationen (rein informativ, fuer die Nachkontrolle) ---
|
|
omd config "$site" show >"$tmp/$BUNDLE_DIRNAME/siteinfo/omd-config.txt" 2>/dev/null || true
|
|
omd status --bare "$site" >"$tmp/$BUNDLE_DIRNAME/siteinfo/omd-status.txt" 2>/dev/null || true
|
|
ip -4 addr show >"$tmp/$BUNDLE_DIRNAME/siteinfo/ip-addr.txt" 2>/dev/null || true
|
|
{
|
|
echo "hostname : $(hostname -f 2>/dev/null || hostname)"
|
|
echo "ips : $(all_ips)"
|
|
echo "kernel : $(uname -r)"
|
|
[ -r /etc/os-release ] && (. /etc/os-release && echo "os : $PRETTY_NAME")
|
|
echo "omd sites:"; omd sites 2>/dev/null || true
|
|
} >"$tmp/$BUNDLE_DIRNAME/siteinfo/system.txt"
|
|
# Anzahl registrierter Agent-Verbindungen (nur zur Kontrolle nach dem Import)
|
|
if [ -d "/omd/sites/$site/var/agent-receiver" ]; then
|
|
find "/omd/sites/$site/var/agent-receiver" -maxdepth 2 -type d 2>/dev/null \
|
|
| wc -l >"$tmp/$BUNDLE_DIRNAME/siteinfo/agent-receiver-entries.txt" || true
|
|
fi
|
|
|
|
sum="$(sha256sum "$tmp/$BUNDLE_DIRNAME/site.tar.gz" | awk '{print $1}')"
|
|
size="$(file_size "$tmp/$BUNDLE_DIRNAME/site.tar.gz")"
|
|
printf '%s site.tar.gz\n' "$sum" >"$tmp/$BUNDLE_DIRNAME/site.tar.gz.sha256"
|
|
|
|
cat >"$tmp/$BUNDLE_DIRNAME/MANIFEST" <<EOF
|
|
BUNDLE_VERSION=1
|
|
BUNDLE_TYPE=migrate
|
|
SITE=$site
|
|
CMK_VERSION=$version
|
|
SOURCE_KIND=baremetal
|
|
SOURCE_HOST=$(hostname -f 2>/dev/null || hostname)
|
|
SOURCE_IP=$(primary_ip)
|
|
SOURCE_IPS=$(all_ips)
|
|
SOURCE_OS=$( [ -r /etc/os-release ] && (. /etc/os-release && echo "$PRETTY_NAME") || echo unbekannt )
|
|
CREATED=$(date -Is)
|
|
CREATED_BY=migrate_creator.sh/$VERSION
|
|
ARCHIVE=site.tar.gz
|
|
ARCHIVE_SHA256=$sum
|
|
ARCHIVE_SIZE=$size
|
|
OMD_BACKUP_OPTS=${OMD_OPTS[*]-}
|
|
LABEL=$LABEL
|
|
SITE_STOPPED_DURING_BACKUP=$([ -n "$STOP_SITE" ] && echo yes || echo no)
|
|
AGENT_RECEIVER_PORT=8000
|
|
EOF
|
|
|
|
cat >"$tmp/$BUNDLE_DIRNAME/INFO.txt" <<EOF
|
|
Checkmk Migrations-Bundle
|
|
=========================
|
|
Site : $site
|
|
Checkmk-Version : $version
|
|
Quellserver : $(hostname -f 2>/dev/null || hostname)
|
|
Quell-IP(s) : $(all_ips)
|
|
Erstellt : $(date -Is)
|
|
Nutzdaten : site.tar.gz ($(human_size "$size"))
|
|
SHA256 : $sum
|
|
|
|
Import auf dem Zielsystem (Container-Installation):
|
|
1) Bundle in das Verzeichnis ./backups des Projekts kopieren
|
|
2) Passendes Image beschaffen (Version MUSS uebereinstimmen):
|
|
./scripts/cmk-manage.sh image pull --edition $(
|
|
case "$version" in
|
|
*.cre) echo raw ;;
|
|
*.cee) echo enterprise ;;
|
|
*.cce) echo cloud ;;
|
|
*.cme) echo managed ;;
|
|
*) echo raw ;;
|
|
esac) --version ${version%.*}
|
|
Die Enterprise-Edition liegt NICHT auf Docker Hub - dort zusaetzlich
|
|
--user/--password (Checkmk-Kundenportal) angeben oder
|
|
"image download" verwenden.
|
|
Danach: ./scripts/cmk-manage.sh up
|
|
3) Import ausfuehren:
|
|
./scripts/cmk-manage.sh import --file backups/$(basename "$outfile") --set-default-site
|
|
|
|
Damit die vorhandenen Agents ohne Neuinstallation weiterarbeiten:
|
|
* Der Site-Name muss "$site" bleiben (kein --as-site verwenden).
|
|
* Das Zielsystem muss die IP/den DNS-Namen des Quellservers uebernehmen.
|
|
* Port 8000 (Agent-Receiver) und 443/80 (Web) muessen erreichbar sein.
|
|
* Der alte Server sollte danach abgeschaltet bzw. dessen Site gestoppt werden.
|
|
EOF
|
|
|
|
log "Verpacke Bundle ..."
|
|
mkdir -p "$OUT_DIR"
|
|
tar -czf "$outfile" -C "$tmp" "$BUNDLE_DIRNAME"
|
|
rm -rf "$tmp"
|
|
|
|
ok "Bundle erstellt: $outfile ($(human_size "$(file_size "$outfile")"))"
|
|
LAST_BUNDLE="$outfile"
|
|
|
|
if [ -n "$SCP_TARGET" ]; then
|
|
log "Uebertrage per scp nach $SCP_TARGET ..."
|
|
scp "$outfile" "$SCP_TARGET" && ok "Uebertragung abgeschlossen." \
|
|
|| warn "scp fehlgeschlagen - bitte manuell kopieren."
|
|
fi
|
|
}
|
|
|
|
print_summary() {
|
|
cat <<EOF
|
|
|
|
${C_BLD}Weiteres Vorgehen${C_RST}
|
|
1) Bundle auf das Zielsystem kopieren, z.B.:
|
|
scp ${LAST_BUNDLE:-<bundle>} root@<ziel>:/opt/checkmk-stack/backups/
|
|
2) Dort importieren:
|
|
cd /opt/checkmk-stack
|
|
./scripts/cmk-manage.sh import --file backups/$(basename "${LAST_BUNDLE:-<bundle>}") --set-default-site
|
|
3) Quellserver: Site stoppen bzw. Server abschalten, damit es keine
|
|
doppelte Ueberwachung und keinen IP-Konflikt gibt:
|
|
omd stop <site> && omd disable ... / systemctl poweroff
|
|
4) Zielsystem auf die IP/den DNS-Namen des Quellservers umstellen -
|
|
dann melden sich die vorhandenen Agents unveraendert weiter.
|
|
|
|
EOF
|
|
}
|
|
|
|
# ---------------------------------------------------------------------
|
|
# GUI-Ablauf
|
|
# ---------------------------------------------------------------------
|
|
gui_main() {
|
|
ui_init
|
|
[ -n "$UI_BIN" ] || die "Fuer --gui wird 'dialog' oder 'whiptail' benoetigt.
|
|
Debian/Ubuntu : apt-get install -y dialog
|
|
RHEL/Rocky : dnf install -y dialog"
|
|
|
|
local -a items=() s
|
|
while IFS= read -r s; do
|
|
[ -n "$s" ] || continue
|
|
items+=("$s" "$(site_version "$s") | $(site_state "$s") | $(human_size "$(site_size "$s")")" off)
|
|
done < <(list_sites)
|
|
[ ${#items[@]} -gt 0 ] || die "Auf diesem System wurde keine OMD-Site gefunden."
|
|
|
|
ui_msg "Checkmk Migration" \
|
|
"Dieses Skript erzeugt aus einer Direktinstallation ein Migrations-Bundle
|
|
(.tar.gz) fuer den Import in eine Checkmk-Container-Installation.
|
|
|
|
Server : $(hostname -f 2>/dev/null || hostname)
|
|
IP(s) : $(all_ips)
|
|
Sites : $(list_sites | tr '\n' ' ')
|
|
|
|
Die Agents muessen spaeter NICHT neu eingerichtet werden, solange der
|
|
Site-Name gleich bleibt und das Zielsystem dieselbe IP uebernimmt."
|
|
|
|
local chosen
|
|
chosen="$(ui_checklist "Sites auswaehlen" "Mit LEERTASTE markieren, mit ENTER bestaetigen:" "${items[@]}")" || exit 0
|
|
[ -n "$chosen" ] || { ui_msg "Abbruch" "Es wurde keine Site ausgewaehlt."; exit 0; }
|
|
SITES=()
|
|
local x
|
|
for x in $(printf '%s' "$chosen" | tr -d '"'); do SITES+=("$x"); done
|
|
|
|
local opt
|
|
opt="$(ui_checklist "Optionen" "Optionen fuer das Backup:" \
|
|
stop "Site waehrend des Backups stoppen (empfohlen)" on \
|
|
no-rrds "Performance-Daten (RRD) auslassen" off \
|
|
no-logs "Logdateien auslassen" off)" || exit 0
|
|
case "$opt" in *stop*) STOP_SITE=1 ;; esac
|
|
case "$opt" in *no-rrds*) OMD_OPTS+=(--no-rrds) ;; esac
|
|
case "$opt" in *no-logs*) OMD_OPTS+=(--no-logs) ;; esac
|
|
|
|
OUT_DIR="$(ui_input "Zielverzeichnis" "Wohin sollen die Bundles geschrieben werden?" "${OUT_DIR}")" || exit 0
|
|
LABEL="$(ui_input "Kennzeichnung" "Optionaler Text fuer den Dateinamen (leer = keiner):" "")" || LABEL=""
|
|
LABEL="$(printf '%s' "$LABEL" | tr -cd 'A-Za-z0-9._-')"
|
|
|
|
if ui_yesno "Direkt uebertragen?" "Sollen die Bundles anschliessend per scp auf das Zielsystem kopiert werden?"; then
|
|
SCP_TARGET="$(ui_input "scp-Ziel" "Ziel angeben (Benutzer@Host:/Pfad/):" "root@zielserver:/opt/checkmk-stack/backups/")" || SCP_TARGET=""
|
|
fi
|
|
|
|
ui_yesno "Starten" "Jetzt Bundle(s) erzeugen fuer:\n\n ${SITES[*]}\n\nZiel: $OUT_DIR\n$([ -n "$STOP_SITE" ] && echo 'Die Site(s) werden dabei kurz gestoppt!')" || exit 0
|
|
|
|
local logf; logf="$(mktemp)"
|
|
clear
|
|
ASSUME_YES=1
|
|
local site
|
|
for site in "${SITES[@]}"; do
|
|
create_bundle "$site" 2>&1 | tee -a "$logf"
|
|
done
|
|
print_summary | tee -a "$logf" >/dev/null
|
|
ui_text "Fertig" "$logf"
|
|
rm -f "$logf"
|
|
print_summary
|
|
}
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Argumente
|
|
# ---------------------------------------------------------------------
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-l|--list) LIST_ONLY=1; shift ;;
|
|
-s|--site) SITES+=("$2"); shift 2 ;;
|
|
-a|--all) ALL=1; shift ;;
|
|
-o|--out) OUT_DIR="$2"; shift 2 ;;
|
|
--label) LABEL="$2"; shift 2 ;;
|
|
--no-rrds) OMD_OPTS+=(--no-rrds); shift ;;
|
|
--no-logs) OMD_OPTS+=(--no-logs); shift ;;
|
|
--stop) STOP_SITE=1; shift ;;
|
|
--scp) SCP_TARGET="$2"; shift 2 ;;
|
|
-g|--gui) USE_GUI=1; shift ;;
|
|
-y|--yes) ASSUME_YES=1; shift ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) die "Unbekannte Option: $1 (--help fuer Hilfe)" ;;
|
|
esac
|
|
done
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Vorbedingungen
|
|
# ---------------------------------------------------------------------
|
|
command -v omd >/dev/null 2>&1 \
|
|
|| die "Auf diesem System ist keine OMD-/Checkmk-Direktinstallation gefunden worden ('omd' fehlt)."
|
|
[ "$(id -u)" -eq 0 ] || die "Bitte als root ausfuehren (sudo $0 ...)."
|
|
|
|
if [ -n "${LIST_ONLY:-}" ]; then
|
|
printf '%-20s %-18s %-12s %s\n' "SITE" "VERSION" "STATUS" "GROESSE"
|
|
while IFS= read -r s; do
|
|
[ -n "$s" ] || continue
|
|
printf '%-20s %-18s %-12s %s\n' "$s" "$(site_version "$s")" "$(site_state "$s")" "$(human_size "$(site_size "$s")")"
|
|
done < <(list_sites)
|
|
exit 0
|
|
fi
|
|
|
|
if [ -n "$USE_GUI" ] || { [ ${#SITES[@]} -eq 0 ] && [ -z "$ALL" ] && [ -t 0 ]; }; then
|
|
gui_main
|
|
exit 0
|
|
fi
|
|
|
|
[ -n "$ALL" ] && mapfile -t SITES < <(list_sites)
|
|
[ ${#SITES[@]} -gt 0 ] || die "Keine Site angegeben. --site SITE, --all oder --gui verwenden."
|
|
|
|
for s in "${SITES[@]}"; do
|
|
( set +o pipefail; list_sites | grep -qxF "$s" ) || die "Site '$s' existiert auf diesem Server nicht."
|
|
done
|
|
|
|
printf '\n%sZu sichernde Sites:%s %s\n' "$C_BLD" "$C_RST" "${SITES[*]}"
|
|
printf '%sZielverzeichnis :%s %s\n\n' "$C_BLD" "$C_RST" "$OUT_DIR"
|
|
[ -n "$STOP_SITE" ] && warn "Die Site(s) werden waehrend des Backups gestoppt!"
|
|
confirm "Jetzt Migrations-Bundle(s) erzeugen?" || die "Abgebrochen."
|
|
|
|
for s in "${SITES[@]}"; do
|
|
create_bundle "$s"
|
|
done
|
|
print_summary
|