aboutsummaryrefslogtreecommitdiff
path: root/kolla/docker/mariadb-server/backup_replica.sh
diff options
context:
space:
mode:
Diffstat (limited to 'kolla/docker/mariadb-server/backup_replica.sh')
-rw-r--r--kolla/docker/mariadb-server/backup_replica.sh149
1 files changed, 149 insertions, 0 deletions
diff --git a/kolla/docker/mariadb-server/backup_replica.sh b/kolla/docker/mariadb-server/backup_replica.sh
new file mode 100644
index 000000000..fe10bc61b
--- /dev/null
+++ b/kolla/docker/mariadb-server/backup_replica.sh
@@ -0,0 +1,149 @@
+#!/usr/bin/env bash
+
+set -eu
+set -o pipefail
+
+BACKUP_DIR=/backup/
+DEFAULT_MY_CNF="/etc/mysql/my.cnf"
+REPLICA_MY_CNF="$(mktemp)"
+RETRY_INTERVAL=5 # Interval between retries (in seconds)
+MAX_RETRIES=12 # Max retries (12 retries * 5 seconds = 60 seconds)
+VERIFY_DB_SERVER_CERT="${VERIFY_DB_SERVER_CERT:=FALSE}"
+
+# Cleanup function to remove the REPLICA_MY_CNF file
+cleanup() {
+ rm -f "${REPLICA_MY_CNF}"
+}
+
+# Set trap to ensure cleanup occurs on exit or error
+trap cleanup EXIT
+
+cd "${BACKUP_DIR}"
+
+# Execute a full backup
+backup_full() {
+ echo "Taking a full backup"
+ LAST_FULL_DATE=$(date +%d-%m-%Y-%s)
+ BACKUP_FILE="backup-full-${LAST_FULL_DATE}.mbs.gz"
+ BACKUP_PATH="${BACKUP_DIR}/full-${LAST_FULL_DATE}"
+ mkdir -p "${BACKUP_PATH}"
+
+ mariabackup \
+ --defaults-file="${REPLICA_MY_CNF}" \
+ --backup \
+ --stream=mbstream \
+ --history="${LAST_FULL_DATE}" \
+ | gzip > "${BACKUP_PATH}/${BACKUP_FILE}"
+
+ echo "${BACKUP_PATH}/${BACKUP_FILE}" > "${BACKUP_DIR}/last_full_file"
+}
+
+# Execute an incremental backup
+backup_incremental() {
+ if [ ! -r "${BACKUP_DIR}/last_full_file" ]; then
+ echo "Error: No full backup file found."
+ exit 1
+ fi
+
+ FULL_BACKUP_FILE=$(cat "${BACKUP_DIR}/last_full_file")
+ LAST_FULL_DATE=$(basename "$(dirname "${FULL_BACKUP_FILE}")" | sed 's/^full-//')
+ NOW=$(date +%H-%M-%S-%d-%m-%Y)
+ INCR_DIR="${BACKUP_DIR}/incr-${NOW}-since-${LAST_FULL_DATE}"
+ mkdir -p "${INCR_DIR}"
+
+ # Temp dir for full base restore
+ TMP_BASEDIR=$(mktemp -d)
+
+ echo "Decompressing full backup to temp dir: ${TMP_BASEDIR}"
+ gunzip -c "${FULL_BACKUP_FILE}" | mbstream -x -C "${TMP_BASEDIR}"
+
+ mariabackup \
+ --defaults-file="${REPLICA_MY_CNF}" \
+ --backup \
+ --stream=mbstream \
+ --incremental-basedir="${TMP_BASEDIR}" \
+ --history="incr-${NOW}" \
+ | gzip > "${INCR_DIR}/backup-incremental-${NOW}.mbs.gz"
+
+ rm -rf "${TMP_BASEDIR}"
+}
+
+# Retry logic for database queries
+retry_mysql_query() {
+ local query="$1"
+ local result=""
+ local attempt=1
+
+ while [ ${attempt} -le ${MAX_RETRIES} ]; do
+ result=$(mariadb --ssl-verify-server-cert="${VERIFY_DB_SERVER_CERT}" -h "${HOST}" -u "${USER}" -p"${PASS}" -s -N -e "${query}" 2>/dev/null || true)
+ if [ -n "${result}" ]; then
+ echo "${result}"
+ return 0
+ fi
+ echo "Attempt ${attempt}/${MAX_RETRIES} failed. Retrying in ${RETRY_INTERVAL} seconds..."
+ sleep "${RETRY_INTERVAL}"
+ attempt=$((attempt + 1))
+ done
+
+ echo "Error: Failed to execute the query after ${MAX_RETRIES} attempts."
+ return 1
+}
+
+get_and_set_replica_server() {
+ HOST="$(grep '^host' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
+ USER="$(grep '^user' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
+ PASS="$(grep '^password' "${DEFAULT_MY_CNF}" | awk -F '=' '{print $2}' | xargs)"
+
+ ALL_HOSTS_SELECT="SELECT REGEXP_REPLACE(VARIABLE_VALUE, ':[0-9]*','') FROM information_schema.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_incoming_addresses';"
+ ALL_HOSTS=$(retry_mysql_query "${ALL_HOSTS_SELECT}")
+ if [ -z "${ALL_HOSTS}" ]; then
+ echo "Backup failed due to inability to fetch a list of servers."
+ exit 1
+ fi
+
+ ACTIVE_HOST_SELECT='SELECT @@hostname;'
+ ACTIVE_HOST=$(retry_mysql_query "${ACTIVE_HOST_SELECT}" | xargs getent hosts | awk '{print $1}')
+ if [ -z "${ACTIVE_HOST}" ]; then
+ echo "Backup failed due to inability to fetch active host."
+ exit 1
+ fi
+
+ # Multinode
+ if echo "${ALL_HOSTS}" | grep -q ','; then
+ for server in $(echo "${ALL_HOSTS}" | tr ',' '\n'); do
+ if [[ "${server}" != "${ACTIVE_HOST}" ]]; then
+ REPLICA_HOST="${server}"
+ break
+ fi
+ done
+ # Single node
+ else
+ REPLICA_HOST="${ALL_HOSTS}"
+ fi
+ if [ -z "${REPLICA_HOST}" ]; then
+ echo "Backup failed due to inability to determine replica host."
+ exit 1
+ fi
+
+ cp "${DEFAULT_MY_CNF}" "${REPLICA_MY_CNF}"
+ sed -i "s/${HOST}/${REPLICA_HOST}/g" "${REPLICA_MY_CNF}"
+}
+
+if [ -n "${BACKUP_TYPE}" ]; then
+ get_and_set_replica_server
+ case "${BACKUP_TYPE}" in
+ "full")
+ backup_full
+ ;;
+ "incremental")
+ backup_incremental
+ ;;
+ *)
+ echo "Only full or incremental options are supported."
+ exit 1
+ ;;
+ esac
+else
+ echo "You need to specify either full or incremental backup options."
+ exit 1
+fi