Skip to content

Commit bcd6af9

Browse files
committed
MDEV-23580: WSREP_SST: [ERROR] rsync daemon port has been taken
This commit contains a large set of further bug fixes and improvements to SST scripts for Galera, continuing the work that was started in MDEV-24962 to make SST scripts work smoothly in different network configurations (especially using ipv6) and with different environment settings: 1) The ipv6 addresses were incorrectly handled in the SST script for rsync (incorrect address substitution for establishing a connection, incorrect address substitution for bind, and so on); 2) Checking the locality of the ip-address in SST scripts did not support ipv6 addresses (such as "[::1]"), which were falsely identified as non-local ip, which further did not allow running two SSTs on different local addresses on the same machine. On the other hand, this bug masked some other errors (related to handling ipv6 addresses); 3) The code for checking the locality of the ip address was different in the SST scripts for rsync and for mysqldump, with individual flaws. This code is now made common and moved to wsrep_sst_common; 4) Waiting for the start of the transport channel (socat, nc, rsync, stunnel) in the wait_for_listen() and check_pid_and_port() functions did not process ipv6 addresses correctly in all cases (not for all branches); 5) Waiting for the start of the transport channel (socat, nc, rsync, stunnel) in the wait_for_listen() and check_pid_and_port() functions for some code branches could give a false positive result due to the textual match of prefixes in the port number and/or PID of the process; 6) Waiting for the start of the transport channel (socat, nc, rsync, stunnel) was supported through different utilities in SST scripts for mariabackup and for rsync, and with various minor flaws in the code. Now the code is still different in these scripts, but it supports a common set of utilities (lsof, ss, sockstat) and is synchronized across patterns that used to check the output of these utilities; 7) In SST via mariabackup, the signal about readiness to receive data is sometimes sent too early - immediately after listen(), and not after accept() (which are called by socat or netcat utility). 8) Checking availability of the some options of some utilities was done using the grep pattern, which easily gives false positives; 9) Common name (CN) for local addresses, if not explicitly specified, is now always replaced to "localhost" to avoid the need to generate many separate certificates for local addresses of one machine and not to depend on which the local address is currently used in test (ipv4 or ipv6, etc.); 10) In tests galera_sst_mariabackup_encrypt_with_key_server and galera_sst_rsync_encrypt_with_key_server the correct certificate is selected to avoid commonname (CN) mismatch problems; 11) Further refactoring to protect against spaces in file names. 12) Further general refactoring to eliminate bash-specific constructs or to improve code readability; 13) The code for setting options for the nc (netcat) utility was different in different scripts for SST - now it is made identical. 14) Fixed long-time broken encryption via xbcrypt in combination with mariabackup and added support for key-based encryption via openssl utility, which is now enabled by default for encrypt=1 mode (this default mode can be changed using a new configuration file option "encypt-format=openssl|xbcrypt", which can be placed in the [mysqld], [sst] or in the [xtrabackup] section) - this change will allow us to use and to test the encypt=1 encryption without installing non-standard third-party utilities.
1 parent 86dc7b4 commit bcd6af9

10 files changed

+517
-353
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SELECT 1;
2+
1
3+
1
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
!include ../galera_2nodes.cnf
2+
3+
[mysqld]
4+
wsrep_sst_method=mariabackup
5+
wsrep_sst_auth="root:"
6+
wsrep_debug=ON
7+
8+
[sst]
9+
encrypt-format=openssl
10+
encrypt=1
11+
encrypt-algo=aes-256-ctr
12+
encrypt-key=4FA92C5873672E20FB163A0BCB2BB4A4
13+
transferfmt=@ENV.MTR_GALERA_TFMT
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#
2+
# This test checks that encryption with key using openssl with options
3+
# passed to mariabackup via the my.cnf file
4+
#
5+
--source include/galera_cluster.inc
6+
--source include/have_innodb.inc
7+
--source include/have_mariabackup.inc
8+
9+
SELECT 1;
10+
11+
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
12+
--source include/wait_condition.inc

mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key_server.cnf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ wsrep_sst_method=mariabackup
55
wsrep_sst_auth="root:"
66
wsrep_debug=1
77

8-
ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/client-cert.pem
9-
ssl-key=@ENV.MYSQL_TEST_DIR/std_data/client-key.pem
8+
ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem
9+
ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem
1010
ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem
1111

1212
[sst]

mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key_server.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ SELECT 1;
1818

1919
# Confirm that transfer was SSL-encrypted
2020
--let $assert_text = Using openssl based encryption with socat
21-
--let $assert_select = Using openssl based encryption with socat: with key and c
21+
--let $assert_select = Using openssl based encryption with socat: with key and crt
2222
--let $assert_count = 1
2323
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
2424
--let $assert_only_after = CURRENT_TEST

mysql-test/suite/galera/t/galera_sst_rsync_encrypt_with_server.cnf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
[mysqld]
44
wsrep_sst_method=rsync
5-
ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/client-cert.pem
6-
ssl-key=@ENV.MYSQL_TEST_DIR/std_data/client-key.pem
5+
ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem
6+
ssl-key=@ENV.MYSQL_TEST_DIR/std_data/server-key.pem
77
ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem
88

99
[sst]

scripts/wsrep_sst_common.sh

100644100755
Lines changed: 119 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ case "$1" in
5151
#
5252
# Break address string into host:port/path parts
5353
#
54-
case "${WSREP_SST_OPT_ADDR}" in
54+
case "$WSREP_SST_OPT_ADDR" in
5555
\[*)
5656
# IPv6
5757
# Remove the starting and ending square brackets, if present:
@@ -81,18 +81,18 @@ case "$1" in
8181
# up to "/" (if present):
8282
WSREP_SST_OPT_ADDR_PORT="${remain%%/*}"
8383
# If the "/" character is present, then the path is not empty:
84-
if [ "${remain#*/}" != "${remain}" ]; then
84+
if [ "${remain#*/}" != "$remain" ]; then
8585
# This operation removes everything up to the "/" character,
8686
# effectively removing the port number from the string:
8787
readonly WSREP_SST_OPT_PATH="${remain#*/}"
8888
else
8989
readonly WSREP_SST_OPT_PATH=""
9090
fi
9191
# The rest of the string is the same as the path (for now):
92-
remain="${WSREP_SST_OPT_PATH}"
92+
remain="$WSREP_SST_OPT_PATH"
9393
# If there is one more "/" in the string, then everything before
9494
# it will be the module name, otherwise the module name is empty:
95-
if [ "${remain%%/*}" != "${remain}" ]; then
95+
if [ "${remain%%/*}" != "$remain" ]; then
9696
# This operation removes the tail after the very first
9797
# occurrence of the "/" character (inclusively):
9898
readonly WSREP_SST_OPT_MODULE="${remain%%/*}"
@@ -103,7 +103,7 @@ case "$1" in
103103
remain="${WSREP_SST_OPT_PATH#*/}"
104104
# If the rest of the string does not match the original, then there
105105
# was something else besides the module name:
106-
if [ "$remain" != "${WSREP_SST_OPT_PATH}" ]; then
106+
if [ "$remain" != "$WSREP_SST_OPT_PATH" ]; then
107107
# Extract the part that matches the LSN by removing all
108108
# characters starting from the very first "/":
109109
readonly WSREP_SST_OPT_LSN="${remain%%/*}"
@@ -113,7 +113,7 @@ case "$1" in
113113
# If the remainder does not match the original string,
114114
# then there is something else (the version number in
115115
# our case):
116-
if [ "$remain" != "${WSREP_SST_OPT_LSN}" ]; then
116+
if [ "$remain" != "$WSREP_SST_OPT_LSN" ]; then
117117
# Let's extract the version number by removing the tail
118118
# after the very first occurence of the "/" character
119119
# (inclusively):
@@ -535,7 +535,8 @@ readonly WSREP_SST_OPT_ADDR_PORT
535535

536536
# try to use my_print_defaults, mysql and mysqldump that come with the sources
537537
# (for MTR suite)
538-
SCRIPTS_DIR="$(cd $(dirname "$0"); pwd -P)"
538+
script_binary=$(dirname "$0")
539+
SCRIPTS_DIR=$(cd "$script_binary"; pwd -P)
539540
EXTRA_DIR="$SCRIPTS_DIR/../extra"
540541
CLIENT_DIR="$SCRIPTS_DIR/../client"
541542

@@ -581,30 +582,45 @@ readonly MY_PRINT_DEFAULTS="$MY_PRINT_DEFAULTS $WSREP_SST_OPT_CONF"
581582
#
582583
parse_cnf()
583584
{
584-
local group="$1"
585+
local groups="$1"
585586
local var="$2"
586587
local reval=""
587588

588-
# normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin)
589-
# then search for needed variable
590-
# finally get the variable value (if variables has been specified multiple time use the last value only)
591-
592-
if [ "$group" = '--mysqld' -o \
593-
"$group" = 'mysqld' ]; then
594-
if [ -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
595-
reval=$($MY_PRINT_DEFAULTS "mysqld$WSREP_SST_OPT_SUFFIX_VALUE" | awk 'BEGIN {OFS=FS="="} {sub(/^--loose/,"-",$0); gsub(/_/,"-",$1); if ($1=="--'"$var"'") lastval=substr($0,length($1)+2)} END {print lastval}')
596-
fi
597-
fi
598-
599-
if [ -z "$reval" ]; then
600-
reval=$($MY_PRINT_DEFAULTS "$group" | awk 'BEGIN {OFS=FS="="} {sub(/^--loose/,"-",$0); gsub(/_/,"-",$1); if ($1=="--'"$var"'") lastval=substr($0,length($1)+2)} END {print lastval}')
601-
fi
589+
# normalize the variable names specified in the .cnf file
590+
# (user can use '_' or '-', for example, log-bin or log_bin),
591+
# then search for the last instance of the desired variable
592+
# and finally get the value of that variable (if the variable
593+
# was specified several times - we use only its last instance):
594+
595+
local pattern='BEGIN {OFS=FS="="} {sub(/^--loose/,"-",$0); gsub(/_/,"-",$1); if ($1=="--'"$var"'") lastval=substr($0,length($1)+2)} END {print lastval}'
596+
597+
while [ -n "$groups" ]; do
598+
# Remove the largest suffix starting with the '|' character:
599+
local group="${groups%%\|*}"
600+
# Remove the remainder (the group name) from the rest
601+
# of the groups list (as if it were a prefix):
602+
groups="${groups#$group}"
603+
groups="${groups#\|}"
604+
# if the group name is the same as the "[--]mysqld", then
605+
# try to use it together with the group suffix:
606+
if [ "${group#--}" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
607+
reval=$($MY_PRINT_DEFAULTS "mysqld$WSREP_SST_OPT_SUFFIX_VALUE" | awk "$pattern")
608+
if [ -n "$reval" ]; then
609+
break
610+
fi
611+
fi
612+
# Let's try to use the group name as it is:
613+
reval=$($MY_PRINT_DEFAULTS "$group" | awk "$pattern")
614+
if [ -n "$reval" ]; then
615+
break
616+
fi
617+
done
602618

603-
# use default if we haven't found a value
619+
# use default if we haven't found a value:
604620
if [ -z "$reval" ]; then
605621
[ -n "${3:-}" ] && reval="$3"
606622
fi
607-
echo $reval
623+
echo "$reval"
608624
}
609625

610626
#
@@ -615,18 +631,37 @@ parse_cnf()
615631
#
616632
in_config()
617633
{
618-
local group="$1"
634+
local groups="$1"
619635
local var="$2"
620636
local found=0
621-
if [ "$group" = '--mysqld' -o \
622-
"$group" = 'mysqld' ]; then
623-
if [ -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
624-
found=$($MY_PRINT_DEFAULTS "mysqld$WSREP_SST_OPT_SUFFIX_VALUE" | awk 'BEGIN {OFS=FS="="; found=0} {sub(/^--loose/,"-",$0); gsub(/_/,"-",$1); if ($1=="--'"$var"'") found=1} END {print found}')
625-
fi
626-
fi
627-
if [ $found -eq 0 ]; then
628-
found=$($MY_PRINT_DEFAULTS "$group" | awk 'BEGIN {OFS=FS="="; found=0} {sub(/^--loose/,"-",$0); gsub(/_/,"-",$1); if ($1=="--'"$var"'") found=1} END {print found}')
629-
fi
637+
638+
# normalize the variable names specified in the .cnf file
639+
# (user can use '_' or '-', for example, log-bin or log_bin),
640+
# then search for the last instance(s) of the desired variable:
641+
642+
local pattern='BEGIN {OFS=FS="="; found=0} {sub(/^--loose/,"-",$0); gsub(/_/,"-",$1); if ($1=="--'"$var"'") found=1} END {print found}'
643+
644+
while [ -n "$groups" ]; do
645+
# Remove the largest suffix starting with the '|' character:
646+
local group="${groups%%\|*}"
647+
# Remove the remainder (the group name) from the rest
648+
# of the groups list (as if it were a prefix):
649+
groups="${groups#$group}"
650+
groups="${groups#\|}"
651+
# if the group name is the same as the "[--]mysqld", then
652+
# try to use it together with the group suffix:
653+
if [ "${group#--}" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
654+
found=$($MY_PRINT_DEFAULTS "mysqld$WSREP_SST_OPT_SUFFIX_VALUE" | awk "$pattern")
655+
if [ $found -ne 0 ]; then
656+
break
657+
fi
658+
fi
659+
# Let's try to use the group name as it is:
660+
found=$($MY_PRINT_DEFAULTS "$group" | awk "$pattern")
661+
if [ $found -ne 0 ]; then
662+
break
663+
fi
664+
done
630665
echo $found
631666
}
632667

@@ -747,7 +782,7 @@ wsrep_check_programs()
747782

748783
while [ $# -gt 0 ]
749784
do
750-
wsrep_check_program $1 || ret=$?
785+
wsrep_check_program "$1" || ret=$?
751786
shift
752787
done
753788

@@ -793,3 +828,52 @@ wsrep_gen_secret()
793828
$RANDOM $RANDOM $RANDOM $RANDOM
794829
fi
795830
}
831+
832+
is_local_ip()
833+
{
834+
[ "$1" = '127.0.0.1' ] && return 0
835+
[ "$1" = '127.0.0.2' ] && return 0
836+
[ "$1" = 'localhost' ] && return 0
837+
[ "$1" = '[::1]' ] && return 0
838+
[ "$1" = "$(hostname -s)" ] && return 0
839+
[ "$1" = "$(hostname -f)" ] && return 0
840+
[ "$1" = "$(hostname -d)" ] && return 0
841+
842+
local ip_util="$(command -v ip)"
843+
if [ -x "$ip_util" ]; then
844+
# ip address show ouput format is " inet[6] <address>/<mask>":
845+
"$ip_util" address show \
846+
| grep -E "^[[:space:]]*inet.? [^[:space:]]+/" -o \
847+
| grep -F " $1/" >/dev/null && return 0
848+
else
849+
local ifconfig_util="$(command -v ifconfig)"
850+
if [ -x "$ifconfig_util" ]; then
851+
# ifconfig output format is " inet[6] <address> ...":
852+
"$ifconfig_util" \
853+
| grep -E "^[[:space:]]*inet.? [^[:space:]]+ " -o \
854+
| grep -F " $1 " >/dev/null && return 0
855+
fi
856+
fi
857+
858+
return 1
859+
}
860+
861+
check_sockets_utils()
862+
{
863+
lsof_available=0
864+
sockstat_available=0
865+
ss_available=0
866+
867+
[ -x "$(command -v lsof)" ] && lsof_available=1
868+
[ -x "$(command -v sockstat)" ] && sockstat_available=1
869+
[ -x "$(command -v ss)" ] && ss_available=1
870+
871+
if [ $lsof_available -eq 0 -a \
872+
$sockstat_available -eq 0 -a \
873+
$ss_available -eq 0 ]
874+
then
875+
wsrep_log_error "Neither lsof tool, nor ss or sockstat was found in " \
876+
"the PATH! Make sure you have it installed."
877+
exit 2 # ENOENT
878+
fi
879+
}

0 commit comments

Comments
 (0)