Die berechnete Fenstergroesse galt bisher nur fuer die Dialoge, die ich
dafuer einzeln angefasst hatte. Eine Pruefung des ganzen Projekts zeigte
zwei Luecken:
* in common.sh gab es neun verstreute Aufrufstellen von dialog/whiptail
* migrate_creator.sh hatte noch durchgehend feste Groessen
(20 76 11, 10 76, 18 76, 14 76, 22 78, 8 76)
Beide Skripte rufen dialog/whiptail jetzt nur noch ueber drei Stellen auf:
_ui_list Listenfenster (menu, checklist, radiolist)
_ui_box Textfenster (msgbox, yesno, inputbox, passwordbox, infobox)
_ui_file Dateianzeige (textbox)
Die berechnen die Groesse selbst. Damit stimmt sie auch fuer Fenster, die
spaeter dazukommen - man muss nur eine der ui_*-Huellen benutzen.
Neu: "cmk-manage.sh selftest" haelt das nach. Geprueft werden Syntax
aller vier Skripte, Dialoge an den Engstellen vorbei, fest eingetragene
Fenstergroessen, das Muster "[ ... ] && VAR=..." und die Vollstaendigkeit
der Einstellungstabelle gegenueber .env.example.
Der Lauf fand sofort 19 Altlasten des Musters "[ ... ] && VAR=...", das
hier schon dreimal einen stillen Abbruch verursacht hat - alle in
if-Bloecke umgeschrieben und stichprobenartig geprueft, auch die Faelle
mit case-Abschluss und Array-Zuweisung. Danach laeuft die Selbstpruefung
vollstaendig durch.
Regression: alle CLI-Kommandos, zwoelf Menuefunktionen und das Rendern
von sechs Fenstern unter whiptail in einem echten Pseudo-Terminal.
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
|
|
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
|