From fa08cb4ee79e77f47177c9713b31d52905acbaf3 Mon Sep 17 00:00:00 2001
From: Anthony Yeh <enisoc@google.com>
Date: Fri, 18 Nov 2016 16:10:05 -0800
Subject: [PATCH] Clone from previous peer instead of from master.

---
 .../mysql-statefulset.yaml                    | 43 +++++++++++++------
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/docs/tutorials/replicated-stateful-application/mysql-statefulset.yaml b/docs/tutorials/replicated-stateful-application/mysql-statefulset.yaml
index f4a6c34df8..accefb2fe2 100644
--- a/docs/tutorials/replicated-stateful-application/mysql-statefulset.yaml
+++ b/docs/tutorials/replicated-stateful-application/mysql-statefulset.yaml
@@ -40,9 +40,11 @@ spec:
               # Skip the clone if data already exists.\n
               [[ -d /var/lib/mysql/mysql ]] && exit 0\n
               # Skip the clone on master (ordinal index 0).\n
-              [[ `hostname` =~ -0$ ]] && exit 0\n
-              # Clone data from master.\n
-              ncat --recv-only mysql-0.mysql 3307 | xbstream -x -C /var/lib/mysql\n
+              [[ `hostname` =~ -([0-9]+)$ ]] || exit 1\n
+              ordinal=${BASH_REMATCH[1]}\n
+              [[ $ordinal -eq 0 ]] && exit 0\n
+              # Clone data from previous peer.\n
+              ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql\n
               # Prepare the backup.\n
               xtrabackup --prepare --target-dir=/var/lib/mysql\n
             "],
@@ -92,31 +94,44 @@ spec:
         - "-c"
         - |
           set -ex
+          cd /var/lib/mysql
+
+          # Determine binlog position of cloned data, if any.
+          if [[ -f xtrabackup_slave_info ]]; then
+            # XtraBackup already generated a partial "CHANGE MASTER TO" query
+            # because we're cloning from an existing slave.
+            mv xtrabackup_slave_info change_master_to.sql.in
+            # Ignore xtrabackup_binlog_info in this case (it's useless).
+            rm xtrabackup_binlog_info
+          elif [[ -f xtrabackup_binlog_info ]]; then
+            # We're cloning directly from master. Parse binlog position.
+            [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
+            rm xtrabackup_binlog_info
+            echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
+                  MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
+          fi
 
           # Check if we need to complete a clone by starting replication.
-          cd /var/lib/mysql
-          if [[ -f xtrabackup_binlog_info ]]; then
-            echo "Waiting for mysqld to accept connections"
+          if [[ -f change_master_to.sql.in ]]; then
+            echo "Waiting for mysqld to be ready (accepting connections)"
             until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done
 
             echo "Initializing replication from clone position"
-            [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
-            mv xtrabackup_binlog_info xtrabackup_binlog_info.orig
+            # In case of container restart, attempt this at-most-once.
+            mv change_master_to.sql.in change_master_to.sql.orig
             mysql -h 127.0.0.1 <<EOF
-          CHANGE MASTER TO
+          $(<change_master_to.sql.orig),
             MASTER_HOST='mysql-0.mysql',
             MASTER_USER='root',
             MASTER_PASSWORD='',
-            MASTER_CONNECT_RETRY=10,
-            MASTER_LOG_FILE='${BASH_REMATCH[1]}',
-            MASTER_LOG_POS=${BASH_REMATCH[2]};
+            MASTER_CONNECT_RETRY=10;
           START SLAVE;
           EOF
           fi
 
-          # Start a server to send backups when requested.
+          # Start a server to send backups when requested by peers.
           exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
-            "xtrabackup --backup --stream=xbstream --host=127.0.0.1 --user=root"
+            "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root"
         volumeMounts:
         - name: data
           mountPath: /var/lib/mysql