feat: add detection functions for native MariaDB port takeover
This commit is contained in:
+116
@@ -0,0 +1,116 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PLUGIN_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
COMMON_FILE="$SCRIPT_DIR/mysql_common.sh"
|
||||||
|
|
||||||
|
NATIVE_MY_CNF="${NATIVE_MY_CNF:-/etc/my.cnf}"
|
||||||
|
NATIVE_MY_CNF_D="${NATIVE_MY_CNF_D:-/etc/my.cnf.d}"
|
||||||
|
NATIVE_MYSQL_CONF="${NATIVE_MYSQL_CONF:-/usr/local/directadmin/conf/mysql.conf}"
|
||||||
|
CUSTOMBUILD_OPTIONS_CONF="${CUSTOMBUILD_OPTIONS_CONF:-/usr/local/directadmin/custombuild/options.conf}"
|
||||||
|
NEW_NATIVE_PORT="${NEW_NATIVE_PORT:-3307}"
|
||||||
|
DA_CLI_BIN="${DA_CLI_BIN:-da}"
|
||||||
|
OS_RELEASE_FILE="${OS_RELEASE_FILE:-/etc/os-release}"
|
||||||
|
|
||||||
|
LOG_FILE="${NATIVE_TAKEOVER_LOG:-$PLUGIN_DIR/data/logs/native-port-takeover.log}"
|
||||||
|
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true
|
||||||
|
|
||||||
|
log() {
|
||||||
|
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE"
|
||||||
|
printf '[INFO] %s\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
log "ERROR: $*"
|
||||||
|
printf '[BŁĄD] %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- state populated by the detection functions, consumed by later steps ---
|
||||||
|
NATIVE_CURRENT_PORT=""
|
||||||
|
NATIVE_CURRENT_SOCKET=""
|
||||||
|
NATIVE_CURRENT_HOST=""
|
||||||
|
NATIVE_CURRENT_USER=""
|
||||||
|
NATIVE_CURRENT_PASS=""
|
||||||
|
NATIVE_CURRENT_MYSQL_INST=""
|
||||||
|
|
||||||
|
require_root() {
|
||||||
|
[ "$(id -u)" -eq 0 ] || die "Ten skrypt musi zostać uruchomiony jako root."
|
||||||
|
}
|
||||||
|
|
||||||
|
check_os_guard() {
|
||||||
|
[ -r "$OS_RELEASE_FILE" ] || die "Nie można odczytać $OS_RELEASE_FILE."
|
||||||
|
local os_id="" os_version=""
|
||||||
|
os_id="$(awk -F= '$1=="ID"{gsub(/"/,"",$2); print $2}' "$OS_RELEASE_FILE")"
|
||||||
|
os_version="$(awk -F= '$1=="VERSION_ID"{gsub(/"/,"",$2); print $2}' "$OS_RELEASE_FILE")"
|
||||||
|
|
||||||
|
[ "$os_id" = "almalinux" ] || die "Ten skrypt obsługuje wyłącznie AlmaLinux 8/9 (wykryto: ${os_id:-nieznany})."
|
||||||
|
case "$os_version" in
|
||||||
|
8*|9*) ;;
|
||||||
|
*) die "Ten skrypt obsługuje wyłącznie AlmaLinux 8/9 (wykryto wersję: ${os_version:-nieznana})." ;;
|
||||||
|
esac
|
||||||
|
log "Wykryto obsługiwany system: AlmaLinux $os_version."
|
||||||
|
}
|
||||||
|
|
||||||
|
read_native_mysql_conf() {
|
||||||
|
[ -r "$NATIVE_MYSQL_CONF" ] || die "Nie znaleziono pliku $NATIVE_MYSQL_CONF."
|
||||||
|
NATIVE_CURRENT_USER="$(mysql_read_key_value "$NATIVE_MYSQL_CONF" user || true)"
|
||||||
|
NATIVE_CURRENT_PASS="$(mysql_read_key_value "$NATIVE_MYSQL_CONF" passwd || true)"
|
||||||
|
NATIVE_CURRENT_PORT="$(mysql_read_key_value "$NATIVE_MYSQL_CONF" port || true)"
|
||||||
|
NATIVE_CURRENT_SOCKET="$(mysql_read_key_value "$NATIVE_MYSQL_CONF" socket || true)"
|
||||||
|
NATIVE_CURRENT_HOST="$(mysql_read_key_value "$NATIVE_MYSQL_CONF" host || true)"
|
||||||
|
[ -n "$NATIVE_CURRENT_USER" ] || die "Nie udało się odczytać pola user z $NATIVE_MYSQL_CONF."
|
||||||
|
[ -n "$NATIVE_CURRENT_PORT" ] || die "Nie udało się odczytać pola port z $NATIVE_MYSQL_CONF."
|
||||||
|
}
|
||||||
|
|
||||||
|
read_current_mysql_inst() {
|
||||||
|
[ -r "$CUSTOMBUILD_OPTIONS_CONF" ] || die "Nie znaleziono pliku $CUSTOMBUILD_OPTIONS_CONF."
|
||||||
|
NATIVE_CURRENT_MYSQL_INST="$(mysql_read_key_value "$CUSTOMBUILD_OPTIONS_CONF" mysql_inst || true)"
|
||||||
|
[ -n "$NATIVE_CURRENT_MYSQL_INST" ] || die "Nie udało się odczytać mysql_inst z $CUSTOMBUILD_OPTIONS_CONF."
|
||||||
|
log "Bieżąca wartość mysql_inst: $NATIVE_CURRENT_MYSQL_INST."
|
||||||
|
}
|
||||||
|
|
||||||
|
already_migrated() {
|
||||||
|
[ "$NATIVE_CURRENT_PORT" != "3306" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
check_native_reachable() {
|
||||||
|
local bin
|
||||||
|
bin="$(mysql_detect_binary mysql)" || die "Nie znaleziono klienta mysql/mariadb do sprawdzenia natywnej instancji."
|
||||||
|
MYSQL_PWD="$NATIVE_CURRENT_PASS" "$bin" \
|
||||||
|
--user="$NATIVE_CURRENT_USER" \
|
||||||
|
--protocol=TCP --host=127.0.0.1 --port="$NATIVE_CURRENT_PORT" \
|
||||||
|
-e "SELECT 1" >/dev/null 2>>"$LOG_FILE" \
|
||||||
|
|| die "Natywna instancja MariaDB nie odpowiada na porcie $NATIVE_CURRENT_PORT z bieżącymi poświadczeniami."
|
||||||
|
log "Natywna instancja MariaDB odpowiada na porcie $NATIVE_CURRENT_PORT."
|
||||||
|
}
|
||||||
|
|
||||||
|
port_is_listening() {
|
||||||
|
local port="$1"
|
||||||
|
if command -v ss >/dev/null 2>&1; then
|
||||||
|
ss -ltn "( sport = :$port )" 2>/dev/null | awk 'NR > 1 { found=1 } END { exit !found }'
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
if command -v lsof >/dev/null 2>&1; then
|
||||||
|
lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
log "Nie znaleziono ss ani lsof - zakładam, że port $port jest wolny."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
preflight_new_port_free() {
|
||||||
|
if port_is_listening "$NEW_NATIVE_PORT"; then
|
||||||
|
die "Port $NEW_NATIVE_PORT jest już zajęty. Zmień NEW_NATIVE_PORT i spróbuj ponownie."
|
||||||
|
fi
|
||||||
|
log "Port docelowy $NEW_NATIVE_PORT jest wolny."
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -r "$COMMON_FILE" ] || die "missing helper: $COMMON_FILE"
|
||||||
|
# shellcheck source=./mysql_common.sh
|
||||||
|
source "$COMMON_FILE"
|
||||||
|
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
: # main() is added in Task 4.
|
||||||
|
fi
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PLUGIN_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
SCRIPT="$PLUGIN_DIR/scripts/setup/native_mariadb_port_takeover.sh"
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "FAIL: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Source only the detection functions, without triggering main() (main() is
|
||||||
|
# added in Task 4, guarded behind a BASH_SOURCE check).
|
||||||
|
NATIVE_TAKEOVER_LOG="$TMP_DIR/takeover.log" \
|
||||||
|
source "$SCRIPT"
|
||||||
|
|
||||||
|
# --- check_os_guard: AlmaLinux 9 must pass ---
|
||||||
|
cat > "$TMP_DIR/os-release-alma9" <<'EOF'
|
||||||
|
ID="almalinux"
|
||||||
|
VERSION_ID="9.4"
|
||||||
|
PRETTY_NAME="AlmaLinux 9.4"
|
||||||
|
EOF
|
||||||
|
OS_RELEASE_FILE="$TMP_DIR/os-release-alma9" check_os_guard \
|
||||||
|
|| fail "AlmaLinux 9 should pass the OS guard"
|
||||||
|
|
||||||
|
# --- check_os_guard: AlmaLinux 8 must pass ---
|
||||||
|
cat > "$TMP_DIR/os-release-alma8" <<'EOF'
|
||||||
|
ID="almalinux"
|
||||||
|
VERSION_ID="8.10"
|
||||||
|
EOF
|
||||||
|
OS_RELEASE_FILE="$TMP_DIR/os-release-alma8" check_os_guard \
|
||||||
|
|| fail "AlmaLinux 8 should pass the OS guard"
|
||||||
|
|
||||||
|
# --- check_os_guard: CloudLinux must be refused ---
|
||||||
|
cat > "$TMP_DIR/os-release-cloudlinux" <<'EOF'
|
||||||
|
ID="cloudlinux"
|
||||||
|
VERSION_ID="8.9"
|
||||||
|
ID_LIKE="rhel fedora centos"
|
||||||
|
EOF
|
||||||
|
if ( OS_RELEASE_FILE="$TMP_DIR/os-release-cloudlinux" check_os_guard 2>/dev/null ); then
|
||||||
|
fail "CloudLinux must be refused by the OS guard"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- check_os_guard: AlmaLinux 7 (out of supported range) must be refused ---
|
||||||
|
cat > "$TMP_DIR/os-release-alma7" <<'EOF'
|
||||||
|
ID="almalinux"
|
||||||
|
VERSION_ID="7.9"
|
||||||
|
EOF
|
||||||
|
if ( OS_RELEASE_FILE="$TMP_DIR/os-release-alma7" check_os_guard 2>/dev/null ); then
|
||||||
|
fail "AlmaLinux 7 must be refused by the OS guard (only 8/9 supported)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- read_native_mysql_conf + already_migrated ---
|
||||||
|
cat > "$TMP_DIR/mysql.conf.3306" <<'EOF'
|
||||||
|
user=da_admin
|
||||||
|
passwd=secret
|
||||||
|
port=3306
|
||||||
|
socket=/var/lib/mysql/mysql.sock
|
||||||
|
host=
|
||||||
|
EOF
|
||||||
|
NATIVE_MYSQL_CONF="$TMP_DIR/mysql.conf.3306" read_native_mysql_conf \
|
||||||
|
|| fail "read_native_mysql_conf should succeed on a valid mysql.conf"
|
||||||
|
[ "$NATIVE_CURRENT_USER" = "da_admin" ] || fail "expected user da_admin, got: $NATIVE_CURRENT_USER"
|
||||||
|
[ "$NATIVE_CURRENT_PORT" = "3306" ] || fail "expected port 3306, got: $NATIVE_CURRENT_PORT"
|
||||||
|
already_migrated && fail "already_migrated should be false when native port is still 3306"
|
||||||
|
|
||||||
|
cat > "$TMP_DIR/mysql.conf.3307" <<'EOF'
|
||||||
|
user=da_admin
|
||||||
|
passwd=secret
|
||||||
|
port=3307
|
||||||
|
socket=/var/lib/mysql/mysql.sock
|
||||||
|
host=
|
||||||
|
EOF
|
||||||
|
NATIVE_MYSQL_CONF="$TMP_DIR/mysql.conf.3307" read_native_mysql_conf \
|
||||||
|
|| fail "read_native_mysql_conf should succeed on an already-migrated mysql.conf"
|
||||||
|
already_migrated || fail "already_migrated should be true when native port is 3307"
|
||||||
|
|
||||||
|
# --- read_current_mysql_inst ---
|
||||||
|
cat > "$TMP_DIR/options.conf" <<'EOF'
|
||||||
|
mysql_inst=mariadb
|
||||||
|
mariadb=10.6
|
||||||
|
EOF
|
||||||
|
CUSTOMBUILD_OPTIONS_CONF="$TMP_DIR/options.conf" read_current_mysql_inst \
|
||||||
|
|| fail "read_current_mysql_inst should succeed"
|
||||||
|
[ "$NATIVE_CURRENT_MYSQL_INST" = "mariadb" ] || fail "expected mysql_inst=mariadb, got: $NATIVE_CURRENT_MYSQL_INST"
|
||||||
|
|
||||||
|
# --- preflight_new_port_free using a faked `ss` on PATH ---
|
||||||
|
mkdir -p "$TMP_DIR/bin"
|
||||||
|
cat > "$TMP_DIR/bin/ss" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
# Pretends port 3307 is free and port 9999 is occupied.
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
*:3307*) exit 0 ;;
|
||||||
|
*:9999*)
|
||||||
|
echo "header line"
|
||||||
|
echo "occupied line"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
STUB
|
||||||
|
chmod 755 "$TMP_DIR/bin/ss"
|
||||||
|
|
||||||
|
PATH="$TMP_DIR/bin:$PATH" NEW_NATIVE_PORT="3307" preflight_new_port_free \
|
||||||
|
|| fail "preflight_new_port_free should pass when the target port is free"
|
||||||
|
|
||||||
|
if ( PATH="$TMP_DIR/bin:$PATH" NEW_NATIVE_PORT="9999" preflight_new_port_free 2>/dev/null ); then
|
||||||
|
fail "preflight_new_port_free should refuse when the target port is already occupied"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "native_mariadb_port_takeover_detect_test: OK"
|
||||||
Reference in New Issue
Block a user