diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2017-08-21 13:35:00 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2017-08-21 13:35:00 +0300 |
commit | c23efc7d50530570e6c13207f3c76adcb9237346 (patch) | |
tree | 7c57ca7a1dc61590019abb5608c2b19327f8ed7c /scripts | |
parent | 06106c01481401b6d7ef4309391ca2f66242cc85 (diff) | |
parent | f1af2114993f884b1a6dc34fb1d972ead08f1966 (diff) | |
download | mariadb-git-c23efc7d50530570e6c13207f3c76adcb9237346.tar.gz |
Merge remote-tracking branch 'origin/10.0-galera' into 10.1
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/wsrep_sst_common.sh | 57 | ||||
-rw-r--r-- | scripts/wsrep_sst_mysqldump.sh | 6 | ||||
-rw-r--r-- | scripts/wsrep_sst_rsync.sh | 32 | ||||
-rw-r--r-- | scripts/wsrep_sst_xtrabackup-v2.sh | 396 |
4 files changed, 376 insertions, 115 deletions
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index f173a861e85..723fd311f88 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -32,6 +32,22 @@ while [ $# -gt 0 ]; do case "$1" in '--address') readonly WSREP_SST_OPT_ADDR="$2" + # + # Break address string into host:port/path parts + # + if echo $WSREP_SST_OPT_ADDR | grep -qe '^\[.*\]' + then + # IPv6 notation + readonly WSREP_SST_OPT_HOST=${WSREP_SST_OPT_ADDR/\]*/\]} + readonly WSREP_SST_OPT_HOST_UNESCAPED=$(echo $WSREP_SST_OPT_HOST | \ + cut -d '[' -f 2 | cut -d ']' -f 1) + else + # "traditional" notation + readonly WSREP_SST_OPT_HOST=${WSREP_SST_OPT_ADDR%%[:/]*} + fi + readonly WSREP_SST_OPT_PORT=$(echo $WSREP_SST_OPT_ADDR | \ + cut -d ']' -f 2 | cut -s -d ':' -f 2 | cut -d '/' -f 1) + readonly WSREP_SST_OPT_PATH=${WSREP_SST_OPT_ADDR#*/} shift ;; '--bypass') @@ -181,6 +197,11 @@ wsrep_log_error() wsrep_log "[ERROR] $*" } +wsrep_log_warning() +{ + wsrep_log "[WARNING] $*" +} + wsrep_log_info() { wsrep_log "[INFO] $*" @@ -214,3 +235,39 @@ wsrep_check_programs() return $ret } + +# +# user can specify xtrabackup specific settings that will be used during sst +# process like encryption, etc..... +# parse such configuration option. (group for xb settings is [sst] in my.cnf +# +# 1st param: group : name of the config file section, e.g. mysqld +# 2nd param: var : name of the variable in the section, e.g. server-id +# 3rd param: - : default value for the param +parse_cnf() +{ + local group=$1 + local var=$2 + local reval="" + + # print the default settings for given group using my_print_default. + # normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin) + # then grep for needed variable + # finally get the variable value (if variables has been specified multiple time use the last value only) + + # look in group+suffix + if [[ -n $WSREP_SST_OPT_CONF_SUFFIX ]]; then + reval=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF "${group}${WSREP_SST_OPT_CONF_SUFFIX}" | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) + fi + + # look in group + if [[ -z $reval ]]; then + reval=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) + fi + + # use default if we haven't found a value + if [[ -z $reval ]]; then + [[ -n $3 ]] && reval=$3 + fi + echo $reval +} diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 5f25c2c9d13..59d9a3c5c9c 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -30,6 +30,7 @@ local_ip() { [ "$1" = "127.0.0.1" ] && return 0 [ "$1" = "localhost" ] && return 0 + [ "$1" = "[::1]" ] && return 0 [ "$1" = "$(hostname -s)" ] && return 0 [ "$1" = "$(hostname -f)" ] && return 0 [ "$1" = "$(hostname -d)" ] && return 0 @@ -116,8 +117,9 @@ GTID_BINLOG_STATE=$(echo "SHOW GLOBAL VARIABLES LIKE 'gtid_binlog_state'" |\ $MYSQL_CLIENT $AUTH -S$WSREP_SST_OPT_SOCKET --disable-reconnect --connect_timeout=10 |\ tail -1 | awk -F ' ' '{ print $2 }') -MYSQL="$MYSQL_CLIENT $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ -"--disable-reconnect --connect_timeout=10" +MYSQL="$MYSQL_CLIENT --defaults-extra-file=$WSREP_SST_OPT_CONF "\ +"$AUTH -h${WSREP_SST_OPT_HOST_UNESCAPED:-$WSREP_SST_OPT_HOST} "\ +"-P$WSREP_SST_OPT_PORT --disable-reconnect --connect_timeout=10" # Check if binary logging is enabled on the joiner node. # Note: SELECT cannot be used at this point. diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 10d6896accd..c6e8a7ef4e1 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -67,6 +67,11 @@ check_pid_and_port() exit 2 # ENOENT fi + if ! which lsof > /dev/null; then + wsrep_log_error "lsof tool not found in PATH! Make sure you have it installed." + exit 2 # ENOENT + fi + local port_info=$(lsof -i :$rsync_port -Pn 2>/dev/null | \ grep "(LISTEN)") local is_rsync=$(echo $port_info | \ @@ -97,9 +102,19 @@ fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf if [ -z "$WSREP_LOG_DIR" ]; then - WSREP_LOG_DIR=$($MY_PRINT_DEFAULTS --mysqld \ - | grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \ - | cut -b 29- ) + WSREP_LOG_DIR=$(parse_cnf mariadb-10.0 innodb_log_group_home_dir "") +fi +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld innodb_log_group_home_dir "") +fi +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf server innodb_log_group_home_dir "") +fi +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mariadb innodb_log_group_home_dir "") +fi +if [ -z "$WSREP_LOG_DIR" ]; then + WSREP_LOG_DIR=$(parse_cnf mysqld-10.0 innodb_log_group_home_dir "") fi if [ -n "$WSREP_LOG_DIR" ]; then @@ -222,8 +237,8 @@ then [ "$OS" == "Linux" ] && count=$(grep -c processor /proc/cpuinfo) [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ] && count=$(sysctl -n hw.ncpu) - find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" -print0 | \ - xargs -I{} -0 -P $count \ + find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" \ + -print0 | xargs -I{} -0 -P $count \ rsync --owner --group --perms --links --specials \ --ignore-times --inplace --recursive --delete --quiet \ $WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \ @@ -284,9 +299,9 @@ then RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" if [ -n "${MYSQL_TMP_DIR:-}" ] ; then - SILENT="log file = $MYSQL_TMP_DIR/rsynd.log" + SILENT="log file = $MYSQL_TMP_DIR/rsyncd.log" else - SILENT="" + SILENT="" fi cat << EOF > "$RSYNC_CONF" @@ -304,6 +319,7 @@ EOF # rm -rf "$DATA"/ib_logfile* # we don't want old logs around # listen at all interfaces (for firewalled setups) + readonly RSYNC_PORT=${WSREP_SST_OPT_PORT:-4444} rsync --daemon --no-detach --port $RSYNC_PORT --config "$RSYNC_CONF" & RSYNC_REAL_PID=$! @@ -312,7 +328,7 @@ EOF sleep 0.2 done - echo "ready $ADDR/$MODULE" + echo "ready $WSREP_SST_OPT_HOST:$RSYNC_PORT/$MODULE" # wait for SST to complete by monitoring magic file while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \ diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 565e62e4dbe..78a7d76da09 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -35,6 +35,7 @@ XTRABACKUP_PID="" SST_PORT="" REMOTEIP="" REMOTEHOST="" +tca="" tcert="" tpem="" tkey="" @@ -48,7 +49,6 @@ rlimit="" # Initially stagemsg="${WSREP_SST_OPT_ROLE}" cpat="" -speciald=1 ib_home_dir="" ib_log_dir="" ib_undo_dir="" @@ -72,6 +72,11 @@ xtmpdir="" scomp="" sdecomp="" +ssl_dhparams="" + +ssl_cert="" +ssl_ca="" +ssl_key="" # Required for backup locks # For backup locks it is 1 sent by joiner @@ -151,6 +156,10 @@ get_keys() if [[ -z $ekey ]];then ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" else + wsrep_log_warning "Using the 'encrypt-key' option causes the encryption key" + wsrep_log_warning "to be set via the command-line and is considered insecure." + wsrep_log_warning "It is recommended to use the 'encrypt-key-file' option instead." + ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey" fi @@ -161,6 +170,86 @@ get_keys() stagemsg+="-XB-Encrypted" } +# +# If the ssl_dhparams variable is already set, uses that as a source +# of dh parameters for OpenSSL. Otherwise, looks for dhparams.pem in the +# datadir, and creates it there if it can't find the file. +# No input parameters +# +check_for_dhparams() +{ + if [[ -z "$ssl_dhparams" ]]; then + if ! [[ -r "$DATA/dhparams.pem" ]]; then + wsrep_check_programs openssl + wsrep_log_info "Could not find dhparams file, creating $DATA/dhparams.pem" + + if ! openssl dhparam -out "$DATA/dhparams.pem" 2048 >/dev/null 2>&1 + then + wsrep_log_error "******** FATAL ERROR ********************************* " + wsrep_log_error "* Could not create the dhparams.pem file with OpenSSL. " + wsrep_log_error "****************************************************** " + exit 22 + fi + fi + ssl_dhparams="$DATA/dhparams.pem" + fi +} + +# +# verifies that the certificate matches the private key +# doing this will save us having to wait for a timeout that would +# otherwise occur. +# +# 1st param: path to the cert +# 2nd param: path to the private key +# +verify_cert_matches_key() +{ + local cert_path=$1 + local key_path=$2 + + wsrep_check_programs openssl diff + + # generate the public key from the cert and the key + # they should match (otherwise we can't create an SSL connection) + if ! diff <(openssl x509 -in "$cert_path" -pubkey -noout) <(openssl rsa -in "$key_path" -pubout 2>/dev/null) >/dev/null 2>&1 + then + wsrep_log_error "******** FATAL ERROR ************************* " + wsrep_log_error "* The certifcate and private key do not match. " + wsrep_log_error "* Please check your certificate and key files. " + wsrep_log_error "********************************************** " + exit 22 + fi +} + +# Checks to see if the file exists +# If the file does not exist (or cannot be read), issues an error +# and exits +# +# 1st param: file name to be checked (for read access) +# 2nd param: 1st error message (header) +# 3rd param: 2nd error message (footer, optional) +# +verify_file_exists() +{ + local file_path=$1 + local error_message1=$2 + local error_message2=$3 + + if ! [[ -r "$file_path" ]]; then + wsrep_log_error "******** FATAL ERROR ************************* " + wsrep_log_error "* $error_message1 " + wsrep_log_error "* Could not find/access : $file_path " + + if ! [[ -z "$error_message2" ]]; then + wsrep_log_error "* $error_message2 " + fi + + wsrep_log_error "********************************************** " + exit 22 + fi +} + get_transfer() { if [[ -z $SST_PORT ]];then @@ -174,15 +263,25 @@ get_transfer() wsrep_log_error "nc(netcat) not found in path: $PATH" exit 2 fi + + if [[ $encrypt -eq 2 || $encrypt -eq 3 || $encrypt -eq 4 ]]; then + wsrep_log_error "******** FATAL ERROR *********************** " + wsrep_log_error "* Using SSL encryption (encrypt= 2, 3, or 4) " + wsrep_log_error "* is not supported when using nc(netcat). " + wsrep_log_error "******************************************** " + exit 22 + fi + wsrep_log_info "Using netcat as streamer" if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - if nc -h 2>&1 | grep -q ncat;then - tcmd="nc -l ${TSST_PORT}" + if nc -h 2>&1 | grep -q ncat; then + tcmd="nc $sockopt -l ${TSST_PORT}" else - tcmd="nc -dl ${TSST_PORT}" + tcmd="nc $sockopt -dl ${TSST_PORT}" fi else - tcmd="nc ${REMOTEIP} ${TSST_PORT}" + # netcat doesn't understand [] around IPv6 address + tcmd="nc ${REMOTEIP//[\[\]]/} ${TSST_PORT}" fi else tfmt='socat' @@ -192,74 +291,112 @@ get_transfer() exit 2 fi - if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q "WITH_OPENSSL 1";then - wsrep_log_error "Encryption requested, but socat is not OpenSSL enabled (encrypt=$encrypt)" - exit 2 - fi + donor_extra="" + joiner_extra="" + if [[ $encrypt -eq 2 || $encrypt -eq 3 || $encrypt -eq 4 ]]; then + if ! socat -V | grep -q WITH_OPENSSL; then + wsrep_log_error "******** FATAL ERROR ****************** " + wsrep_log_error "* socat is not openssl enabled. " + wsrep_log_error "* Unable to encrypt SST communications. " + wsrep_log_error "*************************************** " + exit 2 + fi - if [[ $encrypt -eq 2 ]];then - wsrep_log_info "Using openssl based encryption with socat: with crt and pem" - if [[ -z $tpem || -z $tcert ]];then - wsrep_log_error "Both PEM and CRT files required" - exit 22 + # Determine the socat version + SOCAT_VERSION=`socat -V 2>&1 | grep -oe '[0-9]\.[0-9][\.0-9]*' | head -n1` + if [[ -z "$SOCAT_VERSION" ]]; then + wsrep_log_error "******** FATAL ERROR **************** " + wsrep_log_error "* Cannot determine the socat version. " + wsrep_log_error "************************************* " + exit 2 fi + + # socat versions < 1.7.3 will have 512-bit dhparams (too small) + # so create 2048-bit dhparams and send that as a parameter + # socat version >= 1.7.3, checks to see if the peername matches the hostname + # set commonname="" to disable the peername checks + # + if ! check_for_version "$SOCAT_VERSION" "1.7.3"; then + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then + # dhparams check (will create ssl_dhparams if needed) + check_for_dhparams + joiner_extra=",dhparam=$ssl_dhparams" + fi + fi + if check_for_version "$SOCAT_VERSION" "1.7.3"; then + donor_extra=',commonname=""' + fi + fi + + if [[ $encrypt -eq 2 ]]; then + wsrep_log_warning "**** WARNING **** encrypt=2 is deprecated and will be removed in a future release" + wsrep_log_info "Using openssl based encryption with socat: with crt and ca" + + verify_file_exists "$tcert" "Both certificate and CA files are required." \ + "Please check the 'tcert' option. " + verify_file_exists "$tca" "Both certificate and CA files are required." \ + "Please check the 'tca' option. " + stagemsg+="-OpenSSL-Encrypted-2" if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - wsrep_log_info "Decrypting with cert=${tpem}, cafile=${tcert}" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},cafile=${tcert}${sockopt} stdio" + wsrep_log_info "Decrypting with CERT: $tcert, CA: $tca" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},cafile=${tca}${joiner_extra}${sockopt} stdio" else - wsrep_log_info "Encrypting with cert=${tpem}, cafile=${tcert}" - tcmd="socat -u stdio openssl-connect:${REMOTEHOST}:${TSST_PORT},cert=${tpem},cafile=${tcert}${sockopt}" + wsrep_log_info "Encrypting with CERT: $tcert, CA: $tca" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tcert},cafile=${tca}${donor_extra}${sockopt}" fi elif [[ $encrypt -eq 3 ]];then + wsrep_log_warning "**** WARNING **** encrypt=3 is deprecated and will be removed in a future release" wsrep_log_info "Using openssl based encryption with socat: with key and crt" - if [[ -z $tpem || -z $tkey ]];then - wsrep_log_error "Both certificate and key files required" - exit 22 - fi + + verify_file_exists "$tcert" "Both certificate and key files are required." \ + "Please check the 'tcert' option. " + verify_file_exists "$tkey" "Both certificate and key files are required." \ + "Please check the 'tkey' option. " + stagemsg+="-OpenSSL-Encrypted-3" if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then - if [[ -z $tcert ]];then - wsrep_log_info "Decrypting with cert=${tpem}, key=${tkey}, verify=0" + wsrep_log_info "Decrypting with CERT: $tcert, KEY: $tkey" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},key=${tkey},verify=0${joiner_extra}${sockopt} stdio" tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},key=${tkey},verify=0${sockopt} stdio" else - wsrep_log_info "Decrypting with cert=${tpem}, key=${tkey}, cafile=${tcert}" - tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tpem},key=${tkey},cafile=${tcert}${sockopt} stdio" - fi + wsrep_log_info "Encrypting with CERT: $tcert, KEY: $tkey" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tcert},key=${tkey},verify=0${sockopt}" + fi + elif [[ $encrypt -eq 4 ]]; then + wsrep_log_info "Using openssl based encryption with socat: with key, crt, and ca" + + verify_file_exists "$ssl_ca" "CA, certificate, and key files are required." \ + "Please check the 'ssl-ca' option. " + verify_file_exists "$ssl_cert" "CA, certificate, and key files are required." \ + "Please check the 'ssl-cert' option. " + verify_file_exists "$ssl_key" "CA, certificate, and key files are required." \ + "Please check the 'ssl-key' option. " + + # Check to see that the key matches the cert + verify_cert_matches_key $ssl_cert $ssl_key + + stagemsg+="-OpenSSL-Encrypted-4" + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then + wsrep_log_info "Decrypting with CERT: $ssl_cert, KEY: $ssl_key, CA: $ssl_ca" + tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${joiner_extra}${sockopt} stdio" else - if [[ -z $tcert ]];then - wsrep_log_info "Encrypting with cert=${tpem}, key=${tkey}, verify=0" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tpem},key=${tkey},verify=0${sockopt}" - else - wsrep_log_info "Encrypting with cert=${tpem}, key=${tkey}, cafile=${tcert}" - tcmd="socat -u stdio openssl-connect:${REMOTEHOST}:${TSST_PORT},cert=${tpem},key=${tkey},cafile=${tcert}${sockopt}" - fi + wsrep_log_info "Encrypting with CERT: $ssl_cert, KEY: $ssl_key, CA: $ssl_ca" + tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${donor_extra}${sockopt}" fi - else - if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then + else + if [[ $encrypt -eq 1 ]]; then + wsrep_log_warning "**** WARNING **** encrypt=1 is deprecated and will be removed in a future release" + fi + + if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" else tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" fi fi fi - -} - -parse_cnf() -{ - local group=$1 - local var=$2 - # print the default settings for given group using my_print_default. - # normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin) - # then grep for needed variable - # finally get the variable value (if variables has been specified multiple time use the last value only) - reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) - if [[ -z $reval ]];then - [[ -n $3 ]] && reval=$3 - fi - echo $reval } get_footprint() @@ -309,15 +446,15 @@ read_cnf() { sfmt=$(parse_cnf sst streamfmt "xbstream") tfmt=$(parse_cnf sst transferfmt "socat") - tcert=$(parse_cnf sst tca "") - tpem=$(parse_cnf sst tcert "") + tca=$(parse_cnf sst tca "") + tcert=$(parse_cnf sst tcert "") tkey=$(parse_cnf sst tkey "") encrypt=$(parse_cnf sst encrypt 0) sockopt=$(parse_cnf sst sockopt "") progress=$(parse_cnf sst progress "") rebuild=$(parse_cnf sst rebuild 0) ttime=$(parse_cnf sst time 0) - cpat=$(parse_cnf sst cpat '.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + cpat=$(parse_cnf sst cpat '.*\.pem$\|.*init\.ok$\|.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') ealgo=$(parse_cnf xtrabackup encrypt "") ekey=$(parse_cnf xtrabackup encrypt-key "") ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") @@ -331,9 +468,23 @@ read_cnf() ekey=$(parse_cnf sst encrypt-key "") ekeyfile=$(parse_cnf sst encrypt-key-file "") fi + + # Pull the parameters needed for encrypt=4 + ssl_ca=$(parse_cnf sst ssl-ca "") + if [[ -z "$ssl_ca" ]]; then + ssl_ca=$(parse_cnf mysqld ssl-ca "") + fi + ssl_cert=$(parse_cnf sst ssl-cert "") + if [[ -z "$ssl_cert" ]]; then + ssl_cert=$(parse_cnf mysqld ssl-cert "") + fi + ssl_key=$(parse_cnf sst ssl-key "") + if [[ -z "$ssl_key" ]]; then + ssl_key=$(parse_cnf mysqld ssl-key "") + fi + rlimit=$(parse_cnf sst rlimit "") uextra=$(parse_cnf sst use-extra 0) - speciald=$(parse_cnf sst sst-special-dirs 1) iopts=$(parse_cnf sst inno-backup-opts "") iapts=$(parse_cnf sst inno-apply-opts "") impts=$(parse_cnf sst inno-move-opts "") @@ -342,13 +493,8 @@ read_cnf() ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}") ssystag+="-" - if [[ $speciald -eq 0 ]];then - wsrep_log_error "sst-special-dirs equal to 0 is not supported, falling back to 1" - speciald=1 - fi - if [[ $ssyslog -ne -1 ]];then - if $MY_PRINT_DEFAULTS mysqld_safe | tr '_' '-' | grep -q -- "--syslog";then + if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld_safe | tr '_' '-' | grep -q -- "--syslog";then ssyslog=1 fi fi @@ -494,32 +640,30 @@ kill_xtrabackup() setup_ports() { if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then - SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') - REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') - REMOTEHOST=$(getent hosts $REMOTEIP | awk '{ print $2 }') - if [[ -z $REMOTEHOST ]];then - REMOTEHOST=$REMOTEIP - fi - lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') - sst_ver=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $5 }') + SST_PORT=$WSREP_SST_OPT_PORT + REMOTEIP=$WSREP_SST_OPT_HOST + lsn=$(echo $WSREP_SST_OPT_PATH | awk -F '[/]' '{ print $2 }') + sst_ver=$(echo $WSREP_SST_OPT_PATH | awk -F '[/]' '{ print $3 }') else - SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') + SST_PORT=$WSREP_SST_OPT_PORT fi } -# waits ~10 seconds for nc to open the port and then reports ready +# waits ~1 minute for nc/socat to open the port and then reports ready # (regardless of timeout) wait_for_listen() { - local PORT=$1 - local ADDR=$2 + local HOST=$1 + local PORT=$2 local MODULE=$3 - for i in {1..50} + + for i in {1..300} do ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break sleep 0.2 done - echo "ready ${ADDR}/${MODULE}//$sst_ver" + + echo "ready ${HOST}:${PORT}/${MODULE}//$sst_ver" } check_extra() @@ -527,7 +671,7 @@ check_extra() local use_socket=1 if [[ $uextra -eq 1 ]];then if $MY_PRINT_DEFAULTS --mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$($MY_PRINT_DEFAULTS --mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + local eport=$($MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. @@ -622,11 +766,64 @@ send_donor() } +# Returns the version string in a standardized format +# Input "1.2.3" => echoes "010203" +# Wrongly formatted values => echoes "000000" +normalize_version() +{ + local major=0 + local minor=0 + local patch=0 + + # Only parses purely numeric version numbers, 1.2.3 + # Everything after the first three values are ignored + if [[ $1 =~ ^([0-9]+)\.([0-9]+)\.?([0-9]*)([\.0-9])*$ ]]; then + major=${BASH_REMATCH[1]} + minor=${BASH_REMATCH[2]} + patch=${BASH_REMATCH[3]} + fi + + printf %02d%02d%02d $major $minor $patch +} + +# Compares two version strings +# The first parameter is the version to be checked +# The second parameter is the minimum version required +# Returns 1 (failure) if $1 >= $2, 0 (success) otherwise +check_for_version() +{ + local local_version_str="$( normalize_version $1 )" + local required_version_str="$( normalize_version $2 )" + + if [[ "$local_version_str" < "$required_version_str" ]]; then + return 1 + else + return 0 + fi +} + + if [[ ! -x `which $INNOBACKUPEX_BIN` ]];then wsrep_log_error "innobackupex not in path: $PATH" exit 2 fi +# check the version, we require XB-2.4 to ensure that we can pass the +# datadir via the command-line option +XB_REQUIRED_VERSION="2.3.5" + +XB_VERSION=`$INNOBACKUPEX_BIN --version 2>&1 | grep -oe '[0-9]\.[0-9][\.0-9]*' | head -n1` +if [[ -z $XB_VERSION ]]; then + wsrep_log_error "FATAL: Cannot determine the $INNOBACKUPEX_BIN version. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" + exit 2 +fi + +if ! check_for_version $XB_VERSION $XB_REQUIRED_VERSION; then + wsrep_log_error "FATAL: The $INNOBACKUPEX_BIN version is $XB_VERSION. Needs xtrabackup-$XB_REQUIRED_VERSION or higher to perform SST" + exit 2 +fi + + rm -f "${MAGIC_FILE}" if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then @@ -670,13 +867,13 @@ if [[ $ssyslog -eq 1 ]];then } INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply " - INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move " + INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $impts --datadir=${DATA} --move-back --force-non-empty-directories \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move " INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" fi else INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" - INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" + INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $impts --datadir=${DATA} --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log" fi @@ -718,15 +915,6 @@ then fi get_keys - if [[ $encrypt -eq 1 ]];then - if [[ -n $ekey ]];then - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key=$ekey " - else - INNOEXTRA+=" --encrypt=$ealgo --encrypt-key-file=$ekeyfile " - fi - fi - - check_extra wsrep_log_info "Streaming GTID file before SST" @@ -739,17 +927,17 @@ then if [[ $encrypt -eq 1 ]];then if [[ -n $scomp ]];then - tcmd=" $ecmd | $scomp | $tcmd " + tcmd=" \$ecmd | $scomp | $tcmd " else - tcmd=" $ecmd | $tcmd " + tcmd=" \$ecmd | $tcmd " fi elif [[ -n $scomp ]];then tcmd=" $scomp | $tcmd " fi - send_donor $DATA "${stagemsg}-gtid" + # Restore the transport commmand to its original state tcmd="$ttcmd" if [[ -n $progress ]];then get_footprint @@ -764,10 +952,16 @@ then wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}" - if [[ -n $scomp ]];then + # Add compression to the head of the stream (if specified) + if [[ -n $scomp ]]; then tcmd="$scomp | $tcmd" fi + # Add encryption to the head of the stream (if specified) + if [[ $encrypt -eq 1 ]]; then + tcmd=" \$ecmd | $tcmd " + fi + set +e timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" set -e @@ -797,9 +991,9 @@ then get_keys if [[ $encrypt -eq 1 ]];then if [[ -n $scomp ]];then - tcmd=" $ecmd | $scomp | $tcmd " + tcmd=" \$ecmd | $scomp | $tcmd " else - tcmd=" $ecmd | $tcmd " + tcmd=" \$ecmd | $tcmd " fi elif [[ -n $scomp ]];then tcmd=" $scomp | $tcmd " @@ -824,7 +1018,6 @@ then stagemsg="Joiner-Recv" - sencrypted=1 nthreads=1 @@ -835,14 +1028,7 @@ then # May need xtrabackup_checkpoints later on rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile - ADDR=${WSREP_SST_OPT_ADDR} - if [ -z "${SST_PORT}" ] - then - SST_PORT=4444 - ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}" - fi - - wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & + wait_for_listen ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT:-4444} ${MODULE} & trap sig_joiner_cleanup HUP PIPE INT TERM trap cleanup_joiner EXIT @@ -855,9 +1041,9 @@ then get_keys if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then if [[ -n $sdecomp ]];then - strmcmd=" $sdecomp | $ecmd | $strmcmd" + strmcmd=" $sdecomp | \$ecmd | $strmcmd" else - strmcmd=" $ecmd | $strmcmd" + strmcmd=" \$ecmd | $strmcmd" fi elif [[ -n $sdecomp ]];then strmcmd=" $sdecomp | $strmcmd" |