1#!/usr/local/bin/bash 2 3set -ue 4 5# Copyright (C) 2017-2021 MariaDB 6# Copyright (C) 2010-2014 Codership Oy 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; version 2 of the License. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; see the file COPYING. If not, write to the 19# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston 20# MA 02110-1335 USA. 21 22# This is a reference script for rsync-based state snapshot transfer 23 24RSYNC_REAL_PID=0 # rsync process id 25STUNNEL_REAL_PID=0 # stunnel process id 26 27OS="$(uname)" 28[ "$OS" = 'Darwin' ] && export -n LD_LIBRARY_PATH 29 30. $(dirname "$0")/wsrep_sst_common 31wsrep_check_datadir 32 33wsrep_check_programs rsync 34 35cleanup_joiner() 36{ 37 local failure=0 38 39 wsrep_log_info "Joiner cleanup: rsync PID=$RSYNC_REAL_PID," \ 40 "stunnel PID=$STUNNEL_REAL_PID" 41 42 if [ -n "$STUNNEL" ]; then 43 if cleanup_pid $STUNNEL_REAL_PID "$STUNNEL_PID" "$STUNNEL_CONF"; then 44 if [ $RSYNC_REAL_PID -eq 0 ]; then 45 if [ -r "$RSYNC_PID" ]; then 46 RSYNC_REAL_PID=$(cat "$RSYNC_PID" 2>/dev/null || :) 47 if [ -z "$RSYNC_REAL_PID" ]; then 48 RSYNC_REAL_PID=0 49 fi 50 fi 51 fi 52 else 53 wsrep_log_warning "stunnel cleanup failed." 54 failure=1 55 fi 56 fi 57 58 if [ $failure -eq 0 ]; then 59 if cleanup_pid $RSYNC_REAL_PID "$RSYNC_PID" "$RSYNC_CONF"; then 60 [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" 61 else 62 wsrep_log_warning "rsync cleanup failed." 63 fi 64 fi 65 66 wsrep_log_info "Joiner cleanup done." 67 68 if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then 69 wsrep_cleanup_progress_file 70 fi 71 72 [ -f "$SST_PID" ] && rm -f "$SST_PID" 73} 74 75check_pid_and_port() 76{ 77 local pid_file="$1" 78 local pid=$2 79 local addr="$3" 80 local port="$4" 81 82 local utils='rsync|stunnel' 83 84 if ! check_port $pid "$port" "$utils"; then 85 local port_info 86 local busy=0 87 88 if [ $lsof_available -ne 0 ]; then 89 port_info=$(lsof -Pnl -i ":$port" 2>/dev/null | \ 90 grep -F '(LISTEN)') 91 echo "$port_info" | \ 92 grep -q -E "[[:space:]](\\*|\\[?::\\]?):$port[[:space:]]" && busy=1 93 else 94 local filter='([^[:space:]]+[[:space:]]+){4}[^[:space:]]+' 95 if [ $sockstat_available -ne 0 ]; then 96 local opts='-p' 97 if [ "$OS" = 'FreeBSD' ]; then 98 # sockstat on FreeBSD requires the "-s" option 99 # to display the connection state: 100 opts='-sp' 101 # in addition, sockstat produces an additional column: 102 filter='([^[:space:]]+[[:space:]]+){5}[^[:space:]]+' 103 fi 104 port_info=$(sockstat "$opts" "$port" 2>/dev/null | \ 105 grep -E '[[:space:]]LISTEN' | grep -o -E "$filter") 106 else 107 port_info=$(ss -nlpH "( sport = :$port )" 2>/dev/null | \ 108 grep -F 'users:(' | grep -o -E "$filter") 109 fi 110 echo "$port_info" | \ 111 grep -q -E "[[:space:]](\\*|\\[?::\\]?):$port\$" && busy=1 112 fi 113 114 if [ $busy -eq 0 ]; then 115 if ! echo "$port_info" | grep -qw -F "[$addr]:$port" && \ 116 ! echo "$port_info" | grep -qw -F -- "$addr:$port" 117 then 118 if ! ps -p $pid >/dev/null 2>&1; then 119 wsrep_log_error \ 120 "rsync or stunnel daemon (PID: $pid)" \ 121 "terminated unexpectedly." 122 exit 16 # EBUSY 123 fi 124 return 1 125 fi 126 fi 127 128 if ! check_port $pid "$port" "$utils"; then 129 wsrep_log_error "rsync or stunnel daemon port '$port'" \ 130 "has been taken by another program" 131 exit 16 # EBUSY 132 fi 133 fi 134 135 check_pid "$pid_file" && [ $CHECK_PID -eq $pid ] 136} 137 138STUNNEL_CONF="$WSREP_SST_OPT_DATA/stunnel.conf" 139STUNNEL_PID="$WSREP_SST_OPT_DATA/stunnel.pid" 140 141MAGIC_FILE="$WSREP_SST_OPT_DATA/rsync_sst_complete" 142 143BINLOG_TAR_FILE="$WSREP_SST_OPT_DATA/wsrep_sst_binlog.tar" 144BINLOG_N_FILES=1 145 146get_binlog 147 148if [ -n "$WSREP_SST_OPT_BINLOG" ]; then 149 BINLOG_DIRNAME=$(dirname "$WSREP_SST_OPT_BINLOG") 150 BINLOG_FILENAME=$(basename "$WSREP_SST_OPT_BINLOG") 151fi 152 153# if no command line argument and INNODB_LOG_GROUP_HOME is not set, 154# try to get it from my.cnf: 155if [ -z "$INNODB_LOG_GROUP_HOME" ]; then 156 INNODB_LOG_GROUP_HOME=$(parse_cnf '--mysqld' 'innodb-log-group-home-dir') 157fi 158 159OLD_PWD="$(pwd)" 160 161WSREP_LOG_DIR="$INNODB_LOG_GROUP_HOME" 162 163cd "$WSREP_SST_OPT_DATA" 164if [ -n "$WSREP_LOG_DIR" ]; then 165 # handle both relative and absolute paths 166 [ ! -d "$WSREP_LOG_DIR" ] && mkdir -p "$WSREP_LOG_DIR" 167 cd "$WSREP_LOG_DIR" 168fi 169WSREP_LOG_DIR=$(pwd -P) 170 171cd "$OLD_PWD" 172 173# if no command line argument and INNODB_DATA_HOME_DIR environment variable 174# is not set, try to get it from my.cnf: 175if [ -z "$INNODB_DATA_HOME_DIR" ]; then 176 INNODB_DATA_HOME_DIR=$(parse_cnf '--mysqld' 'innodb-data-home-dir') 177fi 178 179cd "$WSREP_SST_OPT_DATA" 180if [ -n "$INNODB_DATA_HOME_DIR" ]; then 181 # handle both relative and absolute paths 182 [ ! -d "$INNODB_DATA_HOME_DIR" ] && mkdir -p "$INNODB_DATA_HOME_DIR" 183 cd "$INNODB_DATA_HOME_DIR" 184fi 185INNODB_DATA_HOME_DIR=$(pwd -P) 186 187cd "$OLD_PWD" 188 189# if no command line argument then try to get it from my.cnf: 190if [ -z "$INNODB_UNDO_DIR" ]; then 191 INNODB_UNDO_DIR=$(parse_cnf '--mysqld' 'innodb-undo-directory') 192fi 193 194cd "$WSREP_SST_OPT_DATA" 195if [ -n "$INNODB_UNDO_DIR" ]; then 196 # handle both relative and absolute paths 197 [ ! -d "$INNODB_UNDO_DIR" ] && mkdir -p "$INNODB_UNDO_DIR" 198 cd "$INNODB_UNDO_DIR" 199fi 200INNODB_UNDO_DIR=$(pwd -P) 201 202cd "$OLD_PWD" 203 204encgroups='--mysqld|sst' 205 206check_server_ssl_config 207 208SSTKEY="$tkey" 209SSTCERT="$tpem" 210SSTCA="$tcert" 211SSTCAP="$tcap" 212 213SSLMODE=$(parse_cnf "$encgroups" 'ssl-mode' | tr [:lower:] [:upper:]) 214 215if [ -z "$SSLMODE" ]; then 216 # Implicit verification if CA is set and the SSL mode 217 # is not specified by user: 218 if [ -n "$SSTCA$SSTCAP" ]; then 219 STUNNEL_BIN=$(commandex 'stunnel') 220 if [ -n "$STUNNEL_BIN" ]; then 221 SSLMODE='VERIFY_CA' 222 fi 223 # Require SSL by default if SSL key and cert are present: 224 elif [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then 225 SSLMODE='REQUIRED' 226 fi 227fi 228 229if [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then 230 verify_cert_matches_key "$SSTCERT" "$SSTKEY" 231fi 232 233CAFILE_OPT="" 234CAPATH_OPT="" 235if [ -n "$SSTCA$SSTCAP" ]; then 236 if [ -n "$SSTCA" ]; then 237 CAFILE_OPT="CAfile = $SSTCA" 238 fi 239 if [ -n "$SSTCAP" ]; then 240 CAPATH_OPT="CApath = $SSTCAP" 241 fi 242 if [ -n "$SSTCERT" ]; then 243 verify_ca_matches_cert "$SSTCERT" "$SSTCA" "$SSTCAP" 244 fi 245fi 246 247VERIFY_OPT="" 248CHECK_OPT="" 249CHECK_OPT_LOCAL="" 250if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then 251 case "$SSLMODE" in 252 'VERIFY_IDENTITY') 253 VERIFY_OPT='verifyPeer = yes' 254 ;; 255 'VERIFY_CA') 256 VERIFY_OPT='verifyChain = yes' 257 ;; 258 *) 259 wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'" 260 exit 22 # EINVAL 261 ;; 262 esac 263 if [ -z "$SSTCA$SSTCAP" ]; then 264 wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path" 265 exit 22 # EINVAL 266 fi 267 if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then 268 CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER" 269 elif [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then 270 # check if the address is an ip-address (v4 or v6): 271 if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \ 272 grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$' 273 then 274 CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED" 275 else 276 CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST" 277 fi 278 if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then 279 CHECK_OPT_LOCAL="checkHost = localhost" 280 fi 281 fi 282fi 283 284STUNNEL="" 285if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then 286 if [ -z "${STUNNEL_BIN+x}" ]; then 287 STUNNEL_BIN=$(commandex 'stunnel') 288 fi 289 if [ -n "$STUNNEL_BIN" ]; then 290 wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA'," \ 291 "CAPATH='$SSTCAP', ssl-mode='$SSLMODE'" 292 STUNNEL="$STUNNEL_BIN $STUNNEL_CONF" 293 fi 294fi 295 296readonly SECRET_TAG="secret" 297 298if [ "$WSREP_SST_OPT_ROLE" = 'donor' ] 299then 300 301 [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" 302 [ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE" 303 [ -f "$STUNNEL_PID" ] && rm -f "$STUNNEL_PID" 304 305 if [ -n "$STUNNEL" ] 306 then 307 cat << EOF > "$STUNNEL_CONF" 308key = $SSTKEY 309cert = $SSTCERT 310${CAFILE_OPT} 311${CAPATH_OPT} 312foreground = yes 313pid = $STUNNEL_PID 314debug = warning 315client = yes 316connect = $WSREP_SST_OPT_HOST_UNESCAPED:$WSREP_SST_OPT_PORT 317TIMEOUTclose = 0 318${VERIFY_OPT} 319${CHECK_OPT} 320${CHECK_OPT_LOCAL} 321EOF 322 else 323 [ -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF" 324 fi 325 326 RC=0 327 328 if [ $WSREP_SST_OPT_BYPASS -eq 0 ]; then 329 330 FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" 331 ERROR="$WSREP_SST_OPT_DATA/sst_error" 332 333 [ -f "$FLUSHED" ] && rm -f "$FLUSHED" 334 [ -f "$ERROR" ] && rm -f "$ERROR" 335 336 echo "flush tables" 337 338 # Wait for : 339 # (a) Tables to be flushed, AND 340 # (b) Cluster state ID & wsrep_gtid_domain_id to be written to the file, OR 341 # (c) ERROR file, in case flush tables operation failed. 342 343 while [ ! -r "$FLUSHED" ] && \ 344 ! grep -q -F ':' '--' "$FLUSHED" >/dev/null 2>&1 345 do 346 # Check whether ERROR file exists. 347 if [ -f "$ERROR" ]; then 348 # Flush tables operation failed. 349 rm -f "$ERROR" 350 exit 255 351 fi 352 sleep 0.2 353 done 354 355 STATE=$(cat "$FLUSHED") 356 rm -f "$FLUSHED" 357 358 sync 359 360 if [ -n "$WSREP_SST_OPT_BINLOG" -a -d "${BINLOG_DIRNAME:-}" ] 361 then 362 # Prepare binlog files 363 cd "$BINLOG_DIRNAME" 364 365 binlog_files_full=$(tail -n $BINLOG_N_FILES \ 366 "$WSREP_SST_OPT_BINLOG_INDEX") 367 binlog_files="" 368 for file in $binlog_files_full; do 369 binlog_file=$(basename "$file") 370 binlog_files="$binlog_files${binlog_files:+ }'$binlog_file'" 371 done 372 373 if [ -n "$binlog_files" ]; then 374 wsrep_log_info "Preparing binlog files for transfer:" 375 eval tar -cvf "'$BINLOG_TAR_FILE'" $binlog_files >&2 376 fi 377 378 cd "$OLD_PWD" 379 fi 380 381 # Use deltaxfer only for WAN 382 inv=$(basename "$0") 383 WHOLE_FILE_OPT="" 384 if [ "${inv%wsrep_sst_rsync_wan*}" = "$inv" ]; then 385 WHOLE_FILE_OPT="--whole-file" 386 fi 387 388# Old filter - include everything except selected 389# FILTER=(--exclude '*.err' --exclude '*.pid' --exclude '*.sock' \ 390# --exclude '*.conf' --exclude core --exclude 'galera.*' \ 391# --exclude grastate.txt --exclude '*.pem' \ 392# --exclude '*.[0-9][0-9][0-9][0-9][0-9][0-9]' --exclude '*.index') 393 394# New filter - exclude everything except dirs (schemas) and innodb files 395FILTER="-f '- /lost+found' 396 -f '- /.zfs' 397 -f '- /.fseventsd' 398 -f '- /.Trashes' 399 -f '- /.pid' 400 -f '- /.conf' 401 -f '+ /wsrep_sst_binlog.tar' 402 -f '- $INNODB_DATA_HOME_DIR/ib_lru_dump' 403 -f '- $INNODB_DATA_HOME_DIR/ibdata*' 404 -f '+ $INNODB_UNDO_DIR/undo*' 405 -f '+ /*/' 406 -f '- /*'" 407 408 # first, the normal directories, so that we can detect 409 # incompatible protocol: 410 eval rsync ${STUNNEL:+"--rsh='$STUNNEL'"} \ 411 --owner --group --perms --links --specials \ 412 --ignore-times --inplace --dirs --delete --quiet \ 413 $WHOLE_FILE_OPT $FILTER "'$WSREP_SST_OPT_DATA/'" \ 414 "'rsync://$WSREP_SST_OPT_ADDR'" >&2 || RC=$? 415 416 if [ $RC -ne 0 ]; then 417 wsrep_log_error "rsync returned code $RC:" 418 case $RC in 419 12) RC=71 # EPROTO 420 wsrep_log_error \ 421 "rsync server on the other end has incompatible" \ 422 "protocol. Make sure you have the same version of" \ 423 "rsync on all nodes." 424 ;; 425 22) RC=12 # ENOMEM 426 ;; 427 *) RC=255 # unknown error 428 ;; 429 esac 430 exit $RC 431 fi 432 433 # Transfer InnoDB data files 434 rsync ${STUNNEL:+--rsh="$STUNNEL"} \ 435 --owner --group --perms --links --specials \ 436 --ignore-times --inplace --dirs --delete --quiet \ 437 $WHOLE_FILE_OPT -f '+ /ibdata*' -f '+ /ib_lru_dump' \ 438 -f '- **' "$INNODB_DATA_HOME_DIR/" \ 439 "rsync://$WSREP_SST_OPT_ADDR-data_dir" >&2 || RC=$? 440 441 if [ $RC -ne 0 ]; then 442 wsrep_log_error "rsync innodb_data_home_dir returned code $RC:" 443 exit 255 # unknown error 444 fi 445 446 # second, we transfer InnoDB and Aria log files 447 rsync ${STUNNEL:+--rsh="$STUNNEL"} \ 448 --owner --group --perms --links --specials \ 449 --ignore-times --inplace --dirs --delete --quiet \ 450 $WHOLE_FILE_OPT -f '+ /ib_logfile[0-9]*' -f '+ /aria_log.*' \ 451 -f '+ /aria_log_control' -f '- **' "$WSREP_LOG_DIR/" \ 452 "rsync://$WSREP_SST_OPT_ADDR-log_dir" >&2 || RC=$? 453 454 if [ $RC -ne 0 ]; then 455 wsrep_log_error "rsync innodb_log_group_home_dir returned code $RC:" 456 exit 255 # unknown error 457 fi 458 459 # then, we parallelize the transfer of database directories, 460 # use '.' so that path concatenation works: 461 462 cd "$WSREP_SST_OPT_DATA" 463 464 backup_threads=$(parse_cnf '--mysqld|sst' 'backup-threads') 465 if [ -z "$backup_threads" ]; then 466 get_proc 467 backup_threads=$nproc 468 fi 469 470 find . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \ 471 -not -name '.zfs' -print0 | xargs -I{} -0 -P $backup_threads \ 472 rsync ${STUNNEL:+--rsh="$STUNNEL"} \ 473 --owner --group --perms --links --specials --ignore-times \ 474 --inplace --recursive --delete --quiet $WHOLE_FILE_OPT \ 475 --exclude '*/ib_logfile*' --exclude '*/aria_log.*' \ 476 --exclude '*/aria_log_control' "$WSREP_SST_OPT_DATA/{}/" \ 477 "rsync://$WSREP_SST_OPT_ADDR/{}" >&2 || RC=$? 478 479 cd "$OLD_PWD" 480 481 if [ $RC -ne 0 ]; then 482 wsrep_log_error "find/rsync returned code $RC:" 483 exit 255 # unknown error 484 fi 485 486 else # BYPASS 487 488 wsrep_log_info "Bypassing state dump." 489 490 # Store donor's wsrep GTID (state ID) and wsrep_gtid_domain_id 491 # (separated by a space). 492 STATE="$WSREP_SST_OPT_GTID $WSREP_SST_OPT_GTID_DOMAIN_ID" 493 494 fi 495 496 echo 'continue' # now server can resume updating data 497 498 echo "$STATE" > "$MAGIC_FILE" 499 500 if [ -n "$WSREP_SST_OPT_REMOTE_PSWD" ]; then 501 # Let joiner know that we know its secret 502 echo "$SECRET_TAG $WSREP_SST_OPT_REMOTE_PSWD" >> "$MAGIC_FILE" 503 fi 504 505 rsync ${STUNNEL:+--rsh="$STUNNEL"} \ 506 --archive --quiet --checksum "$MAGIC_FILE" \ 507 "rsync://$WSREP_SST_OPT_ADDR" >&2 || RC=$? 508 509 if [ $RC -ne 0 ]; then 510 wsrep_log_error "rsync $MAGIC_FILE returned code $RC:" 511 exit 255 # unknown error 512 fi 513 514 echo "done $STATE" 515 516 if [ -n "$STUNNEL" ]; then 517 [ -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF" 518 [ -f "$STUNNEL_PID" ] && rm -f "$STUNNEL_PID" 519 fi 520 521elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] 522then 523 check_sockets_utils 524 525 SST_PID="$WSREP_SST_OPT_DATA/wsrep_sst.pid" 526 527 # give some time for previous SST to complete: 528 check_round=0 529 while check_pid "$SST_PID" 0 'wsrep_sst_'; do 530 wsrep_log_info "previous SST is not completed, waiting for it to exit" 531 check_round=$(( check_round + 1 )) 532 if [ $check_round -eq 10 ]; then 533 wsrep_log_error "previous SST script still running." 534 exit 114 # EALREADY 535 fi 536 sleep 1 537 done 538 539 echo $$ > "$SST_PID" 540 541 # give some time for stunnel from the previous SST to complete: 542 check_round=0 543 while check_pid "$STUNNEL_PID" 1; do 544 wsrep_log_info "Lingering stunnel daemon found at startup," \ 545 "waiting for it to exit" 546 check_round=$(( check_round + 1 )) 547 if [ $check_round -eq 10 ]; then 548 wsrep_log_error "stunnel daemon already running." 549 exit 114 # EALREADY 550 fi 551 sleep 1 552 done 553 554 MODULE="rsync_sst" 555 RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" 556 RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" 557 558 # give some time for rsync from the previous SST to complete: 559 check_round=0 560 while check_pid "$RSYNC_PID" 1; do 561 wsrep_log_info "Lingering rsync daemon found at startup," \ 562 "waiting for it to exit" 563 check_round=$(( check_round + 1 )) 564 if [ $check_round -eq 10 ]; then 565 wsrep_log_error "rsync daemon already running." 566 exit 114 # EALREADY 567 fi 568 sleep 1 569 done 570 571 [ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE" 572 [ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE" 573 574 [ -z "$STUNNEL" -a -f "$STUNNEL_CONF" ] && rm -f "$STUNNEL_CONF" 575 576 ADDR="$WSREP_SST_OPT_ADDR" 577 RSYNC_PORT="$WSREP_SST_OPT_PORT" 578 RSYNC_ADDR="$WSREP_SST_OPT_HOST" 579 RSYNC_ADDR_UNESCAPED="$WSREP_SST_OPT_HOST_UNESCAPED" 580 581 trap "exit 32" HUP PIPE 582 trap "exit 3" INT TERM ABRT 583 trap cleanup_joiner EXIT 584 585 touch "$SST_PROGRESS_FILE" 586 587 if [ -n "${MYSQL_TMP_DIR:-}" ]; then 588 SILENT="log file = $MYSQL_TMP_DIR/rsyncd.log" 589 else 590 SILENT="" 591 fi 592 593cat << EOF > "$RSYNC_CONF" 594pid file = $RSYNC_PID 595use chroot = no 596read only = no 597timeout = 300 598$SILENT 599[$MODULE] 600 path = $WSREP_SST_OPT_DATA 601 exclude = .zfs 602[$MODULE-log_dir] 603 path = $WSREP_LOG_DIR 604[$MODULE-data_dir] 605 path = $INNODB_DATA_HOME_DIR 606EOF 607 608# rm -rf "$DATA/ib_logfile"* # we don't want old logs around 609 610 # If the IP is local, listen only on it: 611 if is_local_ip "$RSYNC_ADDR_UNESCAPED" 612 then 613 RSYNC_EXTRA_ARGS="--address $RSYNC_ADDR_UNESCAPED" 614 STUNNEL_ACCEPT="$RSYNC_ADDR_UNESCAPED:$RSYNC_PORT" 615 else 616 # Not local, possibly a NAT, listen on all interfaces: 617 RSYNC_EXTRA_ARGS="" 618 STUNNEL_ACCEPT="$RSYNC_PORT" 619 # Overwrite address with all: 620 RSYNC_ADDR="*" 621 fi 622 623 if [ -z "$STUNNEL" ]; then 624 rsync --daemon --no-detach --port "$RSYNC_PORT" \ 625 --config "$RSYNC_CONF" $RSYNC_EXTRA_ARGS & 626 RSYNC_REAL_PID=$! 627 TRANSFER_REAL_PID=$RSYNC_REAL_PID 628 TRANSFER_PID="$RSYNC_PID" 629 else 630 # Let's check if the path to the config file contains a space? 631 RSYNC_BIN=$(commandex 'rsync') 632 if [ "${RSYNC_CONF#* }" = "$RSYNC_CONF" ]; then 633 cat << EOF > "$STUNNEL_CONF" 634key = $SSTKEY 635cert = $SSTCERT 636${CAFILE_OPT} 637${CAPATH_OPT} 638foreground = yes 639pid = $STUNNEL_PID 640debug = warning 641client = no 642${VERIFY_OPT} 643${CHECK_OPT} 644${CHECK_OPT_LOCAL} 645[rsync] 646accept = $STUNNEL_ACCEPT 647exec = $RSYNC_BIN 648execargs = rsync --server --daemon --config=$RSYNC_CONF . 649EOF 650 else 651 # The path contains a space, so we will run it via 652 # shell with "eval" command: 653 export RSYNC_CMD="eval '$RSYNC_BIN' --server --daemon --config='$RSYNC_CONF' ." 654 cat << EOF > "$STUNNEL_CONF" 655key = $SSTKEY 656cert = $SSTCERT 657${CAFILE_OPT} 658${CAPATH_OPT} 659foreground = yes 660pid = $STUNNEL_PID 661debug = warning 662client = no 663${VERIFY_OPT} 664${CHECK_OPT} 665${CHECK_OPT_LOCAL} 666[rsync] 667accept = $STUNNEL_ACCEPT 668exec = $SHELL 669execargs = $SHELL -c \$RSYNC_CMD 670EOF 671 fi 672 stunnel "$STUNNEL_CONF" & 673 STUNNEL_REAL_PID=$! 674 TRANSFER_REAL_PID=$STUNNEL_REAL_PID 675 TRANSFER_PID="$STUNNEL_PID" 676 fi 677 678 if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ] 679 then # backward-incompatible behavior 680 CN="" 681 if [ -n "$SSTCERT" ] 682 then 683 # find out my Common Name 684 get_openssl 685 if [ -z "$OPENSSL_BINARY" ]; then 686 wsrep_log_error \ 687 'openssl not found but it is required for authentication' 688 exit 42 689 fi 690 CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$SSTCERT" | \ 691 tr "," "\n" | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ 692 sed s/\ %//) 693 fi 694 MY_SECRET="$(wsrep_gen_secret)" 695 # Add authentication data to address 696 ADDR="$CN:$MY_SECRET@$WSREP_SST_OPT_HOST" 697 else 698 MY_SECRET="" # for check down in recv_joiner() 699 ADDR="$WSREP_SST_OPT_HOST" 700 fi 701 702 until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID \ 703 "$RSYNC_ADDR_UNESCAPED" "$RSYNC_PORT" 704 do 705 sleep 0.2 706 done 707 708 echo "ready $ADDR:$RSYNC_PORT/$MODULE" 709 710 MYSQLD_PID="$WSREP_SST_OPT_PARENT" 711 712 # wait for SST to complete by monitoring magic file 713 while [ ! -r "$MAGIC_FILE" ] && check_pid "$TRANSFER_PID" && \ 714 ps -p $MYSQLD_PID >/dev/null 2>&1 715 do 716 sleep 1 717 done 718 719 if ! ps -p $MYSQLD_PID >/dev/null 2>&1 720 then 721 wsrep_log_error \ 722 "Parent mysqld process (PID: $MYSQLD_PID) terminated unexpectedly." 723 kill -- -$MYSQLD_PID 724 sleep 1 725 exit 32 726 fi 727 728 if [ -n "$WSREP_SST_OPT_BINLOG" ]; then 729 if [ -f "$BINLOG_TAR_FILE" ]; then 730 cd "$BINLOG_DIRNAME" 731 732 binlog_index="$WSREP_SST_OPT_BINLOG_INDEX" 733 734 # Clean up old binlog files first 735 rm -f "$BINLOG_FILENAME".[0-9]* 736 [ -f "$binlog_index" ] && rm -f "$binlog_index" 737 738 # Create a temporary file: 739 tmpdir=$(parse_cnf '--mysqld|sst' 'tmpdir') 740 if [ -z "$tmpdir" ]; then 741 tmpfile="$(mktemp)" 742 elif [ "$OS" = 'Linux' ]; then 743 tmpfile=$(mktemp "--tmpdir=$tmpdir") 744 else 745 tmpfile=$(TMPDIR="$tmpdir"; mktemp) 746 fi 747 748 wsrep_log_info "Extracting binlog files:" 749 if ! tar -xvf "$BINLOG_TAR_FILE" > "$tmpfile"; then 750 wsrep_log_error "Error unpacking tar file with binlog files" 751 rm -f "$tmpfile" 752 exit 32 753 fi 754 755 # Rebuild binlog index: 756 while read bin_file; do 757 echo "$BINLOG_DIRNAME/$bin_file" >> "$binlog_index" 758 done < "$tmpfile" 759 rm -f "$tmpfile" 760 761 cd "$OLD_PWD" 762 fi 763 fi 764 765 if [ -r "$MAGIC_FILE" ]; then 766 if [ -n "$MY_SECRET" ]; then 767 # check donor supplied secret 768 SECRET=$(grep -F -- "$SECRET_TAG " "$MAGIC_FILE" 2>/dev/null | \ 769 cut -d ' ' -f 2) 770 if [ "$SECRET" != "$MY_SECRET" ]; then 771 wsrep_log_error "Donor does not know my secret!" 772 wsrep_log_info "Donor: '$SECRET', my: '$MY_SECRET'" 773 exit 32 774 fi 775 # remove secret from the magic file, and output 776 # the UUID:seqno & wsrep_gtid_domain_id: 777 grep -v -F -- "$SECRET_TAG " "$MAGIC_FILE" 778 else 779 # Output the UUID:seqno and wsrep_gtid_domain_id: 780 cat "$MAGIC_FILE" 781 fi 782 else 783 # this message should cause joiner to abort 784 echo "rsync process ended without creating '$MAGIC_FILE'" 785 fi 786 787# wsrep_cleanup_progress_file 788# cleanup_joiner 789else 790 wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'" 791 exit 22 # EINVAL 792fi 793 794[ -f "$BINLOG_TAR_FILE" ] && rm -f "$BINLOG_TAR_FILE" 795 796exit 0 797