File: //bigscoots/wpo/db/zfs_mycnf_opt.sh
#!/bin/bash
# BigScoots Managed Infrastructure - ZFS Optimization Suite
# Version: 3.1 (Plan-Aware Pool Caps)
source /bigscoots/includes/common.sh
assert_lxd_plan
VTYPE=$(check_virt)
[[ "$VTYPE" != lxd-* ]] && echo "Not LXD, skipping." && exit 0
# Parse Flags
AUTO_RESTART=false
DRY_RUN=false
[[ "$*" == *"--yes"* ]] && AUTO_RESTART=true
[[ "$*" == *"--dry-run"* ]] && DRY_RUN=true
RESTART_REQUIRED=false
# 1. SYSTEMD PLUMBING (Idempotent Check)
DB_SERVICE=$(systemctl list-unit-files | grep -oE "mariadb.service|mysql.service" | head -n 1)
OVERRIDE_DIR="/etc/systemd/system/${DB_SERVICE}.d"
OVERRIDE_FILE="${OVERRIDE_DIR}/no-iouring.conf"
SYSTEMD_CONTENT="[Service]
# BigScoots Fix: Force MariaDB to bypass the buggy ZFS 2.2.2 io_uring path
SystemCallFilter=~io_uring_setup io_uring_enter io_uring_register"
mkdir -p "$OVERRIDE_DIR"
if [[ ! -f "$OVERRIDE_FILE" ]] || [[ "$(cat "$OVERRIDE_FILE")" != "$SYSTEMD_CONTENT" ]]; then
echo "Updating BigScoots Systemd Plumbing (io_uring filter)..."
echo "$SYSTEMD_CONTENT" > "$OVERRIDE_FILE"
systemctl daemon-reload
RESTART_REQUIRED=true
else
echo "Systemd Plumbing is already up to date."
fi
# 2. MYSQL DIRECTORY & INCLUDE CHECK
CONF_D="/etc/my.cnf.d"
MAIN_CONF="/etc/my.cnf"
mkdir -p "$CONF_D"
if ! grep -q "!includedir $CONF_D" "$MAIN_CONF"; then
echo -e "\n!includedir $CONF_D" >> "$MAIN_CONF"
RESTART_REQUIRED=true
fi
# 3. STATIC MYSQL PLUMBING (Idempotent Check)
PLUMBING_FILE="$CONF_D/01-bigscoots-plumbing.cnf"
TUNING_FILE="$CONF_D/02-bigscoots-tuning.cnf"
PLUMBING_CONTENT="# BigScoots Static ZFS Optimization - Fixed Plumbing
[mysqld]
innodb_use_native_aio = 0
innodb_doublewrite = 0
innodb_flush_method = fsync
innodb_flush_log_at_trx_commit = 0
innodb_flush_neighbors = 0
innodb_adaptive_hash_index = 0
innodb_log_write_ahead_size = 16384
optimizer_search_depth = 0
wait_timeout = 30
interactive_timeout = 28800
connect_timeout = 5"
if [[ ! -f "$PLUMBING_FILE" ]] || [[ "$(cat "$PLUMBING_FILE")" != "$PLUMBING_CONTENT" ]]; then
echo "Updating BigScoots Static MariaDB Plumbing..."
echo "$PLUMBING_CONTENT" > "$PLUMBING_FILE"
RESTART_REQUIRED=true
else
echo "Static Plumbing is already up to date."
fi
# 4. PLAN DETECTION
# Read plan from LXD guest API (set via: lxc config set <container> user.plan <plan>)
# Falls back to wpo-starter if not set
LXD_PLAN=$(curl -sf --unix-socket /dev/lxd/sock http://lxd/1.0/config/user.plan 2>/dev/null | tr -d '"' || echo "")
[[ -z "$LXD_PLAN" ]] && LXD_PLAN="wpo-starter"
# Plan-based pool caps and minimums
case "$LXD_PLAN" in
wpo-starter)
PLAN_POOL_CAP_MB=1024
PLAN_POOL_MIN_MB=128
;;
wpo-pro)
PLAN_POOL_CAP_MB=2048
PLAN_POOL_MIN_MB=512
;;
wpo-business)
PLAN_POOL_CAP_MB=4096
PLAN_POOL_MIN_MB=1024
;;
wpo-enterprise)
PLAN_POOL_CAP_MB=8192
PLAN_POOL_MIN_MB=2048
;;
mwp-essential75)
PLAN_POOL_CAP_MB=1024
PLAN_POOL_MIN_MB=128
;;
mwp-essential125)
PLAN_POOL_CAP_MB=1024
PLAN_POOL_MIN_MB=256
;;
mwp-essential200)
PLAN_POOL_CAP_MB=2048
PLAN_POOL_MIN_MB=512
;;
mwp-essential300)
PLAN_POOL_CAP_MB=2048
PLAN_POOL_MIN_MB=512
;;
mwp-core500)
PLAN_POOL_CAP_MB=3072
PLAN_POOL_MIN_MB=512
;;
mwp-core1000)
PLAN_POOL_CAP_MB=4096
PLAN_POOL_MIN_MB=1024
;;
*)
# Unknown plan - use conservative starter limits
PLAN_POOL_CAP_MB=1024
PLAN_POOL_MIN_MB=128
;;
esac
# 5. DYNAMIC CALCULATION LOGIC
echo "----------------------------------------------------"
echo " BigScoots Dynamic Scaling Calculation "
echo " Plan: $LXD_PLAN | Cap: ${PLAN_POOL_CAP_MB}MB | Min: ${PLAN_POOL_MIN_MB}MB"
echo "----------------------------------------------------"
TOTAL_RAM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}')
PAGE_SIZE=$(mysql -N -e "SELECT @@innodb_page_size;" 2>/dev/null || echo 16384)
CURRENT_POOL_BYTES=$(mysql -N -e "SELECT @@innodb_buffer_pool_size;" 2>/dev/null || echo 134217728)
CURRENT_MAX_CONN=$(mysql -N -e "SELECT @@max_connections;" 2>/dev/null || echo 100)
PEAK_CONN=$(mysql -N -e "SHOW GLOBAL STATUS LIKE 'Max_used_connections';" 2>/dev/null | awk '{print $2}' || echo 0)
CURRENT_POOL_MB=$(( CURRENT_POOL_BYTES / 1024 / 1024 ))
PAGES_DATA=$(mysql -N -e "SELECT VARIABLE_VALUE FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'INNODB_BUFFER_POOL_PAGES_DATA';" 2>/dev/null || echo 0)
ACTUAL_DATA_MB=$(( PAGES_DATA * PAGE_SIZE / 1024 / 1024 ))
# Pool Logic - data-driven, capped by plan
if [[ "$ACTUAL_DATA_MB" -ge $(( CURRENT_POOL_MB * 90 / 100 )) ]]; then
# Pool is >=90% full - grow by 25%
TARGET_POOL_MB=$(( CURRENT_POOL_MB * 125 / 100 ))
else
# Pool has headroom - shrink to actual data + 25% buffer
TARGET_POOL_MB=$(( ACTUAL_DATA_MB * 125 / 100 ))
fi
# Apply plan minimum floor
[[ $TARGET_POOL_MB -lt $PLAN_POOL_MIN_MB ]] && TARGET_POOL_MB=$PLAN_POOL_MIN_MB
# Apply plan maximum cap
[[ $TARGET_POOL_MB -gt $PLAN_POOL_CAP_MB ]] && TARGET_POOL_MB=$PLAN_POOL_CAP_MB
FINAL_POOL="${TARGET_POOL_MB}M"
# Conn Logic
SAFE_CONN=$(( TOTAL_RAM_KB / 1024 / 32 ))
if [[ "$PEAK_CONN" -ge $(( CURRENT_MAX_CONN * 90 / 100 )) && $PEAK_CONN -gt 0 ]]; then
CALC_CONN=$(( CURRENT_MAX_CONN + 20 ))
else
CALC_CONN=$SAFE_CONN
fi
[[ $CALC_CONN -lt 40 ]] && CALC_CONN=40
[[ $CALC_CONN -gt 150 ]] && CALC_CONN=150
echo "Calculated Result: Pool: $FINAL_POOL | Connections: $CALC_CONN"
# 6. TUNING APPLICATION (Obeying Dry Run)
TUNING_CONTENT="# BigScoots Dynamic Tuning - Scalable Valves
[mysqld]
max_connections = $CALC_CONN
innodb_buffer_pool_size = $FINAL_POOL
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_read_io_threads = 4
innodb_write_io_threads = 4"
DYNAMIC_CHANGE=false
if [ "$DRY_RUN" = true ]; then
echo "DRY RUN ACTIVE: 02-bigscoots-tuning.cnf will NOT be updated."
else
if [[ ! -f "$TUNING_FILE" ]] || [[ "$(cat "$TUNING_FILE")" != "$TUNING_CONTENT" ]]; then
echo "Applying Dynamic Tuning to $TUNING_FILE..."
echo "$TUNING_CONTENT" > "$TUNING_FILE"
DYNAMIC_CHANGE=true
else
echo "Dynamic Tuning is already optimal."
fi
fi
# 7. APPLY DYNAMIC CHANGES (pool size + connections - no restart needed)
if [ "$DYNAMIC_CHANGE" = true ] && [ "$DRY_RUN" = false ]; then
FINAL_POOL_BYTES=$(( TARGET_POOL_MB * 1024 * 1024 ))
CURRENT_POOL_LIVE=$(mysql -N -e "SELECT @@innodb_buffer_pool_size;" 2>/dev/null || echo 0)
CURRENT_CONN_LIVE=$(mysql -N -e "SELECT @@max_connections;" 2>/dev/null || echo 0)
if [[ "$CURRENT_POOL_LIVE" != "$FINAL_POOL_BYTES" ]]; then
echo "Applying pool size dynamically: ${TARGET_POOL_MB}MB (no restart required)..."
mysql -e "SET GLOBAL innodb_buffer_pool_size = ${FINAL_POOL_BYTES};" 2>/dev/null && \
echo "Pool size updated live." || \
echo "Warning: Dynamic pool update failed - will apply on next restart."
else
echo "Pool size already correct live: ${TARGET_POOL_MB}MB"
fi
if [[ "$CURRENT_CONN_LIVE" != "$CALC_CONN" ]]; then
echo "Applying max_connections dynamically: ${CALC_CONN} (no restart required)..."
mysql -e "SET GLOBAL max_connections = ${CALC_CONN};" 2>/dev/null && \
echo "max_connections updated live." || \
echo "Warning: Dynamic connections update failed."
else
echo "max_connections already correct live: ${CALC_CONN}"
fi
fi
# 8. RESTART LOGIC (only for static plumbing changes - systemd/cnf)
if [ "$RESTART_REQUIRED" = true ]; then
if [ "$AUTO_RESTART" = true ]; then
echo "Restarting $DB_SERVICE to apply Static Plumbing/Systemd changes..."
systemctl restart "$DB_SERVICE"
[[ $? -eq 0 ]] && echo "Success: BigScoots Plumbing Enforced." || exit 1
else
echo "----------------------------------------------------"
read -p "Static plumbing changes detected. Restart $DB_SERVICE now? (y/n): " confirm
[[ "$confirm" == [yY] ]] && systemctl restart "$DB_SERVICE"
fi
else
echo "No restart required."
fi