From cb7973fb1f3264ee58f431d98f29468c5e0756f2 Mon Sep 17 00:00:00 2001 From: caffeinated92 Date: Tue, 17 Sep 2024 18:04:10 +0700 Subject: [PATCH] check binary client and use mariadb binary if exist for compatibility --- share/opensvc/moduleset_mariadb.svc.mrm.db.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/share/opensvc/moduleset_mariadb.svc.mrm.db.json b/share/opensvc/moduleset_mariadb.svc.mrm.db.json index 272f43aa4..b3b364356 100644 --- a/share/opensvc/moduleset_mariadb.svc.mrm.db.json +++ b/share/opensvc/moduleset_mariadb.svc.mrm.db.json @@ -4062,8 +4062,8 @@ { "var_author": "admin Manager", "var_class": "file", - "var_value": "{\"path\":\"%%ENV:SVC_CONF_ENV_BASE_DIR%%/%%ENV:POD%%/init/dbjobs_new\",\"mode\":755,\"uid\":\"%%ENV:MYSQL_UID%%\",\"gid\":\"%%ENV:MYSQL_GID%%\",\"fmt\":\"#!/bin/bash\\nset -x\\nUSER=%%ENV:SVC_CONF_ENV_MYSQL_ROOT_USER%%\\nPASSWORD=$MYSQL_ROOT_PASSWORD\\nMYSQL_PORT=%%ENV:SERVER_PORT%%\\nMYSQL_SERVER=%%ENV:SERVER_HOST%%\\nCLUSTER_NAME=%%ENV:SVC_NAMESPACE%%\\nREPLICATION_MANAGER_ADDR=%%ENV:SVC_CONF_ENV_REPLICATION_MANAGER_ADDR%%\\nMYSQL_CONF=%%ENV:SVC_CONF_ENV_MYSQL_CONFDIR%%\\nDATADIR=%%ENV:SVC_CONF_ENV_MYSQL_DATADIR%%\\nMYSQL_CLIENT_PARAMETERS=\\\"-u$USER -h$MYSQL_SERVER -p$PASSWORD -P$MYSQL_PORT\\\"\\nMYSQL_CLIENT=\\\"%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysql $MYSQL_CLIENT_PARAMETERS\\\"\\nMYSQL_CHECK=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysqlcheck\\nMYSQL_DUMP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysqldump\\nSST_RECEIVER_PORT=%%ENV:SVC_CONF_ENV_SST_RECEIVER_PORT%%\\nSOCAT_BIND=%%ENV:SERVER_IP%%\\nMARIADB_BACKUP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariabackup\\nXTRABACKUP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/xtrabackup\\nINNODBACKUPEX=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/innobackupex\\n\\nERROLOG=%%ENV:SVC_CONF_ENV_ERROR_LOG%%\\nSLOWLOG=%%ENV:SVC_CONF_ENV_SLOW_LOG%%\\nBACKUPDIR=$DATADIR/.system/backup\\nTMP_DIR=/tmp\\n\\n# Directory where the logs are stored\\nLOG_DIR=\\\"$TMP_DIR\\\"\\n# Directory where the checkpoints are stored\\nCHECKPOINT_DIR=\\\"$TMP_DIR/checkpoints\\\"\\n# Directory where lock files are stored\\nLOCK_DIR=\\\"$TMP_DIR/locks\\\"\\nBATCH_SIZE=5\\nJOBS=(\\\"xtrabackup\\\" \\\"mariabackup\\\" \\\"error\\\" \\\"slowquery\\\" \\\"zfssnapback\\\" \\\"optimize\\\" \\\"reseedxtrabackup\\\" \\\"reseedmariabackup\\\" \\\"flashbackxtrabackup\\\" \\\"flashbackmariadbackup\\\" \\\"stop\\\" \\\"restart\\\" \\\"start\\\")\\n\\n# OSX need socat extra path\\nexport PATH=$PATH:/usr/local/bin\\n\\npad_pkcs7() {\\n local data=\\\"$1\\\"\\n local blocksize=32\\n local len=$(printf \\\"%s\\\" \\\"$data\\\" | wc -c)\\n local pad_len=$((blocksize - (len % blocksize)))\\n local padding=$(printf \\\"%${pad_len}s\\\" | tr ' ' '\\\\x01')\\n printf \\\"%s%s\\\" \\\"$data\\\" \\\"$padding\\\"\\n}\\n\\nderive_key() {\\n local key=$(echo -n \\\"$MYSQL_ROOT_PASSWORD\\\" | sha256sum | awk '{print $1}')\\n echo \\\"$key\\\"\\n}\\n\\nderive_iv() {\\n local iv=$(echo -n \\\"$MYSQL_ROOT_PASSWORD\\\" | md5sum | awk '{print $1}')\\n echo \\\"$iv\\\"\\n}\\n\\n# Function to encrypt data using AES-128 in CFB mode\\nencrypt_data() {\\n local key=$(derive_key)\\n local iv=$(derive_iv)\\n local padded=$(pad_pkcs7 \\\"$1\\\")\\n local encrypted=$(echo -n \\\"$padded\\\" | openssl aes-256-cbc -a -nosalt -K \\\"$key\\\" -iv \\\"$iv\\\" | tr -d '\\\\n')\\n # echo \\\"$encrypted\\\" >> /tmp/encrypted.txt\\n echo \\\"$encrypted\\\"\\n}\\n\\n# Function to send encrypted data to a JSON API using socat over HTTP\\nsend_encrypted_data_http() {\\n local api_host=\\\"$1\\\"\\n local api_port=\\\"$2\\\"\\n local api_host_port=\\\"$1:$2\\\"\\n local api_endpoint=\\\"$3\\\"\\n local data=$(encrypt_data \\\"$4\\\")\\n local json_data=\\\"{\\\\\\\"data\\\\\\\":\\\\\\\"$data\\\\\\\"}\\\"\\n\\n local request=\\\"POST $api_endpoint HTTP/1.1\\\\r\\\\nHost: $api_host\\\\r\\\\nContent-Type: application/json\\\\r\\\\nContent-Length: ${#json_data}\\\\r\\\\n\\\\r\\\\n$json_data\\\"\\n # Use socat to send the request over HTTP\\n local response=$(echo -en \\\"$request\\\" | socat - TCP:$api_host_port)\\n echo \\\"$request\\\" >> /tmp/request.txt\\n echo \\\"$response\\\"\\n}\\n\\n# Function to send encrypted data to a JSON API using socat over HTTPS\\nsend_encrypted_data_https() {\\n local api_host=\\\"$1\\\"\\n local api_port=\\\"$2\\\"\\n local api_host_port=\\\"$1:$2\\\"\\n local api_endpoint=\\\"$3\\\"\\n local data=$(encrypt_data \\\"$4\\\")\\n local json_data=\\\"{\\\\\\\"data\\\\\\\":\\\\\\\"$data\\\\\\\"}\\\"\\n\\n local request=\\\"POST $api_endpoint HTTP/1.1\\\\r\\\\nHost: $api_host\\\\r\\\\nContent-Type: application/json\\\\r\\\\nContent-Length: ${#json_data}\\\\r\\\\n\\\\r\\\\n$json_data\\\"\\n # Use socat with SSL and no verification to send the request over HTTPS\\n local response=$(echo -en \\\"$request\\\" | socat - OPENSSL:$api_host_port,verify=0)\\n echo \\\"$request\\\" >> /tmp/request.txt\\n echo \\\"$response\\\"\\n}\\n\\n# Wrapper function to choose between HTTP and HTTPS based on port\\nsend_encrypted_data() {\\n local api_host=$(echo \\\"$1\\\" | cut -d\\\":\\\" -f1)\\n local port=10005\\n local task=\\\"$2\\\"\\n local data=\\\"$3\\\"\\n local api_endpoint=\\\"/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/write-log/$task\\\"\\n\\n if [ \\\"$port\\\" = \\\"10005\\\" ]; then\\n send_encrypted_data_https \\\"$api_host\\\" \\\"$port\\\" \\\"$api_endpoint\\\" \\\"$data\\\"\\n else\\n send_encrypted_data_http \\\"$api_host\\\" \\\"$port\\\" \\\"$api_endpoint\\\" \\\"$data\\\"\\n fi\\n}\\n\\n# Function to send a batch of lines to the API and check for success with retry logic\\nsend_lines_to_api() {\\n local lines=\\\"$1\\\"\\n local job=\\\"$2\\\"\\n local address=\\\"${REPLICATION_MANAGER_ADDR}\\\"\\n local data=\\\"{\\\\\\\"server\\\\\\\":\\\\\\\"$MYSQL_SERVER:$MYSQL_PORT\\\\\\\",\\\\\\\"log\\\\\\\":\\\\\\\"$lines\\\\\\\"}\\\"\\n\\n local max_retries=3\\n local attempt=0\\n local success=false\\n\\n while ((attempt < max_retries)); do\\n # Capture response and HTTP status code\\n local response\\n response=$(send_encrypted_data \\\"$address\\\" \\\"$job\\\" \\\"$data\\\")\\n\\n echo \\\"$response\\\" >> /tmp/curl_response.txt\\n \\n # Extract HTTP status code\\n local http_code=$(echo \\\"$response\\\" | grep -oP '(?<=HTTP/1.1 )[0-9]{3}')\\n\\n if [ \\\"$http_code\\\" -eq 200 ]; then\\n echo \\\"API call successful for job: $job\\\"\\n success=true\\n break\\n else\\n echo \\\"API call failed for job: $job with status code: $http_code\\\"\\n cat /tmp/curl_response.txt\\n ((attempt++))\\n sleep 2 # Wait before retrying\\n fi\\n done\\n\\n if [ \\\"$success\\\" = false ]; then\\n echo \\\"API call failed after $max_retries attempts for job: $job\\\"\\n fi\\n}\\n\\n# Function to create a manual lock file\\ncreate_lock_file() {\\n local lock_file=\\\"$1\\\"\\n if [ -e \\\"$lock_file\\\" ]; then\\n echo \\\"Lock file exists. Exiting.\\\"\\n return 1\\n fi\\n touch \\\"$lock_file\\\"\\n return 0\\n}\\n\\n# Function to remove a manual lock file\\nremove_lock_file() {\\n local lock_file=\\\"$1\\\"\\n rm -f \\\"$lock_file\\\"\\n}\\n\\n# Function to wait for the .run file with a timeout\\nwait_for_run_lockdir() {\\n local run_lockdir=\\\"$1\\\"\\n local timeout=30\\n local start_time=$(date +%s)\\n\\n send_lines_to_api \\\"Waiting for $run_lockdir file...\\\\n\\\" \\\"$job\\\"\\n while [[ ! -d \\\"$run_lockdir\\\" ]]; do\\n sleep 0.5\\n local current_time=$(date +%s)\\n local elapsed=$((current_time - start_time))\\n if ((elapsed >= timeout)); then\\n send_lines_to_api \\\"Timeout reached while waiting for .run file.\\\\n\\\" \\\"$job\\\"\\n return 1\\n fi\\n done\\n send_lines_to_api \\\"$run_lockdir file found...\\\\n\\\" \\\"$job\\\"\\n return 0\\n}\\n\\n# Function to wait for the .run file with a timeout\\nwait_for_log_file() {\\n local logfile=\\\"$1\\\"\\n local timeout=60\\n local start_time=$(date +%s)\\n\\n send_lines_to_api \\\"Waiting for $logfile file...\\\\n\\\" \\\"$job\\\"\\n while [[ ! -f \\\"$logfile\\\" ]]; do\\n sleep 0.5\\n local current_time=$(date +%s)\\n local elapsed=$((current_time - start_time))\\n if ((elapsed >= timeout)); then\\n send_lines_to_api \\\"Timeout reached while waiting for $logfile file. Please check log manually if needed. \\\\n\\\" \\\"$job\\\"\\n return 1\\n fi\\n done\\n send_lines_to_api \\\"$logfile file found...\\\\n\\\" \\\"$job\\\"\\n return 0\\n}\\n\\nread_log_file() {\\n local logfile=\\\"$1\\\"\\n local checkpoint_file=$2\\n local last_read=$(cat $checkpoint_file)\\n local current_line=$((last_read + 1))\\n\\n while IFS= read -r line; do\\n escaped=$(printf '%s' \\\"$line\\\" | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g; s/\\\"/\\\\\\\\\\\"/g; s/\\\\n/\\\\\\\\n/g')\\n ((current_line++))\\n\\n if [[ ! -d \\\"$run_lockdir\\\" ]]; then\\n send_lines_to_api \\\"Run file has been deleted. Processing remaining lines.\\\\n\\\" \\\"$job\\\"\\n break\\n fi\\n\\n batch+=\\\"$escaped\\\\n\\\"\\n if ((current_line % BATCH_SIZE == 0)); then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n batch=\\\"\\\"\\n fi\\n echo \\\"$current_line\\\" >\\\"$checkpoint_file\\\"\\n\\n done < <(sed -n \\\"$current_line,${p}\\\" \\\"$log_file\\\")\\n\\n # Send any remaining lines in the batch after the first loop\\n if [[ -n \\\"$batch\\\" ]]; then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n fi\\n}\\n\\n# Function to process a log file\\nprocess_log_file() {\\n local job=\\\"$1\\\"\\n local log_file\\n case \\\"$job\\\" in\\n \\\"mariabackup\\\"|\\\"xtrabackup\\\")\\n log_file=\\\"$LOG_DIR/backup.out\\\"\\n ;;\\n \\\"reseedmariabackup\\\"|\\\"reseedxtrabackup\\\")\\n log_file=\\\"$LOG_DIR/reseed.out\\\"\\n ;;\\n \\\"flashbackmariabackup\\\"|\\\"flashbackxtrabackup\\\")\\n log_file=\\\"$LOG_DIR/flash.out\\\"\\n ;;\\n *)\\n log_file=\\\"$LOG_DIR/$job.out\\\"\\n ;;\\n esac\\n\\n local checkpoint_file=\\\"$CHECKPOINT_DIR/$job.checkpoint\\\"\\n local run_lockdir=\\\"$LOG_DIR/$job.run\\\"\\n local lock_file=\\\"$LOCK_DIR/${job}_lockfile\\\"\\n\\n if ! create_lock_file \\\"$lock_file\\\"; then\\n return\\n fi\\n\\n # Ensure lock file is removed on script exit\\n trap 'remove_lock_file \\\"$lock_file\\\"' EXIT\\n\\n if ! wait_for_run_lockdir \\\"$run_lockdir\\\"; then\\n remove_lock_file \\\"$lock_file\\\"\\n return\\n fi\\n\\n if ! wait_for_log_file \\\"$log_file\\\"; then\\n remove_lock_file \\\"$lock_file\\\"\\n return\\n fi\\n\\n local last_line=0\\n if [[ -f \\\"$checkpoint_file\\\" ]]; then\\n last_line=$(cat \\\"$checkpoint_file\\\")\\n fi\\n\\n send_lines_to_api \\\"Last checkpoint on \\\"$checkpoint_file\\\" is: $last_line.\\\\n\\\" \\\"$job\\\"\\n\\n local current_line=0\\n local batch=\\\"\\\"\\n local exec_once=1\\n\\n # processing until the end of the file and loop until run file deleted\\n while [[ -d \\\"$run_lockdir\\\" ]] || [[ \\\"$exec_once\\\" -eq 1 ]]; do\\n exec_once=0\\n read_log_file \\\"$log_file\\\" \\\"$checkpoint_file\\\"\\n done\\n\\n # If the run file was deleted, continue processing until the end of the file\\n while IFS= read -r line; do\\n escaped=$(printf '%s' \\\"$line\\\" | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g; s/\\\"/\\\\\\\\\\\"/g; s/\\\\n/\\\\\\\\n/g')\\n ((current_line++))\\n batch+=\\\"$escaped\\\\n\\\"\\n if ((current_line % BATCH_SIZE == 0)); then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n batch=\\\"\\\"\\n fi\\n echo \\\"$current_line\\\" >\\\"$checkpoint_file\\\"\\n done < <(tail -n +\\\"$((current_line - last_line))\\\" \\\"$log_file\\\")\\n\\n if [[ -n \\\"$batch\\\" ]]; then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n fi\\n\\n send_lines_to_api \\\"Removing checkpoint file.\\\\n\\\" \\\"$job\\\"\\n rm -f \\\"$checkpoint_file\\\"\\n\\n remove_lock_file \\\"$lock_file\\\"\\n}\\n\\nsocatCleaner() {\\n kill -9 $(lsof -t -i:$SST_RECEIVER_PORT -sTCP:LISTEN)\\n}\\n\\ndoneJob() {\\n jobstate=3\\n done=1\\n case \\\"$job\\\" in\\n mariabackup | xtrabackup )\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/backup.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/backup.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n reseedmariabackup | reseedxtrabackup)\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/reseed.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/reseed.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n flashbackmariabackup | flashbackxtrabackup)\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/flash.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/flash.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n esac\\n \\n if [ $jobstate -eq 3 ]; then\\n send_lines_to_api \\\"Job $job ended with state: Finished\\\" \\\"$job\\\" \\n else\\n send_lines_to_api \\\"Job $job ended with state: Error\\\" \\\"$job\\\"\\n fi\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set end=NOW(), state=$jobstate, result=LOAD_FILE('/tmp/$job.out'), done=$done WHERE id='$ID';\\\" &\\n}\\n\\npauseJob() {\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set state=2, result='waiting' WHERE id='$ID';\\\" &\\n}\\n\\npartialRestore() {\\n send_lines_to_api \\\"Starting partial restore...\\\" \\\"$job\\\" \\n chown -R mysql:mysql $BACKUPDIR \\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;install plugin BLACKHOLE soname 'ha_blackhole.so'\\\"\\n for dir in $(ls -d $BACKUPDIR/*/ | xargs -n 1 basename | grep -vE 'mysql|performance_schema|replication_manager_schema'); do\\n send_lines_to_api \\\"Restoring $dir...\\\" \\\"$job\\\" \\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;drop database IF EXISTS $dir; CREATE DATABASE $dir;\\\"\\n\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.ibd\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n cat $BACKUPDIR/$dir/$file.frm | sed -e 's/\\\\x06\\\\x00\\\\x49\\\\x6E\\\\x6E\\\\x6F\\\\x44\\\\x42\\\\x00\\\\x00\\\\x00/\\\\x09\\\\x00\\\\x42\\\\x4C\\\\x41\\\\x43\\\\x4B\\\\x48\\\\x4F\\\\x4C\\\\x45/g' >$DATADIR/$dir/mrm_pivo.frm\\n chown mysql:mysql $DATADIR/$dir/mrm_pivo.frm\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;ALTER TABLE $dir.mrm_pivo engine=innodb;RENAME TABLE $dir.mrm_pivo TO $dir.$file; ALTER TABLE $dir.$file DISCARD TABLESPACE;\\\"\\n mv $BACKUPDIR/$dir/$file.ibd $DATADIR/$dir/$file.ibd\\n mv $BACKUPDIR/$dir/$file.exp $DATADIR/$dir/$file.exp\\n mv $BACKUPDIR/$dir/$file.cfg $DATADIR/$dir/$file.cfg\\n mv $BACKUPDIR/$dir/$file.TRG $DATADIR/$dir/$file.TRG\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;ALTER TABLE $dir.$file IMPORT TABLESPACE\\\"\\n done\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.MYD\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/$dir/$file.* $DATADIR/$dir/\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE $dir.$file\\\"\\n done\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.CSV\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/$dir/$file.* $DATADIR/$dir/\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE $dir.$file\\\"\\n done\\n done\\n for file in $(find $BACKUPDIR/mysql/ -name \\\"*.MYD\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/mysql/$file.* $DATADIR/mysql/\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE mysql.$file\\\"\\n done\\n send_lines_to_api \\\"Setting GTID of the last change...\\\" \\\"$job\\\" \\n cat $BACKUPDIR/xtrabackup_info | grep binlog_pos | awk -F, '{ print $3 }' | sed -e 's/GTID of the last change/set sql_log_bin=0;set global gtid_slave_pos=/g' | $MYSQL_CLIENT\\n send_lines_to_api \\\"Flushing privileges...\\\" \\\"$job\\\" \\n $MYSQL_CLIENT -e\\\"set sql_log_bin=0;flush privileges;start slave;\\\"\\n}\\n\\n#######################\\n# JOB START HERE\\n#######################\\n\\nmkdir -p \\\"$CHECKPOINT_DIR\\\"\\nmkdir -p \\\"$LOCK_DIR\\\"\\necho \\\"\\\" > /tmp/curl_response.txt\\necho \\\"\\\" > /tmp/request.txt\\necho \\\"\\\" > /tmp/encrypt.txt\\n\\nfor job in \\\"${JOBS[@]}\\\"; do\\n\\n TASK=($(echo \\\"SELECT concat(id,'@',server,':',port) FROM replication_manager_schema.jobs WHERE task='$job' and done=0 AND state=0 order by id desc limit 1\\\" | $MYSQL_CLIENT -N))\\n\\n ADDRESS=($(echo $TASK | awk -F@ '{ print $2 }'))\\n ID=($(echo $TASK | awk -F@ '{ print $1 }'))\\n\\n if [ \\\"$ID\\\" != \\\"\\\" ]; then\\n send_lines_to_api \\\"Job $job initiated. Clearing previous logs...\\\" \\\"$job\\\" \\n case \\\"$job\\\" in\\n mariabackup|xtrabackup)\\n rm -f \\\"/tmp/backup.out\\\"\\n ;;\\n reseedmariabackup|reseedxtrabackup)\\n rm -f \\\"/tmp/reseed.out\\\"\\n ;;\\n flashbackmariabackup|flashbackxtrabackup)\\n rm -f \\\"/tmp/flash.out\\\"\\n ;;\\n esac\\n\\n rm -f \\\"/tmp/$job.out\\\"\\n rm -f \\\"$CHECKPOINT_DIR/$job.checkpoint\\\"\\n fi\\n\\n\\n if [ \\\"$ADDRESS\\\" == \\\"\\\" ]; then\\n echo \\\"No $job needed\\\"\\n case \\\"$job\\\" in\\n start)\\n if [ \\\"curl -so /dev/null -w '%{response_code}' http://$REPLICATION_MANAGER_ADDR/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/need-start\\\" == \\\"200\\\" ]; then\\n curl http://$REPLICATION_MANAGER_ADDR/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/config | tar xzvf etc/* - -C $CONFDIR/../..\\n systemctl start mysql\\n fi\\n ;;\\n esac\\n else\\n\\n mkdir -p \\\"/tmp/$job.run\\\"\\n process_log_file \\\"$job\\\" &\\n trap 'rmdir \\\"/tmp/$job.run\\\"' EXIT\\n echo \\\"Processing $job\\\"\\n \\n #purge de past\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set done=1 WHERE done=0 AND task='$job' AND ID<>$ID;\\\"\\n $MYSQL_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set state=1, result='processing' WHERE task='$job' AND ID=$ID;\\\"\\n case \\\"$job\\\" in\\n reseedxtrabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $XTRABACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/reseed.out\\\"\\n partialRestore\\n ;;\\n reseedmariabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | mbstream -x -C $BACKUPDIR\\n # mbstream -p, --parallel\\n $MARIADB_BACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/reseed.out\\\"\\n partialRestore\\n ;;\\n flashbackxtrabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $XTRABACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/flash.out\\\"\\n partialRestore\\n ;;\\n flashbackmariadbackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $MARIADB_BACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/flash.out\\\"\\n partialRestore\\n ;;\\n xtrabackup)\\n cd /docker-entrypoint-initdb.d\\n $XTRABACKUP --defaults-file=$MYSQL_CONF/my.cnf --backup -u$USER -H$MYSQL_SERVER -p$PASSWORD -P$MYSQL_PORT --stream=xbstream --target-dir=/tmp/ 2>\\\"/tmp/backup.out\\\" | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n ;;\\n mariabackup)\\n cd /docker-entrypoint-initdb.d\\n $MARIADB_BACKUP --innobackupex --defaults-file=$MYSQL_CONF/my.cnf --databases-exclude=.system --protocol=TCP $MYSQL_CLIENT_PARAMETERS --stream=xbstream 2>\\\"/tmp/backup.out\\\" | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n ;;\\n error)\\n cat $ERROLOG | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n >$ERROLOG\\n ;;\\n slowquery)\\n cat $SLOWLOG | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n >$SLOWLOG\\n ;;\\n zfssnapback)\\n LASTSNAP=$(zfs list -r -t all | grep zp%%ENV:SERVICES_SVCNAME%%_pod01 | grep daily | sort -r | head -n 1 | cut -d\\\" \\\" -f1)\\n %%ENV:SERVICES_SVCNAME%% stop\\n zfs rollback $LASTSNAP\\n %%ENV:SERVICES_SVCNAME%% start\\n ;;\\n optimize)\\n $MYSQL_CHECK -o $MYSQL_CLIENT_PARAMETERS --all-databases --skip-write-binlog &>\\\"/tmp/$job.out\\\"\\n ;;\\n restart)\\n systemctl restart mysql\\n journalctl -u mysql >\\\"/tmp/$job.out\\\"\\n ;;\\n stop)\\n systemctl stop mysql\\n journalctl -u mysql >\\\"/tmp/$job.out\\\"\\n ;;\\n esac\\n doneJob \\\"$job\\\"\\n sleep 1 && rmdir \\\"/tmp/$job.run\\\" &\\n fi\\ndone\"}", - "var_updated": "2024-09-03 11:18:13", + "var_value": "{\"path\":\"%%ENV:SVC_CONF_ENV_BASE_DIR%%/%%ENV:POD%%/init/dbjobs_new\",\"mode\":755,\"uid\":\"%%ENV:MYSQL_UID%%\",\"gid\":\"%%ENV:MYSQL_GID%%\",\"fmt\":\"#!/bin/bash\\nset -x\\nUSER=%%ENV:SVC_CONF_ENV_MYSQL_ROOT_USER%%\\nPASSWORD=$MYSQL_ROOT_PASSWORD\\nMYSQL_PORT=%%ENV:SERVER_PORT%%\\nMYSQL_SERVER=%%ENV:SERVER_HOST%%\\nCLUSTER_NAME=%%ENV:SVC_NAMESPACE%%\\nREPLICATION_MANAGER_ADDR=%%ENV:SVC_CONF_ENV_REPLICATION_MANAGER_ADDR%%\\nMYSQL_CONF=%%ENV:SVC_CONF_ENV_MYSQL_CONFDIR%%\\nDATADIR=%%ENV:SVC_CONF_ENV_MYSQL_DATADIR%%\\nBINARY_CLIENT_PARAMETERS=\\\"-u$USER -h$MYSQL_SERVER -p$PASSWORD -P$MYSQL_PORT\\\"\\n\\n# MariaDB binary paths\\nMARIADB_CLIENT=\\\"%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariadb $BINARY_CLIENT_PARAMETERS\\\"\\nMARIADB_CHECK=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariadb-check\\nMARIADB_DUMP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariadb-dump\\n\\n# MySQL binary paths\\nMYSQL_CLIENT=\\\"%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysql $BINARY_CLIENT_PARAMETERS\\\"\\nMYSQL_CHECK=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysqlcheck\\nMYSQL_DUMP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysqldump\\n\\n# Determine which binary to use (prefer MariaDB, fallback to MySQL)\\nif [ -x \\\"$MARIADB_CLIENT\\\" ]; then\\n BINARY_CLIENT=$MARIADB_CLIENT\\n BINARY_CHECK=$MARIADB_CHECK\\n BINARY_DUMP=$MARIADB_DUMP\\n echo \\\"Using MariaDB binaries.\\\"\\nelif [ -x \\\"$MYSQL_CLIENT\\\" ]; then\\n BINARY_CLIENT=$MYSQL_CLIENT\\n BINARY_CHECK=$MYSQL_CHECK\\n BINARY_DUMP=$MYSQL_DUMP\\n echo \\\"Using MySQL binaries.\\\"\\nelse\\n echo \\\"Neither MariaDB nor MySQL binaries are available.\\\"\\n exit 1\\nfi\\n\\nSST_RECEIVER_PORT=%%ENV:SVC_CONF_ENV_SST_RECEIVER_PORT%%\\nSOCAT_BIND=%%ENV:SERVER_IP%%\\nMARIADB_BACKUP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariabackup\\nXTRABACKUP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/xtrabackup\\nINNODBACKUPEX=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/innobackupex\\n\\nERROLOG=%%ENV:SVC_CONF_ENV_ERROR_LOG%%\\nSLOWLOG=%%ENV:SVC_CONF_ENV_SLOW_LOG%%\\nBACKUPDIR=$DATADIR/.system/backup\\nTMP_DIR=/tmp\\n\\n# Directory where the logs are stored\\nLOG_DIR=\\\"$TMP_DIR\\\"\\n# Directory where the checkpoints are stored\\nCHECKPOINT_DIR=\\\"$TMP_DIR/checkpoints\\\"\\n# Directory where lock files are stored\\nLOCK_DIR=\\\"$TMP_DIR/locks\\\"\\nBATCH_SIZE=5\\nJOBS=(\\\"xtrabackup\\\" \\\"mariabackup\\\" \\\"error\\\" \\\"slowquery\\\" \\\"zfssnapback\\\" \\\"optimize\\\" \\\"reseedxtrabackup\\\" \\\"reseedmariabackup\\\" \\\"flashbackxtrabackup\\\" \\\"flashbackmariadbackup\\\" \\\"stop\\\" \\\"restart\\\" \\\"start\\\")\\n\\n# OSX need socat extra path\\nexport PATH=$PATH:/usr/local/bin\\n\\npad_pkcs7() {\\n local data=\\\"$1\\\"\\n local blocksize=32\\n local len=$(printf \\\"%s\\\" \\\"$data\\\" | wc -c)\\n local pad_len=$((blocksize - (len % blocksize)))\\n local padding=$(printf \\\"%${pad_len}s\\\" | tr ' ' '\\\\x01')\\n printf \\\"%s%s\\\" \\\"$data\\\" \\\"$padding\\\"\\n}\\n\\nderive_key() {\\n local key=$(echo -n \\\"$MYSQL_ROOT_PASSWORD\\\" | sha256sum | awk '{print $1}')\\n echo \\\"$key\\\"\\n}\\n\\nderive_iv() {\\n local iv=$(echo -n \\\"$MYSQL_ROOT_PASSWORD\\\" | md5sum | awk '{print $1}')\\n echo \\\"$iv\\\"\\n}\\n\\n# Function to encrypt data using AES-128 in CFB mode\\nencrypt_data() {\\n local key=$(derive_key)\\n local iv=$(derive_iv)\\n local padded=$(pad_pkcs7 \\\"$1\\\")\\n local encrypted=$(echo -n \\\"$padded\\\" | openssl aes-256-cbc -a -nosalt -K \\\"$key\\\" -iv \\\"$iv\\\" | tr -d '\\\\n')\\n # echo \\\"$encrypted\\\" >> /tmp/encrypted.txt\\n echo \\\"$encrypted\\\"\\n}\\n\\n# Function to send encrypted data to a JSON API using socat over HTTP\\nsend_encrypted_data_http() {\\n local api_host=\\\"$1\\\"\\n local api_port=\\\"$2\\\"\\n local api_host_port=\\\"$1:$2\\\"\\n local api_endpoint=\\\"$3\\\"\\n local data=$(encrypt_data \\\"$4\\\")\\n local json_data=\\\"{\\\\\\\"data\\\\\\\":\\\\\\\"$data\\\\\\\"}\\\"\\n\\n local request=\\\"POST $api_endpoint HTTP/1.1\\\\r\\\\nHost: $api_host\\\\r\\\\nContent-Type: application/json\\\\r\\\\nContent-Length: ${#json_data}\\\\r\\\\n\\\\r\\\\n$json_data\\\"\\n # Use socat to send the request over HTTP\\n local response=$(echo -en \\\"$request\\\" | socat - TCP:$api_host_port)\\n echo \\\"$request\\\" >> /tmp/request.txt\\n echo \\\"$response\\\"\\n}\\n\\n# Function to send encrypted data to a JSON API using socat over HTTPS\\nsend_encrypted_data_https() {\\n local api_host=\\\"$1\\\"\\n local api_port=\\\"$2\\\"\\n local api_host_port=\\\"$1:$2\\\"\\n local api_endpoint=\\\"$3\\\"\\n local data=$(encrypt_data \\\"$4\\\")\\n local json_data=\\\"{\\\\\\\"data\\\\\\\":\\\\\\\"$data\\\\\\\"}\\\"\\n\\n local request=\\\"POST $api_endpoint HTTP/1.1\\\\r\\\\nHost: $api_host\\\\r\\\\nContent-Type: application/json\\\\r\\\\nContent-Length: ${#json_data}\\\\r\\\\n\\\\r\\\\n$json_data\\\"\\n # Use socat with SSL and no verification to send the request over HTTPS\\n local response=$(echo -en \\\"$request\\\" | socat - OPENSSL:$api_host_port,verify=0)\\n echo \\\"$request\\\" >> /tmp/request.txt\\n echo \\\"$response\\\"\\n}\\n\\n# Wrapper function to choose between HTTP and HTTPS based on port\\nsend_encrypted_data() {\\n local api_host=$(echo \\\"$1\\\" | cut -d\\\":\\\" -f1)\\n local port=10005\\n local task=\\\"$2\\\"\\n local data=\\\"$3\\\"\\n local api_endpoint=\\\"/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/write-log/$task\\\"\\n\\n if [ \\\"$port\\\" = \\\"10005\\\" ]; then\\n send_encrypted_data_https \\\"$api_host\\\" \\\"$port\\\" \\\"$api_endpoint\\\" \\\"$data\\\"\\n else\\n send_encrypted_data_http \\\"$api_host\\\" \\\"$port\\\" \\\"$api_endpoint\\\" \\\"$data\\\"\\n fi\\n}\\n\\n# Function to send a batch of lines to the API and check for success with retry logic\\nsend_lines_to_api() {\\n local lines=\\\"$1\\\"\\n local job=\\\"$2\\\"\\n local address=\\\"${REPLICATION_MANAGER_ADDR}\\\"\\n local data=\\\"{\\\\\\\"server\\\\\\\":\\\\\\\"$MYSQL_SERVER:$MYSQL_PORT\\\\\\\",\\\\\\\"log\\\\\\\":\\\\\\\"$lines\\\\\\\"}\\\"\\n\\n local max_retries=3\\n local attempt=0\\n local success=false\\n\\n while ((attempt < max_retries)); do\\n # Capture response and HTTP status code\\n local response\\n response=$(send_encrypted_data \\\"$address\\\" \\\"$job\\\" \\\"$data\\\")\\n\\n echo \\\"$response\\\" >> /tmp/curl_response.txt\\n \\n # Extract HTTP status code\\n local http_code=$(echo \\\"$response\\\" | grep -oP '(?<=HTTP/1.1 )[0-9]{3}')\\n\\n if [ \\\"$http_code\\\" -eq 200 ]; then\\n echo \\\"API call successful for job: $job\\\"\\n success=true\\n break\\n else\\n echo \\\"API call failed for job: $job with status code: $http_code\\\"\\n cat /tmp/curl_response.txt\\n ((attempt++))\\n sleep 2 # Wait before retrying\\n fi\\n done\\n\\n if [ \\\"$success\\\" = false ]; then\\n echo \\\"API call failed after $max_retries attempts for job: $job\\\"\\n fi\\n}\\n\\n# Function to create a manual lock file\\ncreate_lock_file() {\\n local lock_file=\\\"$1\\\"\\n if [ -e \\\"$lock_file\\\" ]; then\\n echo \\\"Lock file exists. Exiting.\\\"\\n return 1\\n fi\\n touch \\\"$lock_file\\\"\\n return 0\\n}\\n\\n# Function to remove a manual lock file\\nremove_lock_file() {\\n local lock_file=\\\"$1\\\"\\n rm -f \\\"$lock_file\\\"\\n}\\n\\n# Function to wait for the .run file with a timeout\\nwait_for_run_lockdir() {\\n local run_lockdir=\\\"$1\\\"\\n local timeout=30\\n local start_time=$(date +%s)\\n\\n send_lines_to_api \\\"Waiting for $run_lockdir file...\\\\n\\\" \\\"$job\\\"\\n while [[ ! -d \\\"$run_lockdir\\\" ]]; do\\n sleep 0.5\\n local current_time=$(date +%s)\\n local elapsed=$((current_time - start_time))\\n if ((elapsed >= timeout)); then\\n send_lines_to_api \\\"Timeout reached while waiting for .run file.\\\\n\\\" \\\"$job\\\"\\n return 1\\n fi\\n done\\n send_lines_to_api \\\"$run_lockdir file found...\\\\n\\\" \\\"$job\\\"\\n return 0\\n}\\n\\n# Function to wait for the .run file with a timeout\\nwait_for_log_file() {\\n local logfile=\\\"$1\\\"\\n local timeout=60\\n local start_time=$(date +%s)\\n\\n send_lines_to_api \\\"Waiting for $logfile file...\\\\n\\\" \\\"$job\\\"\\n while [[ ! -f \\\"$logfile\\\" ]]; do\\n sleep 0.5\\n local current_time=$(date +%s)\\n local elapsed=$((current_time - start_time))\\n if ((elapsed >= timeout)); then\\n send_lines_to_api \\\"Timeout reached while waiting for $logfile file. Please check log manually if needed. \\\\n\\\" \\\"$job\\\"\\n return 1\\n fi\\n done\\n send_lines_to_api \\\"$logfile file found...\\\\n\\\" \\\"$job\\\"\\n return 0\\n}\\n\\nread_log_file() {\\n local logfile=\\\"$1\\\"\\n local checkpoint_file=$2\\n local last_read=$(cat $checkpoint_file)\\n local current_line=$((last_read + 1))\\n\\n while IFS= read -r line; do\\n escaped=$(printf '%s' \\\"$line\\\" | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g; s/\\\"/\\\\\\\\\\\"/g; s/\\\\n/\\\\\\\\n/g')\\n ((current_line++))\\n\\n if [[ ! -d \\\"$run_lockdir\\\" ]]; then\\n send_lines_to_api \\\"Run file has been deleted. Processing remaining lines.\\\\n\\\" \\\"$job\\\"\\n break\\n fi\\n\\n batch+=\\\"$escaped\\\\n\\\"\\n if ((current_line % BATCH_SIZE == 0)); then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n batch=\\\"\\\"\\n fi\\n echo \\\"$current_line\\\" >\\\"$checkpoint_file\\\"\\n\\n done < <(sed -n \\\"$current_line,${p}\\\" \\\"$log_file\\\")\\n\\n # Send any remaining lines in the batch after the first loop\\n if [[ -n \\\"$batch\\\" ]]; then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n fi\\n}\\n\\n# Function to process a log file\\nprocess_log_file() {\\n local job=\\\"$1\\\"\\n local log_file\\n case \\\"$job\\\" in\\n \\\"mariabackup\\\"|\\\"xtrabackup\\\")\\n log_file=\\\"$LOG_DIR/backup.out\\\"\\n ;;\\n \\\"reseedmariabackup\\\"|\\\"reseedxtrabackup\\\")\\n log_file=\\\"$LOG_DIR/reseed.out\\\"\\n ;;\\n \\\"flashbackmariabackup\\\"|\\\"flashbackxtrabackup\\\")\\n log_file=\\\"$LOG_DIR/flash.out\\\"\\n ;;\\n *)\\n log_file=\\\"$LOG_DIR/$job.out\\\"\\n ;;\\n esac\\n\\n local checkpoint_file=\\\"$CHECKPOINT_DIR/$job.checkpoint\\\"\\n local run_lockdir=\\\"$LOG_DIR/$job.run\\\"\\n local lock_file=\\\"$LOCK_DIR/${job}_lockfile\\\"\\n\\n if ! create_lock_file \\\"$lock_file\\\"; then\\n return\\n fi\\n\\n # Ensure lock file is removed on script exit\\n trap 'remove_lock_file \\\"$lock_file\\\"' EXIT\\n\\n if ! wait_for_run_lockdir \\\"$run_lockdir\\\"; then\\n remove_lock_file \\\"$lock_file\\\"\\n return\\n fi\\n\\n if ! wait_for_log_file \\\"$log_file\\\"; then\\n remove_lock_file \\\"$lock_file\\\"\\n return\\n fi\\n\\n local last_line=0\\n if [[ -f \\\"$checkpoint_file\\\" ]]; then\\n last_line=$(cat \\\"$checkpoint_file\\\")\\n fi\\n\\n send_lines_to_api \\\"Last checkpoint on \\\"$checkpoint_file\\\" is: $last_line.\\\\n\\\" \\\"$job\\\"\\n\\n local current_line=0\\n local batch=\\\"\\\"\\n local exec_once=1\\n\\n # processing until the end of the file and loop until run file deleted\\n while [[ -d \\\"$run_lockdir\\\" ]] || [[ \\\"$exec_once\\\" -eq 1 ]]; do\\n exec_once=0\\n read_log_file \\\"$log_file\\\" \\\"$checkpoint_file\\\"\\n done\\n\\n # If the run file was deleted, continue processing until the end of the file\\n while IFS= read -r line; do\\n escaped=$(printf '%s' \\\"$line\\\" | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g; s/\\\"/\\\\\\\\\\\"/g; s/\\\\n/\\\\\\\\n/g')\\n ((current_line++))\\n batch+=\\\"$escaped\\\\n\\\"\\n if ((current_line % BATCH_SIZE == 0)); then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n batch=\\\"\\\"\\n fi\\n echo \\\"$current_line\\\" >\\\"$checkpoint_file\\\"\\n done < <(tail -n +\\\"$((current_line - last_line))\\\" \\\"$log_file\\\")\\n\\n if [[ -n \\\"$batch\\\" ]]; then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n fi\\n\\n send_lines_to_api \\\"Removing checkpoint file.\\\\n\\\" \\\"$job\\\"\\n rm -f \\\"$checkpoint_file\\\"\\n\\n remove_lock_file \\\"$lock_file\\\"\\n}\\n\\nsocatCleaner() {\\n kill -9 $(lsof -t -i:$SST_RECEIVER_PORT -sTCP:LISTEN)\\n}\\n\\ndoneJob() {\\n jobstate=3\\n done=1\\n case \\\"$job\\\" in\\n mariabackup | xtrabackup )\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/backup.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/backup.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n reseedmariabackup | reseedxtrabackup)\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/reseed.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/reseed.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n flashbackmariabackup | flashbackxtrabackup)\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/flash.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/flash.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n esac\\n \\n if [ $jobstate -eq 3 ]; then\\n send_lines_to_api \\\"Job $job ended with state: Finished\\\" \\\"$job\\\" \\n else\\n send_lines_to_api \\\"Job $job ended with state: Error\\\" \\\"$job\\\"\\n fi\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set end=NOW(), state=$jobstate, result=LOAD_FILE('/tmp/$job.out'), done=$done WHERE id='$ID';\\\" &\\n}\\n\\npauseJob() {\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set state=2, result='waiting' WHERE id='$ID';\\\" &\\n}\\n\\npartialRestore() {\\n send_lines_to_api \\\"Starting partial restore...\\\" \\\"$job\\\" \\n chown -R mysql:mysql $BACKUPDIR \\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;install plugin BLACKHOLE soname 'ha_blackhole.so'\\\"\\n for dir in $(ls -d $BACKUPDIR/*/ | xargs -n 1 basename | grep -vE 'mysql|performance_schema|replication_manager_schema'); do\\n send_lines_to_api \\\"Restoring $dir...\\\" \\\"$job\\\" \\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;drop database IF EXISTS $dir; CREATE DATABASE $dir;\\\"\\n\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.ibd\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n cat $BACKUPDIR/$dir/$file.frm | sed -e 's/\\\\x06\\\\x00\\\\x49\\\\x6E\\\\x6E\\\\x6F\\\\x44\\\\x42\\\\x00\\\\x00\\\\x00/\\\\x09\\\\x00\\\\x42\\\\x4C\\\\x41\\\\x43\\\\x4B\\\\x48\\\\x4F\\\\x4C\\\\x45/g' >$DATADIR/$dir/mrm_pivo.frm\\n chown mysql:mysql $DATADIR/$dir/mrm_pivo.frm\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;ALTER TABLE $dir.mrm_pivo engine=innodb;RENAME TABLE $dir.mrm_pivo TO $dir.$file; ALTER TABLE $dir.$file DISCARD TABLESPACE;\\\"\\n mv $BACKUPDIR/$dir/$file.ibd $DATADIR/$dir/$file.ibd\\n mv $BACKUPDIR/$dir/$file.exp $DATADIR/$dir/$file.exp\\n mv $BACKUPDIR/$dir/$file.cfg $DATADIR/$dir/$file.cfg\\n mv $BACKUPDIR/$dir/$file.TRG $DATADIR/$dir/$file.TRG\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;ALTER TABLE $dir.$file IMPORT TABLESPACE\\\"\\n done\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.MYD\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/$dir/$file.* $DATADIR/$dir/\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE $dir.$file\\\"\\n done\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.CSV\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/$dir/$file.* $DATADIR/$dir/\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE $dir.$file\\\"\\n done\\n done\\n for file in $(find $BACKUPDIR/mysql/ -name \\\"*.MYD\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/mysql/$file.* $DATADIR/mysql/\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE mysql.$file\\\"\\n done\\n send_lines_to_api \\\"Setting GTID of the last change...\\\" \\\"$job\\\" \\n cat $BACKUPDIR/xtrabackup_info | grep binlog_pos | awk -F, '{ print $3 }' | sed -e 's/GTID of the last change/set sql_log_bin=0;set global gtid_slave_pos=/g' | $BINARY_CLIENT\\n send_lines_to_api \\\"Flushing privileges...\\\" \\\"$job\\\" \\n $BINARY_CLIENT -e\\\"set sql_log_bin=0;flush privileges;start slave;\\\"\\n}\\n\\n#######################\\n# JOB START HERE\\n#######################\\n\\nmkdir -p \\\"$CHECKPOINT_DIR\\\"\\nmkdir -p \\\"$LOCK_DIR\\\"\\necho \\\"\\\" > /tmp/curl_response.txt\\necho \\\"\\\" > /tmp/request.txt\\necho \\\"\\\" > /tmp/encrypt.txt\\n\\nfor job in \\\"${JOBS[@]}\\\"; do\\n\\n TASK=($(echo \\\"SELECT concat(id,'@',server,':',port) FROM replication_manager_schema.jobs WHERE task='$job' and done=0 AND state=0 order by id desc limit 1\\\" | $BINARY_CLIENT -N))\\n\\n ADDRESS=($(echo $TASK | awk -F@ '{ print $2 }'))\\n ID=($(echo $TASK | awk -F@ '{ print $1 }'))\\n\\n if [ \\\"$ID\\\" != \\\"\\\" ]; then\\n send_lines_to_api \\\"Job $job initiated. Clearing previous logs...\\\" \\\"$job\\\" \\n case \\\"$job\\\" in\\n mariabackup|xtrabackup)\\n rm -f \\\"/tmp/backup.out\\\"\\n ;;\\n reseedmariabackup|reseedxtrabackup)\\n rm -f \\\"/tmp/reseed.out\\\"\\n ;;\\n flashbackmariabackup|flashbackxtrabackup)\\n rm -f \\\"/tmp/flash.out\\\"\\n ;;\\n esac\\n\\n rm -f \\\"/tmp/$job.out\\\"\\n rm -f \\\"$CHECKPOINT_DIR/$job.checkpoint\\\"\\n fi\\n\\n\\n if [ \\\"$ADDRESS\\\" == \\\"\\\" ]; then\\n echo \\\"No $job needed\\\"\\n case \\\"$job\\\" in\\n start)\\n if [ \\\"curl -so /dev/null -w '%{response_code}' http://$REPLICATION_MANAGER_ADDR/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/need-start\\\" == \\\"200\\\" ]; then\\n curl http://$REPLICATION_MANAGER_ADDR/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/config | tar xzvf etc/* - -C $CONFDIR/../..\\n systemctl start mysql\\n fi\\n ;;\\n esac\\n else\\n\\n mkdir -p \\\"/tmp/$job.run\\\"\\n process_log_file \\\"$job\\\" &\\n trap 'rmdir \\\"/tmp/$job.run\\\"' EXIT\\n echo \\\"Processing $job\\\"\\n \\n #purge de past\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set done=1 WHERE done=0 AND task='$job' AND ID<>$ID;\\\"\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set state=1, result='processing' WHERE task='$job' AND ID=$ID;\\\"\\n case \\\"$job\\\" in\\n reseedxtrabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $XTRABACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/reseed.out\\\"\\n partialRestore\\n ;;\\n reseedmariabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | mbstream -x -C $BACKUPDIR\\n # mbstream -p, --parallel\\n $MARIADB_BACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/reseed.out\\\"\\n partialRestore\\n ;;\\n flashbackxtrabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $XTRABACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/flash.out\\\"\\n partialRestore\\n ;;\\n flashbackmariadbackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $MARIADB_BACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/flash.out\\\"\\n partialRestore\\n ;;\\n xtrabackup)\\n cd /docker-entrypoint-initdb.d\\n $XTRABACKUP --defaults-file=$MYSQL_CONF/my.cnf --backup -u$USER -H$MYSQL_SERVER -p$PASSWORD -P$MYSQL_PORT --stream=xbstream --target-dir=/tmp/ 2>\\\"/tmp/backup.out\\\" | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n ;;\\n mariabackup)\\n cd /docker-entrypoint-initdb.d\\n $MARIADB_BACKUP --innobackupex --defaults-file=$MYSQL_CONF/my.cnf --databases-exclude=.system --protocol=TCP $BINARY_CLIENT_PARAMETERS --stream=xbstream 2>\\\"/tmp/backup.out\\\" | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n ;;\\n error)\\n cat $ERROLOG | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n >$ERROLOG\\n ;;\\n slowquery)\\n cat $SLOWLOG | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n >$SLOWLOG\\n ;;\\n zfssnapback)\\n LASTSNAP=$(zfs list -r -t all | grep zp%%ENV:SERVICES_SVCNAME%%_pod01 | grep daily | sort -r | head -n 1 | cut -d\\\" \\\" -f1)\\n %%ENV:SERVICES_SVCNAME%% stop\\n zfs rollback $LASTSNAP\\n %%ENV:SERVICES_SVCNAME%% start\\n ;;\\n optimize)\\n $BINARY_CHECK -o $BINARY_CLIENT_PARAMETERS --all-databases --skip-write-binlog &>\\\"/tmp/$job.out\\\"\\n ;;\\n restart)\\n systemctl restart mysql\\n journalctl -u mysql >\\\"/tmp/$job.out\\\"\\n ;;\\n stop)\\n systemctl stop mysql\\n journalctl -u mysql >\\\"/tmp/$job.out\\\"\\n ;;\\n esac\\n doneJob \\\"$job\\\"\\n sleep 1 && rmdir \\\"/tmp/$job.run\\\" &\\n fi\\ndone\"}", + "var_updated": "2024-09-17 13:00:09", "var_name": "db_cnf_script_dbjobs_new", "id": 6299 }, @@ -4090,6 +4090,14 @@ "var_updated": "2024-07-29 19:28:56", "var_name": "db_cnf_readme", "id": 6303 + }, + { + "var_author": "admin Manager", + "var_class": "file", + "var_value": "{\"path\":\"%%ENV:SVC_CONF_ENV_BASE_DIR%%/%%ENV:POD%%/init/dbjobs_dev\",\"mode\":755,\"uid\":\"%%ENV:MYSQL_UID%%\",\"gid\":\"%%ENV:MYSQL_GID%%\",\"fmt\":\"#!/bin/bash\\nset -x\\nUSER=%%ENV:SVC_CONF_ENV_MYSQL_ROOT_USER%%\\nPASSWORD=$MYSQL_ROOT_PASSWORD\\nMYSQL_PORT=%%ENV:SERVER_PORT%%\\nMYSQL_SERVER=%%ENV:SERVER_HOST%%\\nCLUSTER_NAME=%%ENV:SVC_NAMESPACE%%\\nREPLICATION_MANAGER_ADDR=%%ENV:SVC_CONF_ENV_REPLICATION_MANAGER_ADDR%%\\nMYSQL_CONF=%%ENV:SVC_CONF_ENV_MYSQL_CONFDIR%%\\nDATADIR=%%ENV:SVC_CONF_ENV_MYSQL_DATADIR%%\\nBINARY_CLIENT_PARAMETERS=\\\"-u$USER -h$MYSQL_SERVER -p$PASSWORD -P$MYSQL_PORT\\\"\\n\\n# MariaDB binary paths\\nMARIADB_CLIENT=\\\"%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariadb $BINARY_CLIENT_PARAMETERS\\\"\\nMARIADB_CHECK=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariadb-check\\nMARIADB_DUMP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariadb-dump\\n\\n# MySQL binary paths\\nMYSQL_CLIENT=\\\"%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysql $BINARY_CLIENT_PARAMETERS\\\"\\nMYSQL_CHECK=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysqlcheck\\nMYSQL_DUMP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mysqldump\\n\\n# Determine which binary to use (prefer MariaDB, fallback to MySQL)\\nif [ -x \\\"$MARIADB_CLIENT\\\" ]; then\\n BINARY_CLIENT=$MARIADB_CLIENT\\n BINARY_CHECK=$MARIADB_CHECK\\n BINARY_DUMP=$MARIADB_DUMP\\n echo \\\"Using MariaDB binaries.\\\"\\nelif [ -x \\\"$MYSQL_CLIENT\\\" ]; then\\n BINARY_CLIENT=$MYSQL_CLIENT\\n BINARY_CHECK=$MYSQL_CHECK\\n BINARY_DUMP=$MYSQL_DUMP\\n echo \\\"Using MySQL binaries.\\\"\\nelse\\n echo \\\"Neither MariaDB nor MySQL binaries are available.\\\"\\n exit 1\\nfi\\n\\nSST_RECEIVER_PORT=%%ENV:SVC_CONF_ENV_SST_RECEIVER_PORT%%\\nSOCAT_BIND=%%ENV:SERVER_IP%%\\nMARIADB_BACKUP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/mariabackup\\nXTRABACKUP=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/xtrabackup\\nINNODBACKUPEX=%%ENV:SVC_CONF_ENV_CLIENT_BASEDIR%%/innobackupex\\n\\nERROLOG=%%ENV:SVC_CONF_ENV_ERROR_LOG%%\\nSLOWLOG=%%ENV:SVC_CONF_ENV_SLOW_LOG%%\\nBACKUPDIR=$DATADIR/.system/backup\\nTMP_DIR=/tmp\\n\\n# Directory where the logs are stored\\nLOG_DIR=\\\"$TMP_DIR\\\"\\n# Directory where the checkpoints are stored\\nCHECKPOINT_DIR=\\\"$TMP_DIR/checkpoints\\\"\\n# Directory where lock files are stored\\nLOCK_DIR=\\\"$TMP_DIR/locks\\\"\\nBATCH_SIZE=5\\nJOBS=(\\\"xtrabackup\\\" \\\"mariabackup\\\" \\\"error\\\" \\\"slowquery\\\" \\\"zfssnapback\\\" \\\"optimize\\\" \\\"reseedxtrabackup\\\" \\\"reseedmariabackup\\\" \\\"flashbackxtrabackup\\\" \\\"flashbackmariadbackup\\\" \\\"stop\\\" \\\"restart\\\" \\\"start\\\")\\n\\n# OSX need socat extra path\\nexport PATH=$PATH:/usr/local/bin\\n\\npad_pkcs7() {\\n local data=\\\"$1\\\"\\n local blocksize=32\\n local len=$(printf \\\"%s\\\" \\\"$data\\\" | wc -c)\\n local pad_len=$((blocksize - (len % blocksize)))\\n local padding=$(printf \\\"%${pad_len}s\\\" | tr ' ' '\\\\x01')\\n printf \\\"%s%s\\\" \\\"$data\\\" \\\"$padding\\\"\\n}\\n\\nderive_key() {\\n local key=$(echo -n \\\"$MYSQL_ROOT_PASSWORD\\\" | sha256sum | awk '{print $1}')\\n echo \\\"$key\\\"\\n}\\n\\nderive_iv() {\\n local iv=$(echo -n \\\"$MYSQL_ROOT_PASSWORD\\\" | md5sum | awk '{print $1}')\\n echo \\\"$iv\\\"\\n}\\n\\n# Function to encrypt data using AES-128 in CFB mode\\nencrypt_data() {\\n local key=$(derive_key)\\n local iv=$(derive_iv)\\n local padded=$(pad_pkcs7 \\\"$1\\\")\\n local encrypted=$(echo -n \\\"$padded\\\" | openssl aes-256-cbc -a -nosalt -K \\\"$key\\\" -iv \\\"$iv\\\" | tr -d '\\\\n')\\n # echo \\\"$encrypted\\\" >> /tmp/encrypted.txt\\n echo \\\"$encrypted\\\"\\n}\\n\\n# Function to send encrypted data to a JSON API using socat over HTTP\\nsend_encrypted_data_http() {\\n local api_host=\\\"$1\\\"\\n local api_port=\\\"$2\\\"\\n local api_host_port=\\\"$1:$2\\\"\\n local api_endpoint=\\\"$3\\\"\\n local data=$(encrypt_data \\\"$4\\\")\\n local json_data=\\\"{\\\\\\\"data\\\\\\\":\\\\\\\"$data\\\\\\\"}\\\"\\n\\n local request=\\\"POST $api_endpoint HTTP/1.1\\\\r\\\\nHost: $api_host\\\\r\\\\nContent-Type: application/json\\\\r\\\\nContent-Length: ${#json_data}\\\\r\\\\n\\\\r\\\\n$json_data\\\"\\n # Use socat to send the request over HTTP\\n local response=$(echo -en \\\"$request\\\" | socat - TCP:$api_host_port)\\n echo \\\"$request\\\" >> /tmp/request.txt\\n echo \\\"$response\\\"\\n}\\n\\n# Function to send encrypted data to a JSON API using socat over HTTPS\\nsend_encrypted_data_https() {\\n local api_host=\\\"$1\\\"\\n local api_port=\\\"$2\\\"\\n local api_host_port=\\\"$1:$2\\\"\\n local api_endpoint=\\\"$3\\\"\\n local data=$(encrypt_data \\\"$4\\\")\\n local json_data=\\\"{\\\\\\\"data\\\\\\\":\\\\\\\"$data\\\\\\\"}\\\"\\n\\n local request=\\\"POST $api_endpoint HTTP/1.1\\\\r\\\\nHost: $api_host\\\\r\\\\nContent-Type: application/json\\\\r\\\\nContent-Length: ${#json_data}\\\\r\\\\n\\\\r\\\\n$json_data\\\"\\n # Use socat with SSL and no verification to send the request over HTTPS\\n local response=$(echo -en \\\"$request\\\" | socat - OPENSSL:$api_host_port,verify=0)\\n echo \\\"$request\\\" >> /tmp/request.txt\\n echo \\\"$response\\\"\\n}\\n\\n# Wrapper function to choose between HTTP and HTTPS based on port\\nsend_encrypted_data() {\\n local api_host=$(echo \\\"$1\\\" | cut -d\\\":\\\" -f1)\\n local port=10005\\n local task=\\\"$2\\\"\\n local data=\\\"$3\\\"\\n local api_endpoint=\\\"/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/write-log/$task\\\"\\n\\n if [ \\\"$port\\\" = \\\"10005\\\" ]; then\\n send_encrypted_data_https \\\"$api_host\\\" \\\"$port\\\" \\\"$api_endpoint\\\" \\\"$data\\\"\\n else\\n send_encrypted_data_http \\\"$api_host\\\" \\\"$port\\\" \\\"$api_endpoint\\\" \\\"$data\\\"\\n fi\\n}\\n\\n# Function to send a batch of lines to the API and check for success with retry logic\\nsend_lines_to_api() {\\n local lines=\\\"$1\\\"\\n local job=\\\"$2\\\"\\n local address=\\\"${REPLICATION_MANAGER_ADDR}\\\"\\n local data=\\\"{\\\\\\\"server\\\\\\\":\\\\\\\"$MYSQL_SERVER:$MYSQL_PORT\\\\\\\",\\\\\\\"log\\\\\\\":\\\\\\\"$lines\\\\\\\"}\\\"\\n\\n local max_retries=3\\n local attempt=0\\n local success=false\\n\\n while ((attempt < max_retries)); do\\n # Capture response and HTTP status code\\n local response\\n response=$(send_encrypted_data \\\"$address\\\" \\\"$job\\\" \\\"$data\\\")\\n\\n echo \\\"$response\\\" >> /tmp/curl_response.txt\\n \\n # Extract HTTP status code\\n local http_code=$(echo \\\"$response\\\" | grep -oP '(?<=HTTP/1.1 )[0-9]{3}')\\n\\n if [ \\\"$http_code\\\" -eq 200 ]; then\\n echo \\\"API call successful for job: $job\\\"\\n success=true\\n break\\n else\\n echo \\\"API call failed for job: $job with status code: $http_code\\\"\\n cat /tmp/curl_response.txt\\n ((attempt++))\\n sleep 2 # Wait before retrying\\n fi\\n done\\n\\n if [ \\\"$success\\\" = false ]; then\\n echo \\\"API call failed after $max_retries attempts for job: $job\\\"\\n fi\\n}\\n\\n# Function to create a manual lock file\\ncreate_lock_file() {\\n local lock_file=\\\"$1\\\"\\n if [ -e \\\"$lock_file\\\" ]; then\\n echo \\\"Lock file exists. Exiting.\\\"\\n return 1\\n fi\\n touch \\\"$lock_file\\\"\\n return 0\\n}\\n\\n# Function to remove a manual lock file\\nremove_lock_file() {\\n local lock_file=\\\"$1\\\"\\n rm -f \\\"$lock_file\\\"\\n}\\n\\n# Function to wait for the .run file with a timeout\\nwait_for_run_lockdir() {\\n local run_lockdir=\\\"$1\\\"\\n local timeout=30\\n local start_time=$(date +%s)\\n\\n send_lines_to_api \\\"Waiting for $run_lockdir file...\\\\n\\\" \\\"$job\\\"\\n while [[ ! -d \\\"$run_lockdir\\\" ]]; do\\n sleep 0.5\\n local current_time=$(date +%s)\\n local elapsed=$((current_time - start_time))\\n if ((elapsed >= timeout)); then\\n send_lines_to_api \\\"Timeout reached while waiting for .run file.\\\\n\\\" \\\"$job\\\"\\n return 1\\n fi\\n done\\n send_lines_to_api \\\"$run_lockdir file found...\\\\n\\\" \\\"$job\\\"\\n return 0\\n}\\n\\n# Function to wait for the .run file with a timeout\\nwait_for_log_file() {\\n local logfile=\\\"$1\\\"\\n local timeout=60\\n local start_time=$(date +%s)\\n\\n send_lines_to_api \\\"Waiting for $logfile file...\\\\n\\\" \\\"$job\\\"\\n while [[ ! -f \\\"$logfile\\\" ]]; do\\n sleep 0.5\\n local current_time=$(date +%s)\\n local elapsed=$((current_time - start_time))\\n if ((elapsed >= timeout)); then\\n send_lines_to_api \\\"Timeout reached while waiting for $logfile file. Please check log manually if needed. \\\\n\\\" \\\"$job\\\"\\n return 1\\n fi\\n done\\n send_lines_to_api \\\"$logfile file found...\\\\n\\\" \\\"$job\\\"\\n return 0\\n}\\n\\nread_log_file() {\\n local logfile=\\\"$1\\\"\\n local checkpoint_file=$2\\n local last_read=$(cat $checkpoint_file)\\n local current_line=$((last_read + 1))\\n\\n while IFS= read -r line; do\\n escaped=$(printf '%s' \\\"$line\\\" | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g; s/\\\"/\\\\\\\\\\\"/g; s/\\\\n/\\\\\\\\n/g')\\n ((current_line++))\\n\\n if [[ ! -d \\\"$run_lockdir\\\" ]]; then\\n send_lines_to_api \\\"Run file has been deleted. Processing remaining lines.\\\\n\\\" \\\"$job\\\"\\n break\\n fi\\n\\n batch+=\\\"$escaped\\\\n\\\"\\n if ((current_line % BATCH_SIZE == 0)); then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n batch=\\\"\\\"\\n fi\\n echo \\\"$current_line\\\" >\\\"$checkpoint_file\\\"\\n\\n done < <(sed -n \\\"$current_line,${p}\\\" \\\"$log_file\\\")\\n\\n # Send any remaining lines in the batch after the first loop\\n if [[ -n \\\"$batch\\\" ]]; then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n fi\\n}\\n\\n# Function to process a log file\\nprocess_log_file() {\\n local job=\\\"$1\\\"\\n local log_file\\n case \\\"$job\\\" in\\n \\\"mariabackup\\\"|\\\"xtrabackup\\\")\\n log_file=\\\"$LOG_DIR/backup.out\\\"\\n ;;\\n \\\"reseedmariabackup\\\"|\\\"reseedxtrabackup\\\")\\n log_file=\\\"$LOG_DIR/reseed.out\\\"\\n ;;\\n \\\"flashbackmariabackup\\\"|\\\"flashbackxtrabackup\\\")\\n log_file=\\\"$LOG_DIR/flash.out\\\"\\n ;;\\n *)\\n log_file=\\\"$LOG_DIR/$job.out\\\"\\n ;;\\n esac\\n\\n local checkpoint_file=\\\"$CHECKPOINT_DIR/$job.checkpoint\\\"\\n local run_lockdir=\\\"$LOG_DIR/$job.run\\\"\\n local lock_file=\\\"$LOCK_DIR/${job}_lockfile\\\"\\n\\n if ! create_lock_file \\\"$lock_file\\\"; then\\n return\\n fi\\n\\n # Ensure lock file is removed on script exit\\n trap 'remove_lock_file \\\"$lock_file\\\"' EXIT\\n\\n if ! wait_for_run_lockdir \\\"$run_lockdir\\\"; then\\n remove_lock_file \\\"$lock_file\\\"\\n return\\n fi\\n\\n if ! wait_for_log_file \\\"$log_file\\\"; then\\n remove_lock_file \\\"$lock_file\\\"\\n return\\n fi\\n\\n local last_line=0\\n if [[ -f \\\"$checkpoint_file\\\" ]]; then\\n last_line=$(cat \\\"$checkpoint_file\\\")\\n fi\\n\\n send_lines_to_api \\\"Last checkpoint on \\\"$checkpoint_file\\\" is: $last_line.\\\\n\\\" \\\"$job\\\"\\n\\n local current_line=0\\n local batch=\\\"\\\"\\n local exec_once=1\\n\\n # processing until the end of the file and loop until run file deleted\\n while [[ -d \\\"$run_lockdir\\\" ]] || [[ \\\"$exec_once\\\" -eq 1 ]]; do\\n exec_once=0\\n read_log_file \\\"$log_file\\\" \\\"$checkpoint_file\\\"\\n done\\n\\n # If the run file was deleted, continue processing until the end of the file\\n while IFS= read -r line; do\\n escaped=$(printf '%s' \\\"$line\\\" | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g; s/\\\"/\\\\\\\\\\\"/g; s/\\\\n/\\\\\\\\n/g')\\n ((current_line++))\\n batch+=\\\"$escaped\\\\n\\\"\\n if ((current_line % BATCH_SIZE == 0)); then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n batch=\\\"\\\"\\n fi\\n echo \\\"$current_line\\\" >\\\"$checkpoint_file\\\"\\n done < <(tail -n +\\\"$((current_line - last_line))\\\" \\\"$log_file\\\")\\n\\n if [[ -n \\\"$batch\\\" ]]; then\\n send_lines_to_api \\\"$batch\\\" \\\"$job\\\"\\n fi\\n\\n send_lines_to_api \\\"Removing checkpoint file.\\\\n\\\" \\\"$job\\\"\\n rm -f \\\"$checkpoint_file\\\"\\n\\n remove_lock_file \\\"$lock_file\\\"\\n}\\n\\nsocatCleaner() {\\n kill -9 $(lsof -t -i:$SST_RECEIVER_PORT -sTCP:LISTEN)\\n}\\n\\ndoneJob() {\\n jobstate=3\\n done=1\\n case \\\"$job\\\" in\\n mariabackup | xtrabackup )\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/backup.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/backup.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n reseedmariabackup | reseedxtrabackup)\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/reseed.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/reseed.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n flashbackmariabackup | flashbackxtrabackup)\\n matches=$(sed -n '/[0-9]\\\\{4\\\\}-[0-9]\\\\{2\\\\}-[0-9]\\\\{2\\\\} [0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\}:[0-9]\\\\{2\\\\} completed OK!/p' /tmp/flash.out)\\n if [ ! -n \\\"$matches\\\" ]; then\\n jobstate=5\\n done=0\\n echo \\\"No successful record (complete OK!) found in /tmp/flash.out.\\\" >>/tmp/$job.out\\n fi\\n ;;\\n esac\\n \\n if [ $jobstate -eq 3 ]; then\\n send_lines_to_api \\\"Job $job ended with state: Finished\\\" \\\"$job\\\" \\n else\\n send_lines_to_api \\\"Job $job ended with state: Error\\\" \\\"$job\\\"\\n fi\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set end=NOW(), state=$jobstate, result=LOAD_FILE('/tmp/$job.out'), done=$done WHERE id='$ID';\\\" &\\n}\\n\\npauseJob() {\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set state=2, result='waiting' WHERE id='$ID';\\\" &\\n}\\n\\npartialRestore() {\\n send_lines_to_api \\\"Starting partial restore...\\\" \\\"$job\\\" \\n chown -R mysql:mysql $BACKUPDIR \\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;install plugin BLACKHOLE soname 'ha_blackhole.so'\\\"\\n for dir in $(ls -d $BACKUPDIR/*/ | xargs -n 1 basename | grep -vE 'mysql|performance_schema|replication_manager_schema'); do\\n send_lines_to_api \\\"Restoring $dir...\\\" \\\"$job\\\" \\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;drop database IF EXISTS $dir; CREATE DATABASE $dir;\\\"\\n\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.ibd\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n cat $BACKUPDIR/$dir/$file.frm | sed -e 's/\\\\x06\\\\x00\\\\x49\\\\x6E\\\\x6E\\\\x6F\\\\x44\\\\x42\\\\x00\\\\x00\\\\x00/\\\\x09\\\\x00\\\\x42\\\\x4C\\\\x41\\\\x43\\\\x4B\\\\x48\\\\x4F\\\\x4C\\\\x45/g' >$DATADIR/$dir/mrm_pivo.frm\\n chown mysql:mysql $DATADIR/$dir/mrm_pivo.frm\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;ALTER TABLE $dir.mrm_pivo engine=innodb;RENAME TABLE $dir.mrm_pivo TO $dir.$file; ALTER TABLE $dir.$file DISCARD TABLESPACE;\\\"\\n mv $BACKUPDIR/$dir/$file.ibd $DATADIR/$dir/$file.ibd\\n mv $BACKUPDIR/$dir/$file.exp $DATADIR/$dir/$file.exp\\n mv $BACKUPDIR/$dir/$file.cfg $DATADIR/$dir/$file.cfg\\n mv $BACKUPDIR/$dir/$file.TRG $DATADIR/$dir/$file.TRG\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;ALTER TABLE $dir.$file IMPORT TABLESPACE\\\"\\n done\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.MYD\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/$dir/$file.* $DATADIR/$dir/\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE $dir.$file\\\"\\n done\\n for file in $(find $BACKUPDIR/$dir/ -name \\\"*.CSV\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/$dir/$file.* $DATADIR/$dir/\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE $dir.$file\\\"\\n done\\n done\\n for file in $(find $BACKUPDIR/mysql/ -name \\\"*.MYD\\\" | xargs -n 1 basename | cut -d'.' --complement -f2-); do\\n mv $BACKUPDIR/mysql/$file.* $DATADIR/mysql/\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;FLUSH TABLE mysql.$file\\\"\\n done\\n send_lines_to_api \\\"Setting GTID of the last change...\\\" \\\"$job\\\" \\n cat $BACKUPDIR/xtrabackup_info | grep binlog_pos | awk -F, '{ print $3 }' | sed -e 's/GTID of the last change/set sql_log_bin=0;set global gtid_slave_pos=/g' | $BINARY_CLIENT\\n send_lines_to_api \\\"Flushing privileges...\\\" \\\"$job\\\" \\n $BINARY_CLIENT -e\\\"set sql_log_bin=0;flush privileges;start slave;\\\"\\n}\\n\\n#######################\\n# JOB START HERE\\n#######################\\n\\nmkdir -p \\\"$CHECKPOINT_DIR\\\"\\nmkdir -p \\\"$LOCK_DIR\\\"\\necho \\\"\\\" > /tmp/curl_response.txt\\necho \\\"\\\" > /tmp/request.txt\\necho \\\"\\\" > /tmp/encrypt.txt\\n\\nfor job in \\\"${JOBS[@]}\\\"; do\\n\\n TASK=($(echo \\\"SELECT concat(id,'@',server,':',port) FROM replication_manager_schema.jobs WHERE task='$job' and done=0 AND state=0 order by id desc limit 1\\\" | $BINARY_CLIENT -N))\\n\\n ADDRESS=($(echo $TASK | awk -F@ '{ print $2 }'))\\n ID=($(echo $TASK | awk -F@ '{ print $1 }'))\\n\\n if [ \\\"$ID\\\" != \\\"\\\" ]; then\\n send_lines_to_api \\\"Job $job initiated. Clearing previous logs...\\\" \\\"$job\\\" \\n case \\\"$job\\\" in\\n mariabackup|xtrabackup)\\n rm -f \\\"/tmp/backup.out\\\"\\n ;;\\n reseedmariabackup|reseedxtrabackup)\\n rm -f \\\"/tmp/reseed.out\\\"\\n ;;\\n flashbackmariabackup|flashbackxtrabackup)\\n rm -f \\\"/tmp/flash.out\\\"\\n ;;\\n esac\\n\\n rm -f \\\"/tmp/$job.out\\\"\\n rm -f \\\"$CHECKPOINT_DIR/$job.checkpoint\\\"\\n fi\\n\\n\\n if [ \\\"$ADDRESS\\\" == \\\"\\\" ]; then\\n echo \\\"No $job needed\\\"\\n case \\\"$job\\\" in\\n start)\\n if [ \\\"curl -so /dev/null -w '%{response_code}' http://$REPLICATION_MANAGER_ADDR/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/need-start\\\" == \\\"200\\\" ]; then\\n curl http://$REPLICATION_MANAGER_ADDR/api/clusters/$CLUSTER_NAME/servers/$MYSQL_SERVER/$MYSQL_PORT/config | tar xzvf etc/* - -C $CONFDIR/../..\\n systemctl start mysql\\n fi\\n ;;\\n esac\\n else\\n\\n mkdir -p \\\"/tmp/$job.run\\\"\\n process_log_file \\\"$job\\\" &\\n trap 'rmdir \\\"/tmp/$job.run\\\"' EXIT\\n echo \\\"Processing $job\\\"\\n \\n #purge de past\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set done=1 WHERE done=0 AND task='$job' AND ID<>$ID;\\\"\\n $BINARY_CLIENT -e \\\"set sql_log_bin=0;UPDATE replication_manager_schema.jobs set state=1, result='processing' WHERE task='$job' AND ID=$ID;\\\"\\n case \\\"$job\\\" in\\n reseedxtrabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $XTRABACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/reseed.out\\\"\\n partialRestore\\n ;;\\n reseedmariabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | mbstream -x -C $BACKUPDIR\\n # mbstream -p, --parallel\\n $MARIADB_BACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/reseed.out\\\"\\n partialRestore\\n ;;\\n flashbackxtrabackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $XTRABACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/flash.out\\\"\\n partialRestore\\n ;;\\n flashbackmariadbackup)\\n rm -rf $BACKUPDIR\\n mkdir -p $BACKUPDIR\\n socatCleaner\\n echo \\\"Waiting backup.\\\" >\\\"/tmp/$job.out\\\"\\n pauseJob \\\"$job\\\"\\n socat -u TCP-LISTEN:$SST_RECEIVER_PORT,reuseaddr,bind=$SOCAT_BIND STDOUT | xbstream -x -C $BACKUPDIR\\n $MARIADB_BACKUP --prepare --export --target-dir=$BACKUPDIR 2>\\\"/tmp/flash.out\\\"\\n partialRestore\\n ;;\\n xtrabackup)\\n cd /docker-entrypoint-initdb.d\\n $XTRABACKUP --defaults-file=$MYSQL_CONF/my.cnf --backup -u$USER -H$MYSQL_SERVER -p$PASSWORD -P$MYSQL_PORT --stream=xbstream --target-dir=/tmp/ 2>\\\"/tmp/backup.out\\\" | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n ;;\\n mariabackup)\\n cd /docker-entrypoint-initdb.d\\n $MARIADB_BACKUP --innobackupex --defaults-file=$MYSQL_CONF/my.cnf --databases-exclude=.system --protocol=TCP $BINARY_CLIENT_PARAMETERS --stream=xbstream 2>\\\"/tmp/backup.out\\\" | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n ;;\\n error)\\n cat $ERROLOG | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n >$ERROLOG\\n ;;\\n slowquery)\\n cat $SLOWLOG | socat -u stdio TCP:$ADDRESS &>\\\"/tmp/$job.out\\\"\\n >$SLOWLOG\\n ;;\\n zfssnapback)\\n LASTSNAP=$(zfs list -r -t all | grep zp%%ENV:SERVICES_SVCNAME%%_pod01 | grep daily | sort -r | head -n 1 | cut -d\\\" \\\" -f1)\\n %%ENV:SERVICES_SVCNAME%% stop\\n zfs rollback $LASTSNAP\\n %%ENV:SERVICES_SVCNAME%% start\\n ;;\\n optimize)\\n $BINARY_CHECK -o $BINARY_CLIENT_PARAMETERS --all-databases --skip-write-binlog &>\\\"/tmp/$job.out\\\"\\n ;;\\n restart)\\n systemctl restart mysql\\n journalctl -u mysql >\\\"/tmp/$job.out\\\"\\n ;;\\n stop)\\n systemctl stop mysql\\n journalctl -u mysql >\\\"/tmp/$job.out\\\"\\n ;;\\n esac\\n doneJob \\\"$job\\\"\\n sleep 1 && rmdir \\\"/tmp/$job.run\\\" &\\n fi\\ndone\"}", + "var_updated": "2024-09-17 12:34:17", + "var_name": "db_cnf_script_dbjobs_dev", + "id": 6342 } ], "ruleset_public": false,