From 09b824671a8e5d48312e1129e7a280c589b61ec8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristoffer=20Gr=C3=B6nlund?= <krig@koru.se>
Date: Tue, 5 Sep 2017 09:26:30 +0200
Subject: [PATCH 13/13] High: galera: Backport galera fixes from upstream
 (bsc#1055017) (bsc#1056635)

Contains the following upstream patches:

* galera: Fix instance name in master_exists()
* galera: Honor "safe_to_bootstrap" flag in grastate.dat
---
 heartbeat/galera | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 65 insertions(+), 3 deletions(-)

diff --git a/heartbeat/galera b/heartbeat/galera
index 32c42221..dc681a47 100755
--- a/heartbeat/galera
+++ b/heartbeat/galera
@@ -332,6 +332,27 @@ get_last_commit()
     fi
 }
 
+clear_safe_to_bootstrap()
+{
+    ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-safe-to-bootstrap" -D
+}
+
+set_safe_to_bootstrap()
+{
+    ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-safe-to-bootstrap" -v $1
+}
+
+get_safe_to_bootstrap()
+{
+    local node=$1
+
+    if [ -z "$node" ]; then
+        ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-safe-to-bootstrap" -Q 2>/dev/null
+    else
+        ${HA_SBIN_DIR}/crm_attribute -N $node -l reboot --name "${INSTANCE_ATTR_NAME}-safe-to-bootstrap" -Q 2>/dev/null
+    fi
+}
+
 wait_for_sync()
 {
     local state=$(get_status_variable "wsrep_local_state")
@@ -386,7 +407,7 @@ master_exists()
         return 1
     fi
     # determine if a master instance is already up and is healthy
-    crm_mon --as-xml | grep "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1
+    crm_mon --as-xml | grep "resource.*id=\"${INSTANCE_ATTR_NAME}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1
     return $?
 }
 
@@ -465,6 +486,7 @@ detect_first_master()
     local all_nodes
     local best_node_gcomm
     local best_node
+    local safe_to_bootstrap
 
     all_nodes=$(echo "$OCF_RESKEY_wsrep_cluster_address" | sed 's/gcomm:\/\///g' | tr -d ' ' | tr -s ',' ' ')
     best_node_gcomm=$(echo "$all_nodes" | sed 's/^.* \(.*\)$/\1/')
@@ -492,6 +514,19 @@ detect_first_master()
     done
 
     for node in $nodes_recovered $nodes; do
+        safe_to_bootstrap=$(get_safe_to_bootstrap $node)
+
+        if [ "$safe_to_bootstrap" = "1" ]; then
+            # Galera marked the node as safe to boostrap during shutdown. Let's just
+            # pick it as our bootstrap node.
+            ocf_log info "Node <${node}> is marked as safe to bootstrap."
+            best_node=$node
+
+            # We don't need to wait for the other nodes to report state in this case
+            missing_nodes=0
+            break
+        fi
+
         last_commit=$(get_last_commit $node)
 
         if [ -z "$last_commit" ]; then
@@ -522,6 +557,22 @@ detect_first_master()
     set_bootstrap_node $best_node
 }
 
+detect_safe_to_bootstrap()
+{
+    local safe_to_bootstrap=""
+
+    if [ -f ${OCF_RESKEY_datadir}/grastate.dat ]; then
+        ocf_log info "attempting to read safe_to_bootstrap flag from ${OCF_RESKEY_datadir}/grastate.dat"
+        safe_to_bootstrap=$(sed -n 's/^safe_to_bootstrap:\s*\(.*\)$/\1/p' < ${OCF_RESKEY_datadir}/grastate.dat)
+    fi
+
+    if [ "$safe_to_bootstrap" = "1" ] || [ "$safe_to_bootstrap" = "0" ]; then
+        set_safe_to_bootstrap $safe_to_bootstrap
+    else
+        clear_safe_to_bootstrap
+    fi
+}
+
 detect_last_commit()
 {
     local last_commit
@@ -596,7 +647,7 @@ galera_promote()
     local rc
     local extra_opts
     local bootstrap
-    
+    local safe_to_bootstrap
     master_exists
     if [ $? -eq 0 ]; then
         # join without bootstrapping
@@ -605,6 +656,11 @@ galera_promote()
         bootstrap=$(is_bootstrap)
 
         if ocf_is_true $bootstrap; then
+            # The best node for bootstrapping wasn't cleanly shutdown. Allow
+            # bootstrapping anyways
+            if [ "$(get_safe_to_bootstrap)" = "0" ]; then
+                sed -ie 's/^\(safe_to_bootstrap:\) 0/\1 1/' ${OCF_RESKEY_datadir}/grastate.dat
+            fi
             ocf_log info "Node <${NODENAME}> is bootstrapping the cluster"
             extra_opts="--wsrep-cluster-address=gcomm://"
         else
@@ -621,12 +677,14 @@ galera_promote()
             clear_bootstrap_node
             ocf_log info "boostrap node already up, promoting the rest of the galera instances."
         fi
+        clear_safe_to_bootstrap
         clear_last_commit
         return $OCF_SUCCESS
     fi
 
-    # last commit is no longer relevant once promoted
+    # last commit/safe_to_bootstrap flag are no longer relevant once promoted
     clear_last_commit
+    clear_safe_to_bootstrap
 
     mysql_common_prepare_dirs
     mysql_common_start "$extra_opts"
@@ -687,6 +745,7 @@ galera_demote()
     clear_bootstrap_node
     clear_last_commit
     clear_no_grastate
+    clear_safe_to_bootstrap
 
     # Clear master score here rather than letting pacemaker do so once
     # demote finishes. This way a promote cannot take place right
@@ -696,6 +755,7 @@ galera_demote()
     clear_master_score
 
     # record last commit for next promotion
+    detect_safe_to_bootstrap
     detect_last_commit
     rc=$?
     return $rc
@@ -726,6 +786,7 @@ galera_start()
 
     mysql_common_prepare_dirs
 
+    detect_safe_to_bootstrap
     detect_last_commit
     rc=$?
     if [ $rc -ne $OCF_SUCCESS ]; then
@@ -815,6 +876,7 @@ galera_stop()
     mysql_common_stop
     rc=$1
 
+    clear_safe_to_bootstrap
     clear_last_commit
     clear_master_score
     clear_bootstrap_node
-- 
2.14.1

