Blame SOURCES/bz1116166-galera-agent.patch

b4da46
From 591302a81c5961a03ffad70369433c20b31aebbe Mon Sep 17 00:00:00 2001
b4da46
From: David Vossel <dvossel@redhat.com>
b4da46
Date: Fri, 18 Jul 2014 13:01:48 -0500
b4da46
Subject: [PATCH] galera resource agent
b4da46
b4da46
---
b4da46
 doc/man/Makefile.am         |   1 +
b4da46
 heartbeat/Makefile.am       |   2 +
b4da46
 heartbeat/galera            | 693 ++++++++++++++++++++++++++++++++++++++++++++
b4da46
 heartbeat/mysql             | 273 +----------------
b4da46
 heartbeat/mysql-common.sh   | 279 ++++++++++++++++++
b4da46
 heartbeat/ocf-shellfuncs.in |   1 +
b4da46
 6 files changed, 991 insertions(+), 258 deletions(-)
b4da46
 create mode 100644 heartbeat/galera
b4da46
 create mode 100644 heartbeat/mysql-common.sh
b4da46
b4da46
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
b4da46
index a3517aa..e97c7e9 100644
b4da46
--- a/doc/man/Makefile.am
b4da46
+++ b/doc/man/Makefile.am
b4da46
@@ -102,6 +102,7 @@ man_MANS	       = ocf_heartbeat_AoEtarget.7 \
b4da46
                           ocf_heartbeat_ethmonitor.7 \
b4da46
                           ocf_heartbeat_exportfs.7 \
b4da46
                           ocf_heartbeat_fio.7 \
b4da46
+                          ocf_heartbeat_galera.7 \
b4da46
                           ocf_heartbeat_iSCSILogicalUnit.7 \
b4da46
                           ocf_heartbeat_iSCSITarget.7 \
b4da46
                           ocf_heartbeat_ids.7 \
b4da46
diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am
b4da46
index 65a2cfb..aab521f 100644
b4da46
--- a/heartbeat/Makefile.am
b4da46
+++ b/heartbeat/Makefile.am
b4da46
@@ -73,6 +73,7 @@ ocf_SCRIPTS	     =  ClusterMon		\
b4da46
 			exportfs		\
b4da46
 			Filesystem		\
b4da46
 			fio			\
b4da46
+			galera			\
b4da46
 			ids			\
b4da46
 			iscsi			\
b4da46
 			ICP			\
b4da46
@@ -140,6 +141,7 @@ ocfcommon_DATA		= ocf-shellfuncs 	\
b4da46
 			  sapdb-nosha.sh	\
b4da46
 			  sapdb.sh		\
b4da46
 			  ora-common.sh		\
b4da46
+			  mysql-common.sh		\
b4da46
 			  findif.sh
b4da46
 
b4da46
 # Legacy locations
b4da46
diff --git a/heartbeat/galera b/heartbeat/galera
b4da46
new file mode 100644
b4da46
index 0000000..6d8cf12
b4da46
--- /dev/null
b4da46
+++ b/heartbeat/galera
b4da46
@@ -0,0 +1,693 @@
b4da46
+#!/bin/sh
b4da46
+#
b4da46
+# Copyright (c) 2014 David Vossel <dvossel@redhat.com>
b4da46
+#                    All Rights Reserved.
b4da46
+#
b4da46
+# This program is free software; you can redistribute it and/or modify
b4da46
+# it under the terms of version 2 of the GNU General Public License as
b4da46
+# published by the Free Software Foundation.
b4da46
+#
b4da46
+# This program is distributed in the hope that it would be useful, but
b4da46
+# WITHOUT ANY WARRANTY; without even the implied warranty of
b4da46
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
b4da46
+#
b4da46
+# Further, this software is distributed without any warranty that it is
b4da46
+# free of the rightful claim of any third person regarding infringement
b4da46
+# or the like.  Any license provided herein, whether implied or
b4da46
+# otherwise, applies only to this software file.  Patent licenses, if
b4da46
+# any, provided herein do not apply to combinations of this program with
b4da46
+# other software, or any other product whatsoever.
b4da46
+#
b4da46
+# You should have received a copy of the GNU General Public License
b4da46
+# along with this program; if not, write the Free Software Foundation,
b4da46
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
b4da46
+#
b4da46
+
b4da46
+##
b4da46
+# README.
b4da46
+# 
b4da46
+# This agent only supports being configured as a multistate Master
b4da46
+# resource.
b4da46
+#
b4da46
+# Slave vs Master role:
b4da46
+#
b4da46
+# During the 'Slave' role, galera instances are in read-only mode and
b4da46
+# will not attempt to connect to the cluster. This role exists only as
b4da46
+# a means to determine which galera instance is the most up-to-date. The
b4da46
+# most up-to-date node will be used to bootstrap a galera cluster that
b4da46
+# has no current members.
b4da46
+#
b4da46
+# The galera instances will only begin to be promoted to the Master role
b4da46
+# once all the nodes in the 'wsrep_cluster_address' connection address
b4da46
+# have entered read-only mode. At that point the node containing the
b4da46
+# database that is most current will be promoted to Master. Once the first
b4da46
+# Master instance bootstraps the galera cluster, the other nodes will be
b4da46
+# promoted to Master as well.
b4da46
+#
b4da46
+# Example: Create a galera cluster using nodes rhel7-node1 rhel7-node2 rhel7-node3
b4da46
+#
b4da46
+# pcs resource create db galera enable_creation=true \
b4da46
+# wsrep_cluster_address="gcomm://rhel7-auto1,rhel7-auto2,rhel7-auto3" meta master-max=3 --master
b4da46
+#
b4da46
+# By setting the 'enable_creation' option, the database will be automatically 
b4da46
+# generated at startup. The meta attribute 'master-max=3' means that all 3
b4da46
+# nodes listed in the wsrep_cluster_address list will be allowed to connect
b4da46
+# to the galera cluster and perform replication.
b4da46
+#
b4da46
+# NOTE: If you have more nodes in the pacemaker cluster then you wish
b4da46
+# to have in the galera cluster, make sure to use location contraints to prevent
b4da46
+# pacemaker from attempting to place a galera instance on a node that is
b4da46
+# not in the 'wsrep_cluster_address" list. 
b4da46
+#
b4da46
+##
b4da46
+
b4da46
+#######################################################################
b4da46
+# Initialization:
b4da46
+
b4da46
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
b4da46
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
b4da46
+. ${OCF_FUNCTIONS_DIR}/mysql-common.sh
b4da46
+
b4da46
+# It is common for some galera instances to store
b4da46
+# check user that can be used to query status
b4da46
+# in this file
b4da46
+if [ -f "/etc/sysconfig/clustercheck" ]; then
b4da46
+    . /etc/sysconfig/clustercheck
b4da46
+fi
b4da46
+
b4da46
+#######################################################################
b4da46
+
b4da46
+usage() {
b4da46
+  cat <
b4da46
+usage: $0 (start|stop|validate-all|meta-data|monitor|promote|demote|notify)
b4da46
+
b4da46
+$0 manages a galera Database as an HA resource.
b4da46
+
b4da46
+The 'start' operation starts the database.
b4da46
+The 'stop' operation stops the database.
b4da46
+The 'status' operation reports whether the database is running
b4da46
+The 'monitor' operation reports whether the database seems to be working
b4da46
+The 'promote' operation makes this mysql server run as master
b4da46
+The 'demote' operation makes this mysql server run as slave
b4da46
+The 'validate-all' operation reports whether the parameters are valid
b4da46
+
b4da46
+UEND
b4da46
+}
b4da46
+
b4da46
+meta_data() {
b4da46
+   cat <
b4da46
+
b4da46
+
b4da46
+<resource-agent name="galera">
b4da46
+<version>1.0</version>
b4da46
+
b4da46
+<longdesc lang="en">
b4da46
+Resource script for managing galara database.
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">Manages a galara instance</shortdesc>
b4da46
+<parameters>
b4da46
+
b4da46
+<parameter name="binary" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Location of the MySQL server binary
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL server binary</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_binary_default}" />
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="client_binary" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Location of the MySQL client binary
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL client binary</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_client_binary_default}" />
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="config" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Configuration file
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL config</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_config_default}" />
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="datadir" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Directory containing databases
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL datadir</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_datadir_default}" />
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="user" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+User running MySQL daemon
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL user</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_user_default}" />
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="group" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Group running MySQL daemon (for logfile and directory permissions)
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL group</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_group_default}"/>
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="log" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+The logfile to be used for mysqld.
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL log file</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_log_default}"/>
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="pid" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+The pidfile to be used for mysqld.
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL pid file</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_pid_default}"/>
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="socket" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+The socket to be used for mysqld.
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL socket</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_socket_default}"/>
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="enable_creation" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+If the MySQL database does not exist, it will be created
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">Create the database if it does not exist</shortdesc>
b4da46
+<content type="boolean" default="${OCF_RESKEY_enable_creation_default}"/>
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="additional_parameters" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Additional parameters which are passed to the mysqld on startup.
b4da46
+(e.g. --skip-external-locking or --skip-grant-tables)
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">Additional parameters to pass to mysqld</shortdesc>
b4da46
+<content type="string" default="${OCF_RESKEY_additional_parameters_default}"/>
b4da46
+</parameter>
b4da46
+
b4da46
+
b4da46
+<parameter name="wsrep_cluster_address" unique="0" required="1">
b4da46
+<longdesc lang="en">
b4da46
+The galera cluster address. This takes the form of:
b4da46
+gcomm://node,node,node
b4da46
+
b4da46
+Only nodes present in this node list will be allowed to start a galera instance.
b4da46
+It is expected that the galera node names listed in this address match valid
b4da46
+pacemaker node names.
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">Galera cluster address</shortdesc>
b4da46
+<content type="string" default=""/>
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="check_user" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Cluster check user.
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">MySQL test user</shortdesc>
b4da46
+<content type="string" default="root" />
b4da46
+</parameter>
b4da46
+
b4da46
+<parameter name="check_passwd" unique="0" required="0">
b4da46
+<longdesc lang="en">
b4da46
+Cluster check user password
b4da46
+</longdesc>
b4da46
+<shortdesc lang="en">check password</shortdesc>
b4da46
+<content type="string" default="" />
b4da46
+</parameter>
b4da46
+
b4da46
+</parameters>
b4da46
+
b4da46
+<actions>
b4da46
+<action name="start" timeout="120" />
b4da46
+<action name="stop" timeout="120" />
b4da46
+<action name="status" timeout="60" />
b4da46
+<action name="monitor" depth="0" timeout="30" interval="20" />
b4da46
+<action name="monitor" role="Master" depth="0" timeout="30" interval="10" />
b4da46
+<action name="monitor" role="Slave" depth="0" timeout="30" interval="30" />
b4da46
+<action name="promote" timeout="120" />
b4da46
+<action name="demote" timeout="120" />
b4da46
+<action name="notify" timeout="90" />
b4da46
+<action name="validate-all" timeout="5" />
b4da46
+<action name="meta-data" timeout="5" />
b4da46
+</actions>
b4da46
+</resource-agent>
b4da46
+END
b4da46
+}
b4da46
+
b4da46
+get_option_variable()
b4da46
+{
b4da46
+    local key=$1
b4da46
+
b4da46
+    $MYSQL $MYSQL_OPTIONS_CHECK  -e "SHOW VARIABLES like '$key';" | tail -1
b4da46
+}
b4da46
+
b4da46
+get_status_variable()
b4da46
+{
b4da46
+    local key=$1
b4da46
+
b4da46
+    $MYSQL $MYSQL_OPTIONS_CHECK -e "show status like '$key';" | tail -1
b4da46
+}
b4da46
+
b4da46
+set_bootstrap_node()
b4da46
+{
b4da46
+    local node=$1
b4da46
+
b4da46
+    ${HA_SBIN_DIR}/crm_attribute -N $node -l reboot --name "${INSTANCE_ATTR_NAME}-bootstrap" -v "true"
b4da46
+}
b4da46
+
b4da46
+clear_bootstrap_node()
b4da46
+{
b4da46
+    ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-bootstrap" -D
b4da46
+}
b4da46
+
b4da46
+is_bootstrap()
b4da46
+{
b4da46
+    ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-bootstrap" -Q 2>/dev/null
b4da46
+
b4da46
+}
b4da46
+
b4da46
+clear_last_commit()
b4da46
+{
b4da46
+    ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-last-committed" -D
b4da46
+}
b4da46
+
b4da46
+set_last_commit()
b4da46
+{
b4da46
+    ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-last-committed" -v $1
b4da46
+}
b4da46
+
b4da46
+get_last_commit()
b4da46
+{
b4da46
+    local node=$1
b4da46
+
b4da46
+    if [ -z "$node" ]; then
b4da46
+       ${HA_SBIN_DIR}/crm_attribute -N $NODENAME -l reboot --name "${INSTANCE_ATTR_NAME}-last-committed" -Q 2>/dev/null
b4da46
+    else 
b4da46
+       ${HA_SBIN_DIR}/crm_attribute -N $node -l reboot --name "${INSTANCE_ATTR_NAME}-last-committed" -Q 2>/dev/null
b4da46
+    fi
b4da46
+}
b4da46
+
b4da46
+wait_for_sync()
b4da46
+{
b4da46
+    local state=$(get_status_variable "wsrep_local_state")
b4da46
+
b4da46
+    ocf_log info "Waiting for database to sync with the cluster. "
b4da46
+    while [ "$state" != "4" ]; do
b4da46
+        sleep 1
b4da46
+        state=$(get_status_variable "wsrep_local_state")
b4da46
+    done
b4da46
+    ocf_log info "Database synced."
b4da46
+}
b4da46
+
b4da46
+is_primary()
b4da46
+{
b4da46
+    cluster_status=$(get_status_variable "wsrep_cluster_status")
b4da46
+    if [ "$cluster_status" = "Primary" ]; then
b4da46
+        return 0
b4da46
+    fi
b4da46
+
b4da46
+    if [ -z "$cluster_status" ]; then
b4da46
+        ocf_log err "Unable to retrieve wsrep_cluster_status, verify check_user '$OCF_RESKEY_check_user' has permissions to view status"
b4da46
+    else
b4da46
+        ocf_log info "Galera instance wsrep_cluster_status=${cluster_status}"
b4da46
+    fi
b4da46
+    return 1
b4da46
+}
b4da46
+
b4da46
+is_readonly()
b4da46
+{
b4da46
+    local res=$(get_option_variable "read_only")
b4da46
+
b4da46
+    if ! ocf_is_true "$res"; then
b4da46
+        return 1
b4da46
+    fi
b4da46
+
b4da46
+    cluster_status=$(get_status_variable "wsrep_cluster_status")
b4da46
+    if ! [ "$cluster_status" = "Disconnected" ]; then
b4da46
+        return 1
b4da46
+    fi
b4da46
+
b4da46
+    return 0
b4da46
+}
b4da46
+
b4da46
+master_exists()
b4da46
+{
b4da46
+    # determine if a master instance is already up and is healthy
b4da46
+    crm_mon --as-xml | grep "resource.*id=\"${OCF_RESOURCE_INSTANCE}\".*role=\"Master\".*active=\"true\".*orphaned=\"false\".*failed=\"false\"" > /dev/null 2>&1
b4da46
+    return $?
b4da46
+}
b4da46
+
b4da46
+clear_master_score()
b4da46
+{
b4da46
+    local node=$1
b4da46
+    if [ -z "$node" ]; then
b4da46
+        $CRM_MASTER -D
b4da46
+    else 
b4da46
+        $CRM_MASTER -D -N $node
b4da46
+    fi
b4da46
+}
b4da46
+
b4da46
+set_master_score()
b4da46
+{
b4da46
+    local node=$1
b4da46
+
b4da46
+    if [ -z "$node" ]; then
b4da46
+        $CRM_MASTER -v 100
b4da46
+    else 
b4da46
+        $CRM_MASTER -N $node -v 100
b4da46
+    fi
b4da46
+}
b4da46
+
b4da46
+promote_everyone()
b4da46
+{
b4da46
+
b4da46
+    for node in $(echo "$OCF_RESKEY_wsrep_cluster_address" | sed 's/gcomm:\/\///g' | tr -d ' ' | tr -s ',' ' '); do
b4da46
+
b4da46
+        set_master_score $node
b4da46
+    done
b4da46
+}
b4da46
+
b4da46
+greater_than_equal_long()
b4da46
+{
b4da46
+    # there are values we need to compare in this script
b4da46
+    # that are too large for shell -gt to process
b4da46
+    echo | awk -v n1="$1" -v n2="$2"  '{if (n1>=n2) printf ("true"); else printf ("false");}' |  grep -q "true"
b4da46
+}
b4da46
+
b4da46
+detect_first_master()
b4da46
+{
b4da46
+    local best_commit=0
b4da46
+    local best_node="$NODENAME"
b4da46
+    local last_commit=0
b4da46
+    local missing_nodes=0
b4da46
+
b4da46
+    for node in $(echo "$OCF_RESKEY_wsrep_cluster_address" | sed 's/gcomm:\/\///g' | tr -d ' ' | tr -s ',' ' '); do
b4da46
+        last_commit=$(get_last_commit $node)
b4da46
+
b4da46
+        if [ -z "$last_commit" ]; then
b4da46
+            ocf_log info "Waiting on node <${node}> to report database status before Master instances can start."
b4da46
+            missing_nodes=1
b4da46
+            continue
b4da46
+        fi
b4da46
+
b4da46
+        # this means -1, or that no commit has occured yet.
b4da46
+        if [ "$last_commit" = "18446744073709551615" ]; then
b4da46
+            last_commit="0"
b4da46
+        fi
b4da46
+
b4da46
+        greater_than_equal_long "$last_commit" "$best_commit"
b4da46
+        if [ $? -eq 0 ]; then
b4da46
+            best_node=$node
b4da46
+            best_commit=$last_commit
b4da46
+        fi
b4da46
+
b4da46
+    done
b4da46
+
b4da46
+    if [ $missing_nodes -eq 1 ]; then
b4da46
+        return
b4da46
+    fi
b4da46
+
b4da46
+    ocf_log info "Promoting $best_node to be our bootstrap node"
b4da46
+    set_master_score $best_node
b4da46
+    set_bootstrap_node $best_node
b4da46
+}
b4da46
+
b4da46
+# For galera, promote is really start
b4da46
+galera_promote()
b4da46
+{
b4da46
+    local rc
b4da46
+    local extra_opts
b4da46
+    local bootstrap
b4da46
+    
b4da46
+    master_exists
b4da46
+    if [ $? -eq 0 ]; then
b4da46
+        # join without bootstrapping
b4da46
+        extra_opts="--wsrep-cluster-address=${OCF_RESKEY_wsrep_cluster_address}"
b4da46
+    else
b4da46
+        bootstrap=$(is_bootstrap)
b4da46
+
b4da46
+        if ocf_is_true $bootstrap; then
b4da46
+            ocf_log info "Node <${NODENAME}> is bootstrapping the cluster"
b4da46
+            extra_opts="--wsrep-cluster-address=gcomm://"
b4da46
+        else
b4da46
+            ocf_log err "Failure, Attempted to promote Master instance of $OCF_RESOURCE_INSTANCE before bootstrap node has been detected."
b4da46
+            return $OCF_ERR_GENERIC
b4da46
+        fi
b4da46
+
b4da46
+    fi
b4da46
+
b4da46
+    # make sure the read only instance is stopped
b4da46
+    mysql_common_stop
b4da46
+    rc=$?
b4da46
+    if [ $rc -ne $OCF_SUCCESS ] && [ $rc -ne $OCF_NOT_RUNNING ]; then
b4da46
+        ocf_log err "Failed to stop read-only galera instance during promotion to Master"
b4da46
+        return $rc
b4da46
+    fi
b4da46
+
b4da46
+    sleep 4
b4da46
+
b4da46
+    mysql_common_prepare_dirs
b4da46
+    mysql_common_start "$extra_opts"
b4da46
+    rc=$?
b4da46
+    if [ $rc != $OCF_SUCCESS ]; then
b4da46
+        return $rc
b4da46
+    fi
b4da46
+
b4da46
+    galera_monitor
b4da46
+    rc=$?
b4da46
+    if [ $rc != $OCF_SUCCESS -a $rc != $OCF_RUNNING_MASTER ]; then
b4da46
+        ocf_log err "Failed initial monitor action"
b4da46
+        return $rc
b4da46
+    fi
b4da46
+
b4da46
+    is_readonly
b4da46
+    if [ $? -eq 0 ]; then
b4da46
+        ocf_log err "Failure. Master instance started in read-only mode, check configuration."
b4da46
+        return $OCF_ERR_GENERIC
b4da46
+    fi
b4da46
+
b4da46
+    is_primary
b4da46
+    if [ $? -ne 0 ]; then
b4da46
+        ocf_log err "Failure. Master instance started, but is not in Primary mode."
b4da46
+        return $OCF_ERR_GENERIC
b4da46
+    fi
b4da46
+
b4da46
+    if ocf_is_true $bootstrap; then
b4da46
+        promote_everyone
b4da46
+        clear_bootstrap_node
b4da46
+        ocf_log info "Bootstrap complete, promoting the rest of the galera instances."
b4da46
+    else
b4da46
+        # if this is not the bootstrap node, make sure this instance
b4da46
+        # syncs with the rest of the cluster before promotion returns.
b4da46
+        wait_for_sync
b4da46
+    fi
b4da46
+
b4da46
+    # last commit is no longer relevant once promoted
b4da46
+    clear_last_commit
b4da46
+
b4da46
+    ocf_log info "Galera started"
b4da46
+    return $OCF_SUCCESS
b4da46
+}
b4da46
+
b4da46
+galera_demote()
b4da46
+{
b4da46
+    mysql_common_stop
b4da46
+    rc=$?
b4da46
+    if [ $rc -ne $OCF_SUCCESS ] && [ $rc -ne $OCF_NOT_RUNNING ]; then
b4da46
+        ocf_log err "Failed to stop Master galera instance during demotion to Master"
b4da46
+        return $rc
b4da46
+    fi
b4da46
+
b4da46
+    # if this node was previously a bootstrap node, that is no longer the case.
b4da46
+    clear_bootstrap_node
b4da46
+
b4da46
+    # start again in slave mode so the new last commit is recorded
b4da46
+    galera_start
b4da46
+}
b4da46
+
b4da46
+galera_start()
b4da46
+{
b4da46
+    local extra_opts='--read-only=true'
b4da46
+    local last_commit
b4da46
+
b4da46
+    echo $OCF_RESKEY_wsrep_cluster_address | grep -q $NODENAME
b4da46
+    if [ $? -ne 0 ]; then
b4da46
+        ocf_log err "local node <${NODENAME}> must be a member of the wsrep_cluster_address <${OCF_RESKEY_wsrep_cluster_address}>to start this galera instance"
b4da46
+        return $OCF_ERR_CONFIGURED
b4da46
+    fi
b4da46
+
b4da46
+    mysql_common_prepare_dirs
b4da46
+    mysql_common_start "$extra_opts"
b4da46
+
b4da46
+    is_readonly
b4da46
+    if [ $? -ne 0 ]; then
b4da46
+        ocf_log err "Failure. Slave instance did not start correctly in read-only mode, Make sure local galera.cnf does not have wsrep_cluster_address set."
b4da46
+        return $OCF_ERR_GENERIC
b4da46
+    fi
b4da46
+
b4da46
+    ocf_log info "attempting to detect last commit version"
b4da46
+    while [ -z "$last_commit" ]; do
b4da46
+        last_commit=$(get_status_variable "wsrep_last_committed")
b4da46
+        if [ -z "$last_commit" ]; then
b4da46
+            sleep 1
b4da46
+        fi
b4da46
+    done
b4da46
+    ocf_log info "Last commit version found:  $last_commit"
b4da46
+
b4da46
+    set_last_commit $last_commit
b4da46
+
b4da46
+    master_exists
b4da46
+    if [ $? -eq 0 ]; then
b4da46
+        ocf_log info "Master instances are already up, setting master score so this instance will join galera cluster."
b4da46
+        set_master_score $NODENAME
b4da46
+    else
b4da46
+        clear_master_score
b4da46
+        detect_first_master
b4da46
+    fi
b4da46
+
b4da46
+    return $OCF_SUCCESS
b4da46
+}
b4da46
+
b4da46
+galera_monitor()
b4da46
+{
b4da46
+    local rc
b4da46
+    local status_loglevel="err"
b4da46
+
b4da46
+    # Set loglevel to info during probe
b4da46
+    if ocf_is_probe; then
b4da46
+        status_loglevel="info"
b4da46
+    fi
b4da46
+ 
b4da46
+    mysql_common_status $status_loglevel
b4da46
+    rc=$?
b4da46
+
b4da46
+    # If status returned an error, return that immediately
b4da46
+    if [ $rc -ne $OCF_SUCCESS ]; then
b4da46
+        return $rc
b4da46
+    fi
b4da46
+
b4da46
+    echo $OCF_RESKEY_wsrep_cluster_address | grep -q $NODENAME
b4da46
+    if [ $? -ne 0 ]; then
b4da46
+        ocf_log err "local node <${NODENAME}> is started, but is not a member of the wsrep_cluster_address <${OCF_RESKEY_wsrep_cluster_address}>"
b4da46
+        return $OCF_ERR_GENERIC
b4da46
+    fi
b4da46
+
b4da46
+    is_readonly
b4da46
+    if [ $? -ne 0 ]; then
b4da46
+        is_primary
b4da46
+        if [ $? -ne 0 ]; then
b4da46
+            ocf_log err "local node <${NODENAME}> is neither in primary mode nor in read_only mode. Unknown state."
b4da46
+            return $OCF_ERR_GENERIC
b4da46
+        fi
b4da46
+
b4da46
+        if ocf_is_probe; then
b4da46
+            # restore master score during probe
b4da46
+            # if we detect this is a master instance
b4da46
+            set_master_score
b4da46
+        fi
b4da46
+        rc=$OCF_RUNNING_MASTER
b4da46
+    else 
b4da46
+        master_exists
b4da46
+        if [ $? -ne 0 ]; then
b4da46
+            detect_first_master
b4da46
+        else
b4da46
+            # a master instance exists and is healthy, promote this
b4da46
+            # local read only instance
b4da46
+            # so it can join the master galera cluster.
b4da46
+            set_master_score
b4da46
+        fi
b4da46
+    fi
b4da46
+    # TODO look at what is done in the wait script
b4da46
+
b4da46
+    return $rc
b4da46
+}
b4da46
+
b4da46
+galera_stop()
b4da46
+{
b4da46
+    local rc
b4da46
+    # make sure the process is stopped
b4da46
+    mysql_common_stop
b4da46
+    rc=$1
b4da46
+
b4da46
+    clear_last_commit
b4da46
+    clear_master_score
b4da46
+    clear_bootstrap_node
b4da46
+    return $rc
b4da46
+}
b4da46
+
b4da46
+galera_validate()
b4da46
+{
b4da46
+    if ! ocf_is_ms; then
b4da46
+        ocf_log err "Galera must be configured as a multistate Master/Slave resource."
b4da46
+        return $OCF_ERR_CONFIGURED
b4da46
+    fi
b4da46
+
b4da46
+    if [ -z "$OCF_RESKEY_wsrep_cluster_address" ]; then
b4da46
+        ocf_log err "Galera must be configured with a wsrep_cluster_address value."
b4da46
+        return $OCF_ERR_CONFIGURED
b4da46
+    fi
b4da46
+
b4da46
+    mysql_common_validate
b4da46
+}
b4da46
+
b4da46
+case "$1" in
b4da46
+  meta-data)    meta_data
b4da46
+        exit $OCF_SUCCESS;;
b4da46
+  usage|help)   usage
b4da46
+        exit $OCF_SUCCESS;;
b4da46
+esac
b4da46
+
b4da46
+galera_validate
b4da46
+rc=$?
b4da46
+LSB_STATUS_STOPPED=3
b4da46
+if [ $rc -ne 0 ]; then
b4da46
+    case "$1" in
b4da46
+        stop) exit $OCF_SUCCESS;;
b4da46
+        monitor) exit $OCF_NOT_RUNNING;;
b4da46
+        status) exit $LSB_STATUS_STOPPED;;
b4da46
+        *) exit $rc;;
b4da46
+    esac
b4da46
+fi
b4da46
+
b4da46
+if [ -z "${OCF_RESKEY_check_passwd}" ]; then
b4da46
+    # This value is automatically sourced from /etc/sysconfig/checkcluster if available
b4da46
+    OCF_RESKEY_check_passwd=${MYSQL_PASSWORD}
b4da46
+fi
b4da46
+if [ -z "${OCF_RESKEY_check_user}" ]; then
b4da46
+    # This value is automatically sourced from /etc/sysconfig/checkcluster if available
b4da46
+    OCF_RESKEY_check_user=${MYSQL_USERNAME}
b4da46
+fi
b4da46
+: ${OCF_RESKEY_check_user="root"}
b4da46
+
b4da46
+MYSQL_OPTIONS_CHECK="-nNE --user=${OCF_RESKEY_check_user}"
b4da46
+if [ -n "${OCF_RESKEY_check_passwd}" ]; then
b4da46
+    MYSQL_OPTIONS_CHECK="$MYSQL_OPTIONS_CHECK --password=${MYSQL_PASSWORD}"
b4da46
+fi
b4da46
+
b4da46
+# What kind of method was invoked?
b4da46
+case "$1" in
b4da46
+  start)    galera_start;;
b4da46
+  stop)     galera_stop;;
b4da46
+  status)   mysql_common_status err;;
b4da46
+  monitor)  galera_monitor;;
b4da46
+  promote)  galera_promote;;
b4da46
+  demote)   galera_demote;;
b4da46
+  notify)   galera_notify;;
b4da46
+  validate-all) exit $OCF_SUCCESS;;
b4da46
+
b4da46
+ *)     usage
b4da46
+        exit $OCF_ERR_UNIMPLEMENTED;;
b4da46
+esac
b4da46
+
b4da46
+# vi:sw=4:ts=4:et:
b4da46
diff --git a/heartbeat/mysql b/heartbeat/mysql
b4da46
index f7eb9f2..41287d0 100755
b4da46
--- a/heartbeat/mysql
b4da46
+++ b/heartbeat/mysql
b4da46
@@ -51,97 +51,7 @@
b4da46
 
b4da46
 : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
b4da46
 . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
b4da46
-
b4da46
-#######################################################################
b4da46
-
b4da46
-# Attempt to detect a default binary
b4da46
-OCF_RESKEY_binary_default=$(which mysqld_safe 2> /dev/null)
b4da46
-if [ "$OCF_RESKEY_binary_default" = "" ]; then
b4da46
-	OCF_RESKEY_binary_default=$(which safe_mysqld 2> /dev/null)
b4da46
-fi
b4da46
-
b4da46
-# Fill in some defaults if no values are specified
b4da46
-HOSTOS=`uname`
b4da46
-if [ "X${HOSTOS}" = "XOpenBSD" ];then
b4da46
-	if [ "$OCF_RESKEY_binary_default" = "" ]; then
b4da46
-		OCF_RESKEY_binary_default="/usr/local/bin/mysqld_safe"
b4da46
-	fi
b4da46
-	OCF_RESKEY_config_default="/etc/my.cnf"
b4da46
-	OCF_RESKEY_datadir_default="/var/mysql"
b4da46
-	OCF_RESKEY_user_default="_mysql"
b4da46
-	OCF_RESKEY_group_default="_mysql"
b4da46
-	OCF_RESKEY_log_default="/var/log/mysqld.log"
b4da46
-	OCF_RESKEY_pid_default="/var/mysql/mysqld.pid"
b4da46
-	OCF_RESKEY_socket_default="/var/run/mysql/mysql.sock"
b4da46
-else
b4da46
-	if [ "$OCF_RESKEY_binary_default" = "" ]; then
b4da46
-		OCF_RESKEY_binary_default="/usr/bin/safe_mysqld"
b4da46
-	fi
b4da46
-	OCF_RESKEY_config_default="/etc/my.cnf"
b4da46
-	OCF_RESKEY_datadir_default="/var/lib/mysql"
b4da46
-	OCF_RESKEY_user_default="mysql"
b4da46
-	OCF_RESKEY_group_default="mysql"
b4da46
-	OCF_RESKEY_log_default="/var/log/mysqld.log"
b4da46
-	OCF_RESKEY_pid_default="/var/run/mysql/mysqld.pid"
b4da46
-	OCF_RESKEY_socket_default="/var/lib/mysql/mysql.sock"
b4da46
-fi
b4da46
-OCF_RESKEY_client_binary_default="mysql"
b4da46
-OCF_RESKEY_test_user_default="root"
b4da46
-OCF_RESKEY_test_table_default="mysql.user"
b4da46
-OCF_RESKEY_test_passwd_default=""
b4da46
-OCF_RESKEY_enable_creation_default=0
b4da46
-OCF_RESKEY_additional_parameters_default=""
b4da46
-OCF_RESKEY_replication_port_default="3306"
b4da46
-OCF_RESKEY_max_slave_lag_default="3600"
b4da46
-OCF_RESKEY_evict_outdated_slaves_default="false"
b4da46
-OCF_RESKEY_reader_attribute_default="readable"
b4da46
-
b4da46
-: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
b4da46
-MYSQL_BINDIR=`dirname ${OCF_RESKEY_binary}`
b4da46
-
b4da46
-: ${OCF_RESKEY_client_binary=${OCF_RESKEY_client_binary_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
b4da46
-: ${OCF_RESKEY_datadir=${OCF_RESKEY_datadir_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
b4da46
-: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_log=${OCF_RESKEY_log_default}}
b4da46
-: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
b4da46
-: ${OCF_RESKEY_socket=${OCF_RESKEY_socket_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_test_user=${OCF_RESKEY_test_user_default}}
b4da46
-: ${OCF_RESKEY_test_table=${OCF_RESKEY_test_table_default}}
b4da46
-: ${OCF_RESKEY_test_passwd=${OCF_RESKEY_test_passwd_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_enable_creation=${OCF_RESKEY_enable_creation_default}}
b4da46
-: ${OCF_RESKEY_additional_parameters=${OCF_RESKEY_additional_parameters_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_replication_user=${OCF_RESKEY_replication_user_default}}
b4da46
-: ${OCF_RESKEY_replication_passwd=${OCF_RESKEY_replication_passwd_default}}
b4da46
-: ${OCF_RESKEY_replication_port=${OCF_RESKEY_replication_port_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_max_slave_lag=${OCF_RESKEY_max_slave_lag_default}}
b4da46
-: ${OCF_RESKEY_evict_outdated_slaves=${OCF_RESKEY_evict_outdated_slaves_default}}
b4da46
-
b4da46
-: ${OCF_RESKEY_reader_attribute=${OCF_RESKEY_reader_attribute_default}}
b4da46
-
b4da46
-#######################################################################
b4da46
-# Convenience variables
b4da46
-
b4da46
-MYSQL=$OCF_RESKEY_client_binary
b4da46
-MYSQL_OPTIONS_LOCAL="-S $OCF_RESKEY_socket --connect_timeout=10"
b4da46
-MYSQL_OPTIONS_REPL="$MYSQL_OPTIONS_LOCAL --user=$OCF_RESKEY_replication_user --password=$OCF_RESKEY_replication_passwd"
b4da46
-MYSQL_OPTIONS_TEST="$MYSQL_OPTIONS_LOCAL --user=$OCF_RESKEY_test_user --password=$OCF_RESKEY_test_passwd"
b4da46
-MYSQL_TOO_MANY_CONN_ERR=1040
b4da46
-
b4da46
-CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot "
b4da46
-NODENAME=$(ocf_local_nodename)
b4da46
-CRM_ATTR="${HA_SBIN_DIR}/crm_attribute -N $NODENAME "
b4da46
-INSTANCE_ATTR_NAME=`echo ${OCF_RESOURCE_INSTANCE}| awk -F : '{print $1}'`
b4da46
-CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name ${INSTANCE_ATTR_NAME}_REPL_INFO -s mysql_replication"
b4da46
-
b4da46
+. ${OCF_FUNCTIONS_DIR}/mysql-common.sh
b4da46
 #######################################################################
b4da46
 
b4da46
 usage() {
b4da46
@@ -794,57 +704,6 @@ get_local_ip() {
b4da46
 
b4da46
 # Functions invoked by resource manager actions
b4da46
 
b4da46
-mysql_validate() {
b4da46
-    check_binary $OCF_RESKEY_binary
b4da46
-    check_binary  $OCF_RESKEY_client_binary
b4da46
-
b4da46
-    if [ ! -f $OCF_RESKEY_config ]; then
b4da46
-        ocf_log err "Config $OCF_RESKEY_config doesn't exist";
b4da46
-        return $OCF_ERR_INSTALLED;
b4da46
-    fi
b4da46
-
b4da46
-    if [ ! -d $OCF_RESKEY_datadir ]; then
b4da46
-        ocf_log err "Datadir $OCF_RESKEY_datadir doesn't exist";
b4da46
-        return $OCF_ERR_INSTALLED;
b4da46
-    fi
b4da46
-
b4da46
-    getent passwd $OCF_RESKEY_user >/dev/null 2>&1
b4da46
-    if [ ! $? -eq 0 ]; then
b4da46
-        ocf_log err "User $OCF_RESKEY_user doesn't exit";
b4da46
-        return $OCF_ERR_INSTALLED;
b4da46
-    fi
b4da46
-
b4da46
-    getent group $OCF_RESKEY_group >/dev/null 2>&1
b4da46
-    if [ ! $? -eq 0 ]; then
b4da46
-        ocf_log err "Group $OCF_RESKEY_group doesn't exist";
b4da46
-        return $OCF_ERR_INSTALLED;
b4da46
-    fi
b4da46
-
b4da46
-    true
b4da46
-}
b4da46
-
b4da46
-mysql_status() {
b4da46
-    if [ ! -e $OCF_RESKEY_pid ]; then
b4da46
-        ocf_log $1 "MySQL is not running"
b4da46
-        return $OCF_NOT_RUNNING;
b4da46
-    fi
b4da46
-
b4da46
-    pid=`cat $OCF_RESKEY_pid`;
b4da46
-    if [ -d /proc -a -d /proc/1 ]; then
b4da46
-        [ "u$pid" != "u" -a -d /proc/$pid ]
b4da46
-    else
b4da46
-        kill -s 0 $pid >/dev/null 2>&1
b4da46
-    fi
b4da46
-
b4da46
-    if [ $? -eq 0 ]; then
b4da46
-        return $OCF_SUCCESS;
b4da46
-    else
b4da46
-        ocf_log $1 "MySQL not running: removing old PID file"
b4da46
-        rm -f $OCF_RESKEY_pid
b4da46
-        return $OCF_NOT_RUNNING;
b4da46
-    fi
b4da46
-}
b4da46
-
b4da46
 mysql_monitor() {
b4da46
     local rc
b4da46
     local status_loglevel="err"
b4da46
@@ -854,7 +713,7 @@ mysql_monitor() {
b4da46
         status_loglevel="info"
b4da46
     fi
b4da46
  
b4da46
-    mysql_status $status_loglevel
b4da46
+    mysql_common_status $status_loglevel
b4da46
 
b4da46
     rc=$?
b4da46
 
b4da46
@@ -865,7 +724,6 @@ mysql_monitor() {
b4da46
         return $rc
b4da46
     fi
b4da46
 
b4da46
-
b4da46
     if [ $OCF_CHECK_LEVEL -gt 0 -a -n "$OCF_RESKEY_test_table" ]; then
b4da46
         # Check if this instance is configured as a slave, and if so
b4da46
         # check slave status
b4da46
@@ -894,58 +752,20 @@ mysql_monitor() {
b4da46
 }
b4da46
 
b4da46
 mysql_start() {
b4da46
-    local rc pid
b4da46
+    local rc
b4da46
 
b4da46
     if ocf_is_ms; then
b4da46
         # Initialize the ReaderVIP attribute, monitor will enable it
b4da46
         set_reader_attr 0
b4da46
     fi
b4da46
 
b4da46
-    mysql_status info
b4da46
+    mysql_common_status info
b4da46
     if [ $? = $OCF_SUCCESS ]; then
b4da46
         ocf_log info "MySQL already running"
b4da46
         return $OCF_SUCCESS
b4da46
     fi
b4da46
 
b4da46
-    touch $OCF_RESKEY_log
b4da46
-    chown $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_log
b4da46
-    chmod 0640 $OCF_RESKEY_log
b4da46
-    [ -x /sbin/restorecon ] && /sbin/restorecon $OCF_RESKEY_log
b4da46
-
b4da46
-    if ocf_is_true "$OCF_RESKEY_enable_creation" && [ ! -d $OCF_RESKEY_datadir/mysql ] ; then
b4da46
-        ocf_log info "Initializing MySQL database: "
b4da46
-        $MYSQL_BINDIR/mysql_install_db --datadir=$OCF_RESKEY_datadir
b4da46
-        rc=$?
b4da46
-        if [ $rc -ne 0 ] ; then
b4da46
-            ocf_log err "Initialization failed: $rc";
b4da46
-            exit $OCF_ERR_GENERIC
b4da46
-        fi
b4da46
-        chown -R $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_datadir
b4da46
-    fi
b4da46
-
b4da46
-    pid_dir=`dirname $OCF_RESKEY_pid`
b4da46
-    if [ ! -d $pid_dir ] ; then
b4da46
-        ocf_log info "Creating PID dir: $pid_dir"
b4da46
-        mkdir -p $pid_dir
b4da46
-        chown $OCF_RESKEY_user:$OCF_RESKEY_group $pid_dir
b4da46
-    fi
b4da46
-
b4da46
-    socket_dir=`dirname $OCF_RESKEY_socket`
b4da46
-    if [ ! -d $socket_dir ] ; then
b4da46
-        ocf_log info "Creating socket dir: $socket_dir"
b4da46
-        mkdir -p $socket_dir
b4da46
-        chown $OCF_RESKEY_user:$OCF_RESKEY_group $socket_dir
b4da46
-    fi
b4da46
-
b4da46
-    # Regardless of whether we just created the directory or it
b4da46
-    # already existed, check whether it is writable by the configured
b4da46
-    # user
b4da46
-    for dir in $pid_dir $socket_dir; do
b4da46
-        if ! su -s /bin/sh - $OCF_RESKEY_user -c "test -w $dir"; then
b4da46
-            ocf_log err "Directory $dir is not writable by $OCF_RESKEY_user"
b4da46
-            exit $OCF_ERR_PERM;
b4da46
-        fi
b4da46
-    done
b4da46
+    mysql_common_prepare_dirs
b4da46
 
b4da46
     # Uncomment to perform permission clensing
b4da46
     # - not convinced this should be enabled by default
b4da46
@@ -958,34 +778,11 @@ mysql_start() {
b4da46
         mysql_extra_params="--skip-slave-start"
b4da46
     fi
b4da46
 
b4da46
-    ${OCF_RESKEY_binary} --defaults-file=$OCF_RESKEY_config \
b4da46
-    --pid-file=$OCF_RESKEY_pid \
b4da46
-    --socket=$OCF_RESKEY_socket \
b4da46
-    --datadir=$OCF_RESKEY_datadir \
b4da46
-    --log-error=$OCF_RESKEY_log \
b4da46
-    --user=$OCF_RESKEY_user $OCF_RESKEY_additional_parameters \
b4da46
-    $mysql_extra_params >/dev/null 2>&1 &
b4da46
-    pid=$!
b4da46
-
b4da46
-    # Spin waiting for the server to come up.
b4da46
-    # Let the CRM/LRM time us out if required.
b4da46
-    start_wait=1
b4da46
-    while [ $start_wait = 1 ]; do
b4da46
-        if ! ps $pid > /dev/null 2>&1; then
b4da46
-            wait $pid
b4da46
-            ocf_log err "MySQL server failed to start (rc=$?), please check your installation"
b4da46
-            return $OCF_ERR_GENERIC
b4da46
-        fi
b4da46
-        mysql_status info
b4da46
-        rc=$?
b4da46
-        if [ $rc = $OCF_SUCCESS ]; then
b4da46
-            start_wait=0
b4da46
-        elif [ $rc != $OCF_NOT_RUNNING ]; then
b4da46
-            ocf_log info "MySQL start failed: $rc"
b4da46
-            return $rc
b4da46
-        fi
b4da46
-        sleep 2
b4da46
-    done
b4da46
+    mysql_common_start $mysql_extra_params
b4da46
+    rc=$?
b4da46
+    if [ $rc != $OCF_SUCCESS ]; then
b4da46
+        return $rc
b4da46
+    fi
b4da46
 
b4da46
     if ocf_is_ms; then
b4da46
         # We're configured as a stateful resource. We must start as
b4da46
@@ -1035,7 +832,6 @@ mysql_start() {
b4da46
 }
b4da46
 
b4da46
 mysql_stop() {
b4da46
-
b4da46
     if ocf_is_ms; then
b4da46
         # clear preference for becoming master
b4da46
         $CRM_MASTER -D
b4da46
@@ -1044,52 +840,13 @@ mysql_stop() {
b4da46
         set_reader_attr 0
b4da46
     fi
b4da46
 
b4da46
-    if [ ! -f $OCF_RESKEY_pid ]; then
b4da46
-        ocf_log info "MySQL is not running"
b4da46
-        return $OCF_SUCCESS
b4da46
-    fi
b4da46
-
b4da46
-    pid=`cat $OCF_RESKEY_pid 2> /dev/null `
b4da46
-    /bin/kill $pid > /dev/null
b4da46
-    rc=$?
b4da46
-    if [ $rc != 0 ]; then
b4da46
-        ocf_log err "MySQL couldn't be stopped"
b4da46
-        return $OCF_ERR_GENERIC
b4da46
-    fi
b4da46
-    # stop waiting
b4da46
-    shutdown_timeout=15
b4da46
-    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
b4da46
-        shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
b4da46
-    fi
b4da46
-    count=0
b4da46
-    while [ $count -lt $shutdown_timeout ]
b4da46
-    do
b4da46
-        mysql_status info
b4da46
-        rc=$?
b4da46
-        if [ $rc = $OCF_NOT_RUNNING ]; then
b4da46
-            break
b4da46
-        fi
b4da46
-        count=`expr $count + 1`
b4da46
-        sleep 1
b4da46
-        ocf_log debug "MySQL still hasn't stopped yet. Waiting..."
b4da46
-    done
b4da46
-
b4da46
-    mysql_status info
b4da46
-    if [ $? != $OCF_NOT_RUNNING ]; then
b4da46
-        ocf_log info "MySQL failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL..."
b4da46
-        /bin/kill -KILL $pid > /dev/null
b4da46
-    fi
b4da46
-
b4da46
-    ocf_log info "MySQL stopped";
b4da46
-    rm -f /var/lock/subsys/mysqld
b4da46
-    rm -f $OCF_RESKEY_socket
b4da46
-    return $OCF_SUCCESS
b4da46
+    mysql_common_stop
b4da46
 }
b4da46
 
b4da46
 mysql_promote() {
b4da46
     local master_info
b4da46
 
b4da46
-    if ( ! mysql_status err ); then
b4da46
+    if ( ! mysql_common_status err ); then
b4da46
         return $OCF_NOT_RUNNING
b4da46
     fi
b4da46
     ocf_run $MYSQL $MYSQL_OPTIONS_REPL \
b4da46
@@ -1115,7 +872,7 @@ mysql_promote() {
b4da46
 }
b4da46
 
b4da46
 mysql_demote() {
b4da46
-    if ! mysql_status err; then
b4da46
+    if ! mysql_common_status err; then
b4da46
         return $OCF_NOT_RUNNING
b4da46
     fi
b4da46
 
b4da46
@@ -1244,7 +1001,7 @@ case "$1" in
b4da46
         exit $OCF_SUCCESS;;
b4da46
 esac
b4da46
 
b4da46
-mysql_validate
b4da46
+mysql_common_validate
b4da46
 rc=$?
b4da46
 LSB_STATUS_STOPPED=3
b4da46
 if [ $rc -ne 0 ]; then
b4da46
@@ -1260,7 +1017,7 @@ fi
b4da46
 case "$1" in
b4da46
   start)    mysql_start;;
b4da46
   stop)     mysql_stop;;
b4da46
-  status)   mysql_status err;;
b4da46
+  status)   mysql_common_status err;;
b4da46
   monitor)  mysql_monitor;;
b4da46
   promote)  mysql_promote;;
b4da46
   demote)   mysql_demote;;
b4da46
diff --git a/heartbeat/mysql-common.sh b/heartbeat/mysql-common.sh
b4da46
new file mode 100644
b4da46
index 0000000..5b6a991
b4da46
--- /dev/null
b4da46
+++ b/heartbeat/mysql-common.sh
b4da46
@@ -0,0 +1,279 @@
b4da46
+#!/bin/sh
b4da46
+
b4da46
+#######################################################################
b4da46
+
b4da46
+# Attempt to detect a default binary
b4da46
+OCF_RESKEY_binary_default=$(which mysqld_safe 2> /dev/null)
b4da46
+if [ "$OCF_RESKEY_binary_default" = "" ]; then
b4da46
+	OCF_RESKEY_binary_default=$(which safe_mysqld 2> /dev/null)
b4da46
+fi
b4da46
+
b4da46
+# Fill in some defaults if no values are specified
b4da46
+HOSTOS=`uname`
b4da46
+if [ "X${HOSTOS}" = "XOpenBSD" ];then
b4da46
+	if [ "$OCF_RESKEY_binary_default" = "" ]; then
b4da46
+		OCF_RESKEY_binary_default="/usr/local/bin/mysqld_safe"
b4da46
+	fi
b4da46
+	OCF_RESKEY_config_default="/etc/my.cnf"
b4da46
+	OCF_RESKEY_datadir_default="/var/mysql"
b4da46
+	OCF_RESKEY_user_default="_mysql"
b4da46
+	OCF_RESKEY_group_default="_mysql"
b4da46
+	OCF_RESKEY_log_default="/var/log/mysqld.log"
b4da46
+	OCF_RESKEY_pid_default="/var/mysql/mysqld.pid"
b4da46
+	OCF_RESKEY_socket_default="/var/run/mysql/mysql.sock"
b4da46
+else
b4da46
+	if [ "$OCF_RESKEY_binary_default" = "" ]; then
b4da46
+		OCF_RESKEY_binary_default="/usr/bin/safe_mysqld"
b4da46
+	fi
b4da46
+	OCF_RESKEY_config_default="/etc/my.cnf"
b4da46
+	OCF_RESKEY_datadir_default="/var/lib/mysql"
b4da46
+	OCF_RESKEY_user_default="mysql"
b4da46
+	OCF_RESKEY_group_default="mysql"
b4da46
+	OCF_RESKEY_log_default="/var/log/mysqld.log"
b4da46
+	OCF_RESKEY_pid_default="/var/run/mysql/mysqld.pid"
b4da46
+	OCF_RESKEY_socket_default="/var/lib/mysql/mysql.sock"
b4da46
+fi
b4da46
+OCF_RESKEY_client_binary_default="mysql"
b4da46
+OCF_RESKEY_test_user_default="root"
b4da46
+OCF_RESKEY_test_table_default="mysql.user"
b4da46
+OCF_RESKEY_test_passwd_default=""
b4da46
+OCF_RESKEY_enable_creation_default=0
b4da46
+OCF_RESKEY_additional_parameters_default=""
b4da46
+OCF_RESKEY_replication_port_default="3306"
b4da46
+OCF_RESKEY_max_slave_lag_default="3600"
b4da46
+OCF_RESKEY_evict_outdated_slaves_default="false"
b4da46
+OCF_RESKEY_reader_attribute_default="readable"
b4da46
+
b4da46
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
b4da46
+MYSQL_BINDIR=`dirname ${OCF_RESKEY_binary}`
b4da46
+
b4da46
+: ${OCF_RESKEY_client_binary=${OCF_RESKEY_client_binary_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
b4da46
+: ${OCF_RESKEY_datadir=${OCF_RESKEY_datadir_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
b4da46
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_log=${OCF_RESKEY_log_default}}
b4da46
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
b4da46
+: ${OCF_RESKEY_socket=${OCF_RESKEY_socket_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_test_user=${OCF_RESKEY_test_user_default}}
b4da46
+: ${OCF_RESKEY_test_table=${OCF_RESKEY_test_table_default}}
b4da46
+: ${OCF_RESKEY_test_passwd=${OCF_RESKEY_test_passwd_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_enable_creation=${OCF_RESKEY_enable_creation_default}}
b4da46
+: ${OCF_RESKEY_additional_parameters=${OCF_RESKEY_additional_parameters_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_replication_user=${OCF_RESKEY_replication_user_default}}
b4da46
+: ${OCF_RESKEY_replication_passwd=${OCF_RESKEY_replication_passwd_default}}
b4da46
+: ${OCF_RESKEY_replication_port=${OCF_RESKEY_replication_port_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_max_slave_lag=${OCF_RESKEY_max_slave_lag_default}}
b4da46
+: ${OCF_RESKEY_evict_outdated_slaves=${OCF_RESKEY_evict_outdated_slaves_default}}
b4da46
+
b4da46
+: ${OCF_RESKEY_reader_attribute=${OCF_RESKEY_reader_attribute_default}}
b4da46
+
b4da46
+#######################################################################
b4da46
+# Convenience variables
b4da46
+
b4da46
+MYSQL=$OCF_RESKEY_client_binary
b4da46
+MYSQL_OPTIONS_LOCAL="-S $OCF_RESKEY_socket --connect_timeout=10"
b4da46
+MYSQL_OPTIONS_REPL="$MYSQL_OPTIONS_LOCAL --user=$OCF_RESKEY_replication_user --password=$OCF_RESKEY_replication_passwd"
b4da46
+MYSQL_OPTIONS_TEST="$MYSQL_OPTIONS_LOCAL --user=$OCF_RESKEY_test_user --password=$OCF_RESKEY_test_passwd"
b4da46
+MYSQL_TOO_MANY_CONN_ERR=1040
b4da46
+
b4da46
+CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot "
b4da46
+NODENAME=$(ocf_local_nodename)
b4da46
+CRM_ATTR="${HA_SBIN_DIR}/crm_attribute -N $NODENAME "
b4da46
+INSTANCE_ATTR_NAME=`echo ${OCF_RESOURCE_INSTANCE}| awk -F : '{print $1}'`
b4da46
+CRM_ATTR_REPL_INFO="${HA_SBIN_DIR}/crm_attribute --type crm_config --name ${INSTANCE_ATTR_NAME}_REPL_INFO -s mysql_replication"
b4da46
+
b4da46
+#######################################################################
b4da46
+
b4da46
+mysql_common_validate()
b4da46
+{
b4da46
+    check_binary $OCF_RESKEY_binary
b4da46
+    check_binary  $OCF_RESKEY_client_binary
b4da46
+
b4da46
+    if [ ! -f $OCF_RESKEY_config ]; then
b4da46
+        ocf_log err "Config $OCF_RESKEY_config doesn't exist";
b4da46
+        return $OCF_ERR_INSTALLED;
b4da46
+    fi
b4da46
+
b4da46
+    if [ ! -d $OCF_RESKEY_datadir ]; then
b4da46
+        ocf_log err "Datadir $OCF_RESKEY_datadir doesn't exist";
b4da46
+        return $OCF_ERR_INSTALLED;
b4da46
+    fi
b4da46
+
b4da46
+    getent passwd $OCF_RESKEY_user >/dev/null 2>&1
b4da46
+    if [ ! $? -eq 0 ]; then
b4da46
+        ocf_log err "User $OCF_RESKEY_user doesn't exit";
b4da46
+        return $OCF_ERR_INSTALLED;
b4da46
+    fi
b4da46
+
b4da46
+    getent group $OCF_RESKEY_group >/dev/null 2>&1
b4da46
+    if [ ! $? -eq 0 ]; then
b4da46
+        ocf_log err "Group $OCF_RESKEY_group doesn't exist";
b4da46
+        return $OCF_ERR_INSTALLED;
b4da46
+    fi
b4da46
+
b4da46
+    return $OCF_SUCCESS
b4da46
+}
b4da46
+
b4da46
+mysql_common_status() {
b4da46
+    local loglevel=$1
b4da46
+    local pid=$2
b4da46
+    if [ -z "$pid" ]; then
b4da46
+        if [ ! -e $OCF_RESKEY_pid ]; then
b4da46
+            ocf_log $loglevel "MySQL is not running"
b4da46
+            return $OCF_NOT_RUNNING;
b4da46
+        fi
b4da46
+
b4da46
+        pid=`cat $OCF_RESKEY_pid`;
b4da46
+    fi
b4da46
+    if [ -d /proc -a -d /proc/1 ]; then
b4da46
+        [ "u$pid" != "u" -a -d /proc/$pid ]
b4da46
+    else
b4da46
+        kill -s 0 $pid >/dev/null 2>&1
b4da46
+    fi
b4da46
+
b4da46
+    if [ $? -eq 0 ]; then
b4da46
+        return $OCF_SUCCESS;
b4da46
+    else
b4da46
+        ocf_log $loglevel "MySQL not running: removing old PID file"
b4da46
+        rm -f $OCF_RESKEY_pid
b4da46
+        return $OCF_NOT_RUNNING;
b4da46
+    fi
b4da46
+}
b4da46
+
b4da46
+mysql_common_prepare_dirs()
b4da46
+{
b4da46
+    local rc
b4da46
+
b4da46
+    touch $OCF_RESKEY_log
b4da46
+    chown $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_log
b4da46
+    chmod 0640 $OCF_RESKEY_log
b4da46
+    [ -x /sbin/restorecon ] && /sbin/restorecon $OCF_RESKEY_log
b4da46
+
b4da46
+    if ocf_is_true "$OCF_RESKEY_enable_creation" && [ ! -d $OCF_RESKEY_datadir/mysql ] ; then
b4da46
+        ocf_log info "Initializing MySQL database: "
b4da46
+        $MYSQL_BINDIR/mysql_install_db --datadir=$OCF_RESKEY_datadir
b4da46
+        rc=$?
b4da46
+        if [ $rc -ne 0 ] ; then
b4da46
+            ocf_log err "Initialization failed: $rc";
b4da46
+            exit $OCF_ERR_GENERIC
b4da46
+        fi
b4da46
+        chown -R $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_datadir
b4da46
+    fi
b4da46
+
b4da46
+    pid_dir=`dirname $OCF_RESKEY_pid`
b4da46
+    if [ ! -d $pid_dir ] ; then
b4da46
+        ocf_log info "Creating PID dir: $pid_dir"
b4da46
+        mkdir -p $pid_dir
b4da46
+        chown $OCF_RESKEY_user:$OCF_RESKEY_group $pid_dir
b4da46
+    fi
b4da46
+
b4da46
+    socket_dir=`dirname $OCF_RESKEY_socket`
b4da46
+    if [ ! -d $socket_dir ] ; then
b4da46
+        ocf_log info "Creating socket dir: $socket_dir"
b4da46
+        mkdir -p $socket_dir
b4da46
+        chown $OCF_RESKEY_user:$OCF_RESKEY_group $socket_dir
b4da46
+    fi
b4da46
+
b4da46
+    # Regardless of whether we just created the directory or it
b4da46
+    # already existed, check whether it is writable by the configured
b4da46
+    # user
b4da46
+    for dir in $pid_dir $socket_dir; do
b4da46
+        if ! su -s /bin/sh - $OCF_RESKEY_user -c "test -w $dir"; then
b4da46
+            ocf_log err "Directory $dir is not writable by $OCF_RESKEY_user"
b4da46
+            exit $OCF_ERR_PERM;
b4da46
+        fi
b4da46
+    done
b4da46
+}
b4da46
+
b4da46
+mysql_common_start()
b4da46
+{
b4da46
+    local mysql_extra_params="$1"
b4da46
+    local pid
b4da46
+
b4da46
+    ${OCF_RESKEY_binary} --defaults-file=$OCF_RESKEY_config \
b4da46
+    --pid-file=$OCF_RESKEY_pid \
b4da46
+    --socket=$OCF_RESKEY_socket \
b4da46
+    --datadir=$OCF_RESKEY_datadir \
b4da46
+    --log-error=$OCF_RESKEY_log \
b4da46
+    --user=$OCF_RESKEY_user $OCF_RESKEY_additional_parameters \
b4da46
+    $mysql_extra_params >/dev/null 2>&1 &
b4da46
+    pid=$!
b4da46
+
b4da46
+    # Spin waiting for the server to come up.
b4da46
+    # Let the CRM/LRM time us out if required.
b4da46
+    start_wait=1
b4da46
+    while [ $start_wait = 1 ]; do
b4da46
+        if ! ps $pid > /dev/null 2>&1; then
b4da46
+            wait $pid
b4da46
+            ocf_log err "MySQL server failed to start (pid=$pid) (rc=$?), please check your installation"
b4da46
+            return $OCF_ERR_GENERIC
b4da46
+        fi
b4da46
+        mysql_common_status info
b4da46
+        rc=$?
b4da46
+        if [ $rc = $OCF_SUCCESS ]; then
b4da46
+            start_wait=0
b4da46
+        elif [ $rc != $OCF_NOT_RUNNING ]; then
b4da46
+            ocf_log info "MySQL start failed: $rc"
b4da46
+            return $rc
b4da46
+        fi
b4da46
+        sleep 2
b4da46
+    done
b4da46
+
b4da46
+    return $OCF_SUCCESS
b4da46
+}
b4da46
+
b4da46
+mysql_common_stop()
b4da46
+{
b4da46
+    local pid
b4da46
+    local rc
b4da46
+
b4da46
+    if [ ! -f $OCF_RESKEY_pid ]; then
b4da46
+        ocf_log info "MySQL is not running"
b4da46
+        return $OCF_SUCCESS
b4da46
+    fi
b4da46
+
b4da46
+    pid=`cat $OCF_RESKEY_pid 2> /dev/null `
b4da46
+    /bin/kill $pid > /dev/null
b4da46
+    rc=$?
b4da46
+    if [ $rc != 0 ]; then
b4da46
+        ocf_log err "MySQL couldn't be stopped"
b4da46
+        return $OCF_ERR_GENERIC
b4da46
+    fi
b4da46
+    # stop waiting
b4da46
+    shutdown_timeout=15
b4da46
+    if [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
b4da46
+        shutdown_timeout=$((($OCF_RESKEY_CRM_meta_timeout/1000)-5))
b4da46
+    fi
b4da46
+    count=0
b4da46
+    while [ $count -lt $shutdown_timeout ]
b4da46
+    do
b4da46
+        mysql_common_status info $pid
b4da46
+        rc=$?
b4da46
+        if [ $rc = $OCF_NOT_RUNNING ]; then
b4da46
+            break
b4da46
+        fi
b4da46
+        count=`expr $count + 1`
b4da46
+        sleep 1
b4da46
+        ocf_log debug "MySQL still hasn't stopped yet. Waiting..."
b4da46
+    done
b4da46
+
b4da46
+    mysql_common_status info $pid
b4da46
+    if [ $? != $OCF_NOT_RUNNING ]; then
b4da46
+        ocf_log info "MySQL failed to stop after ${shutdown_timeout}s using SIGTERM. Trying SIGKILL..."
b4da46
+        /bin/kill -KILL $pid > /dev/null
b4da46
+    fi
b4da46
+
b4da46
+    ocf_log info "MySQL stopped";
b4da46
+    rm -f /var/lock/subsys/mysqld
b4da46
+    rm -f $OCF_RESKEY_socket
b4da46
+    return $OCF_SUCCESS
b4da46
+
b4da46
+}
b4da46
diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in
b4da46
index 8820961..254da57 100644
b4da46
--- a/heartbeat/ocf-shellfuncs.in
b4da46
+++ b/heartbeat/ocf-shellfuncs.in
b4da46
@@ -518,6 +518,7 @@ ocf_local_nodename() {
b4da46
 	which pacemakerd > /dev/null 2>&1
b4da46
 	if [ $? -eq 0 ]; then
b4da46
 		local version=$(pacemakerd -$ | grep "Pacemaker .*" | awk '{ print $2 }')
b4da46
+		version=$(echo $version | awk -F- '{ print $1 }')
b4da46
 		ocf_version_cmp "$version" "1.1.8"
b4da46
 		if [ $? -eq 2 ]; then
b4da46
 			which crm_node > /dev/null 2>&1
b4da46
-- 
b4da46
1.8.4.2
b4da46