Commit 83664e21 authored by Alexey Yurchenko's avatar Alexey Yurchenko Committed by Jan Lindström

MW-366 Improved support for IPv6 networks - made mysqld and SST scripts to...

MW-366 Improved support for IPv6 networks - made mysqld and SST scripts to recognize []-escaped IPv6 addresses - pulled in latest Percona and MariaDB updates to SST scripts - instruct netcat and socat in wsrep_sst_xtrabackup-v2 to listen on IPv6 socket via sockopt parameter in the [sst] section of my.cnf

In summary, wsrep_node_address and wsrep_sst_receive_address can now
be set to IPv6 addresses escaped by []. Rsync SST works out ouf the
box thanks to rsync daemon listening on both IPv4 and IPv6 sockets by
default. For xtrabackup SST onver IPv6 one needs to set sockopt in
the [sst] section of joiner's configuration file to ",pf=ip6" if
using socat as a streamer or to "-6" if using netcat.
parent 5108dede
...@@ -30,6 +30,22 @@ while [ $# -gt 0 ]; do ...@@ -30,6 +30,22 @@ while [ $# -gt 0 ]; do
case "$1" in case "$1" in
'--address') '--address')
readonly WSREP_SST_OPT_ADDR="$2" 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 shift
;; ;;
'--bypass') '--bypass')
...@@ -169,6 +185,11 @@ wsrep_log_error() ...@@ -169,6 +185,11 @@ wsrep_log_error()
wsrep_log "[ERROR] $*" wsrep_log "[ERROR] $*"
} }
wsrep_log_warning()
{
wsrep_log "[WARNING] $*"
}
wsrep_log_info() wsrep_log_info()
{ {
wsrep_log "[INFO] $*" wsrep_log "[INFO] $*"
...@@ -202,3 +223,39 @@ wsrep_check_programs() ...@@ -202,3 +223,39 @@ wsrep_check_programs()
return $ret 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
}
...@@ -30,6 +30,7 @@ local_ip() ...@@ -30,6 +30,7 @@ local_ip()
{ {
[ "$1" = "127.0.0.1" ] && return 0 [ "$1" = "127.0.0.1" ] && return 0
[ "$1" = "localhost" ] && return 0 [ "$1" = "localhost" ] && return 0
[ "$1" = "[::1]" ] && return 0
[ "$1" = "$(hostname -s)" ] && return 0 [ "$1" = "$(hostname -s)" ] && return 0
[ "$1" = "$(hostname -f)" ] && return 0 [ "$1" = "$(hostname -f)" ] && return 0
[ "$1" = "$(hostname -d)" ] && return 0 [ "$1" = "$(hostname -d)" ] && return 0
...@@ -105,8 +106,9 @@ GTID_BINLOG_STATE=$(echo "SHOW GLOBAL VARIABLES LIKE 'gtid_binlog_state'" |\ ...@@ -105,8 +106,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 |\ $MYSQL_CLIENT $AUTH -S$WSREP_SST_OPT_SOCKET --disable-reconnect --connect_timeout=10 |\
tail -1 | awk -F ' ' '{ print $2 }') tail -1 | awk -F ' ' '{ print $2 }')
MYSQL="$MYSQL_CLIENT $AUTH -h$WSREP_SST_OPT_HOST -P$WSREP_SST_OPT_PORT "\ MYSQL="$MYSQL_CLIENT --defaults-extra-file=$WSREP_SST_OPT_CONF "\
"--disable-reconnect --connect_timeout=10" "$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. # Check if binary logging is enabled on the joiner node.
# Note: SELECT cannot be used at this point. # Note: SELECT cannot be used at this point.
......
...@@ -67,6 +67,11 @@ check_pid_and_port() ...@@ -67,6 +67,11 @@ check_pid_and_port()
exit 2 # ENOENT exit 2 # ENOENT
fi 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 | \ local port_info=$(lsof -i :$rsync_port -Pn 2>/dev/null | \
grep "(LISTEN)") grep "(LISTEN)")
local is_rsync=$(echo $port_info | \ local is_rsync=$(echo $port_info | \
...@@ -97,10 +102,19 @@ fi ...@@ -97,10 +102,19 @@ fi
WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} WSREP_LOG_DIR=${WSREP_LOG_DIR:-""}
# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf
if [ -z "$WSREP_LOG_DIR" ]; then if [ -z "$WSREP_LOG_DIR" ]; then
WSREP_LOG_DIR=$($MY_PRINT_DEFAULTS --defaults-file \ WSREP_LOG_DIR=$(parse_cnf mariadb-10.0 innodb_log_group_home_dir "")
"$WSREP_SST_OPT_CONF" mysqld server mysqld-10.0 mariadb mariadb-10.0 \ fi
| grep -- '--innodb[-_]log[-_]group[-_]home[-_]dir=' \ if [ -z "$WSREP_LOG_DIR" ]; then
| cut -b 29- ) 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 fi
if [ -n "$WSREP_LOG_DIR" ]; then if [ -n "$WSREP_LOG_DIR" ]; then
...@@ -208,8 +222,8 @@ then ...@@ -208,8 +222,8 @@ then
[ "$OS" == "Linux" ] && count=$(grep -c processor /proc/cpuinfo) [ "$OS" == "Linux" ] && count=$(grep -c processor /proc/cpuinfo)
[ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ] && count=$(sysctl -n hw.ncpu) [ "$OS" == "Darwin" -o "$OS" == "FreeBSD" ] && count=$(sysctl -n hw.ncpu)
find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" -print0 | \ find . -maxdepth 1 -mindepth 1 -type d -not -name "lost+found" \
xargs -I{} -0 -P $count \ -print0 | xargs -I{} -0 -P $count \
rsync --owner --group --perms --links --specials \ rsync --owner --group --perms --links --specials \
--ignore-times --inplace --recursive --delete --quiet \ --ignore-times --inplace --recursive --delete --quiet \
$WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \ $WHOLE_FILE_OPT --exclude '*/ib_logfile*' "$WSREP_SST_OPT_DATA"/{}/ \
...@@ -252,25 +266,24 @@ then ...@@ -252,25 +266,24 @@ then
fi fi
rm -rf "$RSYNC_PID" rm -rf "$RSYNC_PID"
ADDR=$WSREP_SST_OPT_ADDR
RSYNC_PORT=$(echo $ADDR | awk -F ':' '{ print $2 }')
if [ -z "$RSYNC_PORT" ]
then
RSYNC_PORT=4444
ADDR="$(echo $ADDR | awk -F ':' '{ print $1 }'):$RSYNC_PORT"
fi
trap "exit 32" HUP PIPE trap "exit 32" HUP PIPE
trap "exit 3" INT TERM ABRT trap "exit 3" INT TERM ABRT
trap cleanup_joiner EXIT trap cleanup_joiner EXIT
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
if [ -n "${MYSQL_TMP_DIR:-}" ] ; then
SILENT="log file = $MYSQL_TMP_DIR/rsyncd.log"
else
SILENT=""
fi
cat << EOF > "$RSYNC_CONF" cat << EOF > "$RSYNC_CONF"
pid file = $RSYNC_PID pid file = $RSYNC_PID
use chroot = no use chroot = no
read only = no read only = no
timeout = 300 timeout = 300
$SILENT
[$MODULE] [$MODULE]
path = $WSREP_SST_OPT_DATA path = $WSREP_SST_OPT_DATA
[$MODULE-log_dir] [$MODULE-log_dir]
...@@ -280,6 +293,7 @@ EOF ...@@ -280,6 +293,7 @@ EOF
# rm -rf "$DATA"/ib_logfile* # we don't want old logs around # rm -rf "$DATA"/ib_logfile* # we don't want old logs around
# listen at all interfaces (for firewalled setups) # 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 --daemon --no-detach --port $RSYNC_PORT --config "$RSYNC_CONF" &
RSYNC_REAL_PID=$! RSYNC_REAL_PID=$!
...@@ -288,7 +302,7 @@ EOF ...@@ -288,7 +302,7 @@ EOF
sleep 0.2 sleep 0.2
done done
echo "ready $ADDR/$MODULE" echo "ready $WSREP_SST_OPT_HOST:$RSYNC_PORT/$MODULE"
# wait for SST to complete by monitoring magic file # wait for SST to complete by monitoring magic file
while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \ while [ ! -r "$MAGIC_FILE" ] && check_pid "$RSYNC_PID" && \
......
...@@ -34,8 +34,8 @@ ssystag="" ...@@ -34,8 +34,8 @@ ssystag=""
XTRABACKUP_PID="" XTRABACKUP_PID=""
SST_PORT="" SST_PORT=""
REMOTEIP="" REMOTEIP=""
tca=""
tcert="" tcert=""
tpem=""
tkey="" tkey=""
sockopt="" sockopt=""
progress="" progress=""
...@@ -47,7 +47,6 @@ rlimit="" ...@@ -47,7 +47,6 @@ rlimit=""
# Initially # Initially
stagemsg="${WSREP_SST_OPT_ROLE}" stagemsg="${WSREP_SST_OPT_ROLE}"
cpat="" cpat=""
speciald=1
ib_home_dir="" ib_home_dir=""
ib_log_dir="" ib_log_dir=""
ib_undo_dir="" ib_undo_dir=""
...@@ -71,6 +70,11 @@ xtmpdir="" ...@@ -71,6 +70,11 @@ xtmpdir=""
scomp="" scomp=""
sdecomp="" sdecomp=""
ssl_dhparams=""
ssl_cert=""
ssl_ca=""
ssl_key=""
# Required for backup locks # Required for backup locks
# For backup locks it is 1 sent by joiner # For backup locks it is 1 sent by joiner
...@@ -150,6 +154,10 @@ get_keys() ...@@ -150,6 +154,10 @@ get_keys()
if [[ -z $ekey ]];then if [[ -z $ekey ]];then
ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile" ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key-file=$ekeyfile"
else 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" ecmd="xbcrypt --encrypt-algo=$ealgo --encrypt-key=$ekey"
fi fi
...@@ -160,6 +168,86 @@ get_keys() ...@@ -160,6 +168,86 @@ get_keys()
stagemsg+="-XB-Encrypted" 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() get_transfer()
{ {
if [[ -z $SST_PORT ]];then if [[ -z $SST_PORT ]];then
...@@ -173,15 +261,25 @@ get_transfer() ...@@ -173,15 +261,25 @@ get_transfer()
wsrep_log_error "nc(netcat) not found in path: $PATH" wsrep_log_error "nc(netcat) not found in path: $PATH"
exit 2 exit 2
fi 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" wsrep_log_info "Using netcat as streamer"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
if nc -h 2>&1 | grep -q ncat;then if nc -h 2>&1 | grep -q ncat; then
tcmd="nc -l ${TSST_PORT}" tcmd="nc $sockopt -l ${TSST_PORT}"
else else
tcmd="nc -dl ${TSST_PORT}" tcmd="nc $sockopt -dl ${TSST_PORT}"
fi fi
else else
tcmd="nc ${REMOTEIP} ${TSST_PORT}" # netcat doesn't understand [] around IPv6 address
tcmd="nc ${REMOTEIP//[\[\]]/} ${TSST_PORT}"
fi fi
else else
tfmt='socat' tfmt='socat'
...@@ -191,64 +289,111 @@ get_transfer() ...@@ -191,64 +289,111 @@ get_transfer()
exit 2 exit 2
fi fi
if [[ $encrypt -eq 2 || $encrypt -eq 3 ]] && ! socat -V | grep -q WITH_OPENSSL;then donor_extra=""
wsrep_log_info "NOTE: socat is not openssl enabled, falling back to plain transfer" joiner_extra=""
encrypt=-1 if [[ $encrypt -eq 2 || $encrypt -eq 3 || $encrypt -eq 4 ]]; then
fi 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 # Determine the socat version
wsrep_log_info "Using openssl based encryption with socat: with crt and pem" SOCAT_VERSION=`socat -V 2>&1 | grep -oe '[0-9]\.[0-9][\.0-9]*' | head -n1`
if [[ -z $tpem || -z $tcert ]];then if [[ -z "$SOCAT_VERSION" ]]; then
wsrep_log_error "Both PEM and CRT files required" wsrep_log_error "******** FATAL ERROR **************** "
exit 22 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 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" stagemsg+="-OpenSSL-Encrypted-2"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with PEM $tpem, CA: $tcert" wsrep_log_info "Decrypting with CERT: $tcert, CA: $tca"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},cafile=${tca}${joiner_extra}${sockopt} stdio"
else else
wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" wsrep_log_info "Encrypting with CERT: $tcert, CA: $tca"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tcert},cafile=${tca}${donor_extra}${sockopt}"
fi fi
elif [[ $encrypt -eq 3 ]];then 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" 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" verify_file_exists "$tcert" "Both certificate and key files are required." \
exit 22 "Please check the 'tcert' option. "
fi verify_file_exists "$tkey" "Both certificate and key files are required." \
"Please check the 'tkey' option. "
stagemsg+="-OpenSSL-Encrypted-3" stagemsg+="-OpenSSL-Encrypted-3"
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then
wsrep_log_info "Decrypting with certificate $tpem, key $tkey" wsrep_log_info "Decrypting with CERT: $tcert, KEY: $tkey"
tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,key=${tkey},verify=0${sockopt} stdio" tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},key=${tkey},verify=0${joiner_extra}${sockopt} stdio"
else
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 else
wsrep_log_info "Encrypting with certificate $tpem, key $tkey" wsrep_log_info "Encrypting with CERT: $ssl_cert, KEY: $ssl_key, CA: $ssl_ca"
tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,key=${tkey},verify=0${sockopt}" tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${donor_extra}${sockopt}"
fi fi
else else
if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then 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" tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio"
else else
tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}"
fi fi
fi 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 -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)
if [[ -z $reval ]];then
[[ -n $3 ]] && reval=$3
fi
echo $reval
} }
get_footprint() get_footprint()
...@@ -298,15 +443,15 @@ read_cnf() ...@@ -298,15 +443,15 @@ read_cnf()
{ {
sfmt=$(parse_cnf sst streamfmt "xbstream") sfmt=$(parse_cnf sst streamfmt "xbstream")
tfmt=$(parse_cnf sst transferfmt "socat") tfmt=$(parse_cnf sst transferfmt "socat")
tcert=$(parse_cnf sst tca "") tca=$(parse_cnf sst tca "")
tpem=$(parse_cnf sst tcert "") tcert=$(parse_cnf sst tcert "")
tkey=$(parse_cnf sst tkey "") tkey=$(parse_cnf sst tkey "")
encrypt=$(parse_cnf sst encrypt 0) encrypt=$(parse_cnf sst encrypt 0)
sockopt=$(parse_cnf sst sockopt "") sockopt=$(parse_cnf sst sockopt "")
progress=$(parse_cnf sst progress "") progress=$(parse_cnf sst progress "")
rebuild=$(parse_cnf sst rebuild 0) rebuild=$(parse_cnf sst rebuild 0)
ttime=$(parse_cnf sst time 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 "") ealgo=$(parse_cnf xtrabackup encrypt "")
ekey=$(parse_cnf xtrabackup encrypt-key "") ekey=$(parse_cnf xtrabackup encrypt-key "")
ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "")
...@@ -320,9 +465,23 @@ read_cnf() ...@@ -320,9 +465,23 @@ read_cnf()
ekey=$(parse_cnf sst encrypt-key "") ekey=$(parse_cnf sst encrypt-key "")
ekeyfile=$(parse_cnf sst encrypt-key-file "") ekeyfile=$(parse_cnf sst encrypt-key-file "")
fi 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 "") rlimit=$(parse_cnf sst rlimit "")
uextra=$(parse_cnf sst use-extra 0) uextra=$(parse_cnf sst use-extra 0)
speciald=$(parse_cnf sst sst-special-dirs 1)
iopts=$(parse_cnf sst inno-backup-opts "") iopts=$(parse_cnf sst inno-backup-opts "")
iapts=$(parse_cnf sst inno-apply-opts "") iapts=$(parse_cnf sst inno-apply-opts "")
impts=$(parse_cnf sst inno-move-opts "") impts=$(parse_cnf sst inno-move-opts "")
...@@ -331,13 +490,8 @@ read_cnf() ...@@ -331,13 +490,8 @@ read_cnf()
ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}") ssystag=$(parse_cnf mysqld_safe syslog-tag "${SST_SYSLOG_TAG:-}")
ssystag+="-" 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 [[ $ssyslog -ne -1 ]];then
if my_print_defaults -c $WSREP_SST_OPT_CONF 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 ssyslog=1
fi fi
fi fi
...@@ -483,28 +637,30 @@ kill_xtrabackup() ...@@ -483,28 +637,30 @@ kill_xtrabackup()
setup_ports() setup_ports()
{ {
if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then
SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') SST_PORT=$WSREP_SST_OPT_PORT
REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') REMOTEIP=$WSREP_SST_OPT_HOST
lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') lsn=$(echo $WSREP_SST_OPT_PATH | awk -F '[/]' '{ print $2 }')
sst_ver=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $5 }') sst_ver=$(echo $WSREP_SST_OPT_PATH | awk -F '[/]' '{ print $3 }')
else else
SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') SST_PORT=$WSREP_SST_OPT_PORT
fi 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) # (regardless of timeout)
wait_for_listen() wait_for_listen()
{ {
local PORT=$1 local HOST=$1
local ADDR=$2 local PORT=$2
local MODULE=$3 local MODULE=$3
for i in {1..50}
for i in {1..300}
do do
ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break
sleep 0.2 sleep 0.2
done done
echo "ready ${ADDR}/${MODULE}//$sst_ver"
echo "ready ${HOST}:${PORT}/${MODULE}//$sst_ver"
} }
check_extra() check_extra()
...@@ -512,7 +668,7 @@ check_extra() ...@@ -512,7 +668,7 @@ check_extra()
local use_socket=1 local use_socket=1
if [[ $uextra -eq 1 ]];then if [[ $uextra -eq 1 ]];then
if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then if $MY_PRINT_DEFAULTS -c $WSREP_SST_OPT_CONF mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then
local eport=$(my_print_defaults -c $WSREP_SST_OPT_CONF 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 if [[ -n $eport ]];then
# Xtrabackup works only locally. # Xtrabackup works only locally.
# Hence, setting host to 127.0.0.1 unconditionally. # Hence, setting host to 127.0.0.1 unconditionally.
...@@ -607,11 +763,64 @@ send_donor() ...@@ -607,11 +763,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 if [[ ! -x `which $INNOBACKUPEX_BIN` ]];then
wsrep_log_error "innobackupex not in path: $PATH" wsrep_log_error "innobackupex not in path: $PATH"
exit 2 exit 2
fi 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}" rm -f "${MAGIC_FILE}"
if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' ]];then
...@@ -655,13 +864,13 @@ if [[ $ssyslog -eq 1 ]];then ...@@ -655,13 +864,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 " INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply "
INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${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} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)"
fi fi
else else
INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log"
INNOMOVE="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $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} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log" INNOBACKUP="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log"
fi fi
...@@ -703,15 +912,6 @@ then ...@@ -703,15 +912,6 @@ then
fi fi
get_keys 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 check_extra
wsrep_log_info "Streaming GTID file before SST" wsrep_log_info "Streaming GTID file before SST"
...@@ -722,17 +922,17 @@ then ...@@ -722,17 +922,17 @@ then
if [[ $encrypt -eq 1 ]];then if [[ $encrypt -eq 1 ]];then
if [[ -n $scomp ]];then if [[ -n $scomp ]];then
tcmd=" $ecmd | $scomp | $tcmd " tcmd=" \$ecmd | $scomp | $tcmd "
else else
tcmd=" $ecmd | $tcmd " tcmd=" \$ecmd | $tcmd "
fi fi
elif [[ -n $scomp ]];then elif [[ -n $scomp ]];then
tcmd=" $scomp | $tcmd " tcmd=" $scomp | $tcmd "
fi fi
send_donor $DATA "${stagemsg}-gtid" send_donor $DATA "${stagemsg}-gtid"
# Restore the transport commmand to its original state
tcmd="$ttcmd" tcmd="$ttcmd"
if [[ -n $progress ]];then if [[ -n $progress ]];then
get_footprint get_footprint
...@@ -747,10 +947,16 @@ then ...@@ -747,10 +947,16 @@ then
wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}" 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" tcmd="$scomp | $tcmd"
fi fi
# Add encryption to the head of the stream (if specified)
if [[ $encrypt -eq 1 ]]; then
tcmd=" \$ecmd | $tcmd "
fi
set +e set +e
timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )" timeit "${stagemsg}-SST" "$INNOBACKUP | $tcmd; RC=( "\${PIPESTATUS[@]}" )"
set -e set -e
...@@ -777,9 +983,9 @@ then ...@@ -777,9 +983,9 @@ then
get_keys get_keys
if [[ $encrypt -eq 1 ]];then if [[ $encrypt -eq 1 ]];then
if [[ -n $scomp ]];then if [[ -n $scomp ]];then
tcmd=" $ecmd | $scomp | $tcmd " tcmd=" \$ecmd | $scomp | $tcmd "
else else
tcmd=" $ecmd | $tcmd " tcmd=" \$ecmd | $tcmd "
fi fi
elif [[ -n $scomp ]];then elif [[ -n $scomp ]];then
tcmd=" $scomp | $tcmd " tcmd=" $scomp | $tcmd "
...@@ -804,7 +1010,6 @@ then ...@@ -804,7 +1010,6 @@ then
stagemsg="Joiner-Recv" stagemsg="Joiner-Recv"
sencrypted=1 sencrypted=1
nthreads=1 nthreads=1
...@@ -815,14 +1020,7 @@ then ...@@ -815,14 +1020,7 @@ then
# May need xtrabackup_checkpoints later on # May need xtrabackup_checkpoints later on
rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile
ADDR=${WSREP_SST_OPT_ADDR} wait_for_listen ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT:-4444} ${MODULE} &
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} &
trap sig_joiner_cleanup HUP PIPE INT TERM trap sig_joiner_cleanup HUP PIPE INT TERM
trap cleanup_joiner EXIT trap cleanup_joiner EXIT
...@@ -835,9 +1033,9 @@ then ...@@ -835,9 +1033,9 @@ then
get_keys get_keys
if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then if [[ $encrypt -eq 1 && $sencrypted -eq 1 ]];then
if [[ -n $sdecomp ]];then if [[ -n $sdecomp ]];then
strmcmd=" $sdecomp | $ecmd | $strmcmd" strmcmd=" $sdecomp | \$ecmd | $strmcmd"
else else
strmcmd=" $ecmd | $strmcmd" strmcmd=" \$ecmd | $strmcmd"
fi fi
elif [[ -n $sdecomp ]];then elif [[ -n $sdecomp ]];then
strmcmd=" $sdecomp | $strmcmd" strmcmd=" $sdecomp | $strmcmd"
......
...@@ -571,27 +571,17 @@ int wsrep_init() ...@@ -571,27 +571,17 @@ int wsrep_init()
size_t const node_addr_len= strlen(node_addr); size_t const node_addr_len= strlen(node_addr);
if (node_addr_len > 0) if (node_addr_len > 0)
{ {
const char* const colon= strrchr(node_addr, ':'); size_t const ip_len= wsrep_host_len(node_addr, node_addr_len);
if (strchr(node_addr, ':') == colon) // 1 or 0 ':' if (ip_len + 7 /* :55555\0 */ < inc_addr_max)
{ {
size_t const ip_len= colon ? colon - node_addr : node_addr_len; memcpy (inc_addr, node_addr, ip_len);
if (ip_len + 7 /* :55555\0 */ < inc_addr_max) snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",
{ (int)mysqld_port);
memcpy (inc_addr, node_addr, ip_len);
snprintf(inc_addr + ip_len, inc_addr_max - ip_len, ":%u",
(int)mysqld_port);
}
else
{
WSREP_WARN("Guessing address for incoming client connections: "
"address too long.");
inc_addr[0]= '\0';
}
} }
else else
{ {
WSREP_WARN("Guessing address for incoming client connections: " WSREP_WARN("Guessing address for incoming client connections: "
"too many colons :) ."); "address too long.");
inc_addr[0]= '\0'; inc_addr[0]= '\0';
} }
} }
......
...@@ -634,18 +634,19 @@ ssize_t wsrep_sst_prepare (void** msg) ...@@ -634,18 +634,19 @@ ssize_t wsrep_sst_prepare (void** msg)
// Figure out SST address. Common for all SST methods // Figure out SST address. Common for all SST methods
if (wsrep_sst_receive_address && if (wsrep_sst_receive_address &&
strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO)) strcmp (wsrep_sst_receive_address, WSREP_SST_ADDRESS_AUTO))
{ {
addr_in= wsrep_sst_receive_address; addr_in= wsrep_sst_receive_address;
} }
else if (wsrep_node_address && strlen(wsrep_node_address)) else if (wsrep_node_address && strlen(wsrep_node_address))
{ {
const char* const colon= strchr (wsrep_node_address, ':'); size_t const addr_len= strlen(wsrep_node_address);
if (colon) size_t const host_len= wsrep_host_len(wsrep_node_address, addr_len);
if (host_len < addr_len)
{ {
ptrdiff_t const len= colon - wsrep_node_address; strncpy (ip_buf, wsrep_node_address, host_len);
strncpy (ip_buf, wsrep_node_address, len); ip_buf[host_len]= '\0';
ip_buf[len]= '\0';
addr_in= ip_buf; addr_in= ip_buf;
} }
else else
...@@ -772,25 +773,6 @@ static int sst_donate_mysqldump (const char* addr, ...@@ -772,25 +773,6 @@ static int sst_donate_mysqldump (const char* addr,
bool bypass, bool bypass,
char** env) // carries auth info char** env) // carries auth info
{ {
size_t host_len;
const char* port = strchr (addr, ':');
if (port)
{
port += 1;
host_len = port - addr;
}
else
{
port = "";
host_len = strlen (addr) + 1;
}
char *host= (char *) alloca(host_len);
strncpy (host, addr, host_len - 1);
host[host_len - 1] = '\0';
int const cmd_len= 4096; int const cmd_len= 4096;
wsp::string cmd_str(cmd_len); wsp::string cmd_str(cmd_len);
...@@ -805,14 +787,13 @@ static int sst_donate_mysqldump (const char* addr, ...@@ -805,14 +787,13 @@ static int sst_donate_mysqldump (const char* addr,
int ret= snprintf (cmd_str(), cmd_len, int ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_mysqldump " "wsrep_sst_mysqldump "
WSREP_SST_OPT_HOST" '%s' " WSREP_SST_OPT_ADDR" '%s' "
WSREP_SST_OPT_PORT" '%s' "
WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_LPORT" '%u' "
WSREP_SST_OPT_SOCKET" '%s' " WSREP_SST_OPT_SOCKET" '%s' "
WSREP_SST_OPT_CONF" '%s' " WSREP_SST_OPT_CONF" '%s' "
WSREP_SST_OPT_GTID" '%s:%lld'" WSREP_SST_OPT_GTID" '%s:%lld'"
"%s", "%s",
host, port, mysqld_port, mysqld_unix_port, addr, mysqld_port, mysqld_unix_port,
wsrep_defaults_file, uuid_str, wsrep_defaults_file, uuid_str,
(long long)seqno, bypass ? " " WSREP_SST_OPT_BYPASS : ""); (long long)seqno, bypass ? " " WSREP_SST_OPT_BYPASS : "");
......
...@@ -554,3 +554,18 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len) ...@@ -554,3 +554,18 @@ size_t wsrep_guess_ip (char* buf, size_t buf_len)
return 0; return 0;
} }
/* returns the length of the host part of the address string */
size_t wsrep_host_len(const char* const addr, size_t const addr_len)
{
// check for IPv6 notation first
const char* const bracket= ('[' == addr[0] ? strchr(addr, ']') : NULL);
if (bracket) { // IPv6
return (bracket - addr + 1);
}
else { // host part ends at ':' or end of string
const char* const colon= strchr(addr, ':');
return (colon ? colon - addr : addr_len);
}
}
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
unsigned int wsrep_check_ip (const char* addr); unsigned int wsrep_check_ip (const char* addr);
size_t wsrep_guess_ip (char* buf, size_t buf_len); size_t wsrep_guess_ip (char* buf, size_t buf_len);
/* returns the length of the host part of the address string */
size_t wsrep_host_len(const char* addr, size_t addr_len);
namespace wsp { namespace wsp {
class node_status class node_status
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment