Little tweaks to redis RA #32

Closed
wants to merge 17 commits into
from
View
10 heartbeat/IPaddr2
@@ -417,8 +417,16 @@ delete_interface () {
netmask="$3"
CMD="$IP2UTIL -f inet addr delete $ipaddr/$netmask dev $iface"
+ ocf_run $CMD
- ocf_run $CMD || return $OCF_ERR_GENERIC
+ if [ $? -ne 0 ]; then
+ CMD="$IP2UTIL -f inet addr show dev $iface | grep '$ipaddr\/$netmask'"
+ ocf_run $CMD
+
+ if [ $? -eq 0 ]; then
+ return $OCF_ERR_GENERIC
+ fi
+ fi
if ocf_is_true $OCF_RESKEY_flush_routes; then
ocf_run $IP2UTIL route flush cache
View
271 heartbeat/IPv6addr2
@@ -0,0 +1,271 @@
+#!/bin/bash
+#
+# OCF Resource Agent compliant resource script.
+# Arturo Borrero <aborrero@cica.es> <cer.inet@gmail.com> || October 2011
+#
+# Based on the anything RA.
+#
+# GPLv3 Licensed. You can read the license in
+# http://www.gnu.org/licenses/gpl-3.0.html
+#
+# Use this RA if you want an IPv6 address in
+# the main loopback interface (for example usign LVS for loadbalancing)
+#
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs
+
+# Custom vars:
+IFCONFIG_BIN="/sbin/ifconfig"
+GREP_BIN="grep"
+SED_BIN="sed"
+process=$OCF_RESOURCE_INSTANCE
+ipv6addr=$OCF_RESKEY_ipv6addr
+cidr_netmask=$OCF_RESKEY_cidr_netmask
+IFACE=$OCF_RESKEY_nic
+
+ipv6addr=$(echo "$ipv6addr" | $SED_BIN 's/:0*/:/g')
+
+validate_ipv6(){
+ ocf_log debug "Validating IPv6 addr: [\"$1\"]."
+
+ echo "$1" | $GREP_BIN -E "^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}))|:)))(%.+)?\s*$" > /dev/null
+ if [ $? -eq 0 ]
+ then
+ ocf_log debug "IPv6 addr: [\"$1\"] is valid."
+ return 1
+ fi
+ # the ipv6 is invalid
+ ocf_log err "IPv6 addr: [\"$1\"] is not valid."
+ return 0
+}
+validate_cidr(){
+ ocf_log debug "Validating cidr: \"$1\"."
+
+ if [ $1 -lt 129 ]
+ then
+ if [ $1 -gt 0 ]
+ then
+ # the cidr is valid
+ ocf_log debug "Cidr: \"$1\" is valid."
+ return 1
+ fi
+ fi
+ ocf_log err "Cidr: \"$1\" is not valid."
+ return 0
+}
+
+iface_has_ipv6()
+{
+ ocf_log debug "Checking if iface \"$IFACE\" has the ipv6 [\"$ipv6addr\"]."
+ if [ ! -z $1 ]
+ then
+ $IFCONFIG_BIN $IFACE | $GREP_BIN $1 2> /dev/null > /dev/null
+ if [ $? -eq 0 ]
+ then
+ # the iface has the IPv6
+ ocf_log debug "The iface \"$IFACE\" has the ipv6 [\"$ipv6addr\"]."
+ return 1
+ fi
+ ocf_log debug "The iface \"$IFACE\" does not have the ipv6 [\"$ipv6addr\"]."
+ fi
+ return 0
+}
+
+IPv6addr2_status() {
+ iface_has_ipv6 $ipv6addr
+ if [ $? -eq 1 ]
+ then
+ return $OCF_RUNNING
+ else
+ return $OCF_NOT_RUNNING
+ fi
+}
+
+IPv6addr2_start() {
+ if ! IPv6addr2_status
+ then
+ # First, validate the input parameteres, ipv6addr and cidr_netmaks
+ validate_ipv6 $ipv6addr
+ if [ $? -ne 1 ]
+ then
+ ocf_log err "$process: The ipv6 addr: \"$ipv6addr\" is not a valid one."
+ return $OCF_ERR_GENERIC
+ fi
+ validate_cidr $cidr_netmask
+ if [ $? -ne 1 ]
+ then
+ ocf_log err "$process: The cidr netmask \"$cidr_netmask\" is not valid."
+ return $OCF_ERR_GENERIC
+ fi
+
+
+ # Before assign the ip, check if we already have that ip
+ iface_has_ipv6 $ipv6addr
+ if [ $? -ne 1 ]
+ then
+ ocf_run $IFCONFIG_BIN $IFACE add $ipv6addr/$cidr_netmask
+ fi
+
+ # Check what happened here.
+ if IPv6addr2_status
+ then
+ ocf_log debug "$process: Started successfully."
+ return $OCF_SUCCESS
+ else
+ ocf_log err "$process: Could not be started: ipv6addr[\"$ipv6addr\"] cidr_netmask[\"$cidr_netmask\"] all_args[\"$*\"]."
+ return $OCF_ERR_GENERIC
+ fi
+ else
+ # If already running, consider start successful
+ ocf_log debug "$process: is already running"
+ return $OCF_SUCCESS
+ fi
+}
+
+IPv6addr2_stop() {
+
+ ocf_log debug "$process: Running STOP function."
+
+ if [ -n "$OCF_RESKEY_stop_timeout" ]
+ then
+ stop_timeout=$OCF_RESKEY_stop_timeout
+ elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
+ # Allow 2/3 of the action timeout for the orderly shutdown
+ # (The origin unit is ms, hence the conversion)
+ stop_timeout=$((OCF_RESKEY_CRM_meta_timeout/1500))
+ else
+ stop_timeout=10
+ fi
+ if IPv6addr2_status
+ then
+ ocf_run $IFCONFIG_BIN $IFACE del $ipv6addr/$cidr_netmask
+ i=0
+ while [ $i -lt $stop_timeout ]
+ do
+ if ! IPv6addr2_status
+ then
+ return $OCF_SUCCESS
+ fi
+ sleep 1
+ i=`expr $i + 1`
+ done
+ ocf_log warn "Stop failed. Trying again."
+ ocf_run $IFCONFIG_BIN $IFACE del $ipv6addr
+ if ! IPv6addr2_status
+ then
+ ocf_log warn "Stop success."
+ return $OCF_SUCCESS
+ else
+ ocf_log err "Failed to stop."
+ return $OCF_ERR_GENERIC
+ fi
+ else
+ return $OCF_SUCCESS
+ fi
+}
+
+IPv6addr2_monitor() {
+ IPv6addr2_status
+ ret=$?
+ if [ $ret -eq $OCF_SUCCESS ]
+ then
+ if [ -n "$OCF_RESKEY_monitor_hook" ]; then
+ eval "$OCF_RESKEY_monitor_hook"
+ if [ $? -ne $OCF_SUCCESS ]; then
+ return ${OCF_ERR_GENERIC}
+ fi
+ return $OCF_SUCCESS
+ else
+ true
+ fi
+ else
+ return $ret
+ fi
+}
+
+
+IPv6addr2_validate() {
+
+ ocf_log debug "IPv6addr2 validating: args:[\"$*\"]"
+
+ if [ -x $IFCONFIG_BIN ]
+ then
+ ocf_log debug "Binary \"$IFCONFIG_BIN\" exist and is executable."
+ return $OCF_SUCCESS
+ else
+ ocf_log err "Binary \"$IFCONFIG_BIN\" does not exist or isn't executable."
+ return $OCF_ERR_INSTALLED
+ fi
+ ocf_log err "Error while validating."
+ return $OCF_ERR_GENERIC
+}
+
+IPv6addr2_meta(){
+cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="IPv6addr2">
+<version>0.1</version>
+<longdesc lang="en">
+OCF RA to manage IPv6addr on loopback interface Linux
+</longdesc>
+<shortdesc lang="en">IPv6 addr on loopback linux</shortdesc>
+
+<parameters>
+<parameter name="ipv6addr" required="1">
+<longdesc lang="en">
+The ipv6 addr to asign to the loopback interface.
+</longdesc>
+<shortdesc lang="en">Ipv6 addr to the loopback interface.</shortdesc>
+<content type="string" default=""/>
+</parameter>
+<parameter name="cidr_netmask" required="1">
+<longdesc lang="en">
+The cidr netmask of the ipv6 addr.
+</longdesc>
+<shortdesc lang="en">netmask of the ipv6 addr.</shortdesc>
+<content type="string" default="128"/>
+</parameter>
+<parameter name="nic" required="1">
+<longdesc lang="en">
+iface
+</longdesc>
+<shortdesc lang="en">IFACE</shortdesc>
+<content type="string" />
+</parameter>
+</parameters>
+<actions>
+<action name="start" timeout="20s" />
+<action name="stop" timeout="20s" />
+<action name="monitor" depth="0" timeout="20s" interval="10" />
+<action name="meta-data" timeout="5" />
+<action name="validate-all" timeout="5" />
+</actions>
+</resource-agent>
+END
+exit 0
+}
+
+case "$1" in
+ meta-data|metadata|meta_data|meta)
+ IPv6addr2_meta
+ ;;
+ start)
+ IPv6addr2_start
+ ;;
+ stop)
+ IPv6addr2_stop
+ ;;
+ monitor)
+ IPv6addr2_monitor
+ ;;
+ validate-all)
+ IPv6addr2_validate
+ ;;
+ *)
+ ocf_log err "$0 was called with unsupported arguments:"
+ exit $OCF_ERR_UNIMPLEMENTED
+ ;;
+esac
View
669 heartbeat/redis
@@ -0,0 +1,669 @@
+#!/bin/bash
+#
+#
+# redis
+#
+# Description: Manages redis as Linux-HA resource
+#
+# Authors: Alan Robertson,
+# Jakub Janczak,
+# Andrew Beekhof,
+# Sebastian Reitenbach,
+# Narayan Newton,
+# Marian Marinov,
+# Florian Haas: MySQL script
+# Martin Walter: rewrite as redis
+# Jose Junior: tweaks to the redis version
+# Michael Braun: properly bringup as slave (even if no master has already been promoted)
+#
+# Support: linux-ha@lists.linux-ha.org
+# License: GNU General Public License (GPL)
+#
+# (c) 2002-2005 International Business Machines, Inc.
+# 2005-2010 Linux-HA contributors
+#
+# An example usage in /etc/ha.d/haresources:
+# node1 10.0.0.170 redis
+#
+# See usage() function below for more details...
+#
+# OCF instance parameters:
+# OCF_RESKEY_binary
+# OCF_RESKEY_client_binary
+# OCF_RESKEY_aof_check_binary
+# OCF_RESKEY_config
+# OCF_RESKEY_user
+# OCF_RESKEY_group
+# OCF_RESKEY_log
+# OCF_RESKEY_pid
+# OCF_RESKEY_tmp
+#######################################################################
+# Initialization:
+
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
+
+#######################################################################
+PATH=$PATH:/usr/local/bin:/usr/local/sbin
+
+# Fill in some defaults if no values are specified
+OCF_RESKEY_binary_default=redis-server
+OCF_RESKEY_client_binary_default=redis-cli
+OCF_RESKEY_aof_check_binary_default=redis-check-aof
+OCF_RESKEY_config_default=/etc/redis/redis.conf
+OCF_RESKEY_user_default=redis
+OCF_RESKEY_group_default=redis
+OCF_RESKEY_log_default=/var/log/redis/redis-server.log
+OCF_RESKEY_pid_default=/var/run/redis.pid
+OCF_RESKEY_tmp_default=/var/run/
+
+: ${OCF_RESKEY_binary=${OCF_RESKEY_binary_default}}
+: ${OCF_RESKEY_client_binary=${OCF_RESKEY_client_binary_default}}
+: ${OCF_RESKEY_aof_check_binary=${OCF_RESKEY_aof_check_binary_default}}
+: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}}
+: ${OCF_RESKEY_user=${OCF_RESKEY_user_default}}
+: ${OCF_RESKEY_group=${OCF_RESKEY_group_default}}
+: ${OCF_RESKEY_log=${OCF_RESKEY_log_default}}
+: ${OCF_RESKEY_pid=${OCF_RESKEY_pid_default}}
+: ${OCF_RESKEY_tmp=${OCF_RESKEY_tmp_default}}
+
+REDIS_SERVER_NAME=${OCF_RESOURCE_INSTANCE}
+: ${REDIS_SERVER_NAME=${OCF_RESKEY_binary}}
+
+#######################################################################
+
+usage() {
+ cat <<UEND
+ usage: $0 (start|stop|validate-all|meta-data|monitor|promote|demote|notify)
+
+ $0 manages redis as an HA resource.
+
+ The 'start' operation starts redis.
+ The 'stop' operation stops redis.
+ The 'status' operation reports whether redis is running
+ The 'monitor' operation reports whether redis seems to be working
+ The 'promote' operation makes this redis instance run as master
+ The 'demote' operation makes this redis instance run as slave
+ The 'validate-all' operation reports whether the parameters are valid
+
+UEND
+}
+
+meta_data() {
+ cat <<END
+<?xml version="1.0"?>
+<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
+<resource-agent name="redis">
+<version>1.0</version>
+
+<longdesc lang="en">
+Resource script for redis.
+It manages a redis instance as an HA resource.
+</longdesc>
+<shortdesc lang="en">Manages a redis instance</shortdesc>
+
+<parameters>
+
+<parameter name="binary" unique="0" required="0">
+<longdesc lang="en">
+Name of the redis server binary. Use an absolute path if the binary is not resolvable via \$PATH
+</longdesc>
+<shortdesc lang="en">redis binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_binary_default}" />
+</parameter>
+
+<parameter name="client_binary" unique="0" required="0">
+<longdesc lang="en">
+Name of the redis client binary. Use an absolute path if the binary is not resolvable via \$PATH
+</longdesc>
+<shortdesc lang="en">redis client binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_client_binary_default}" />
+</parameter>
+
+<parameter name="aof_check_binary" unique="0" required="0">
+<longdesc lang="en">
+Name of the redis aof-check binary. Use an absolute path if the binary is not resolvable via \$PATH
+</longdesc>
+<shortdesc lang="en">redis aof-check binary</shortdesc>
+<content type="string" default="${OCF_RESKEY_aof_check_binary_default}" />
+</parameter>
+
+<parameter name="config" unique="0" required="0">
+<longdesc lang="en">
+Location of the Redis configuration file
+</longdesc>
+<shortdesc lang="en">redis config</shortdesc>
+<content type="string" default="${OCF_RESKEY_config_default}" />
+</parameter>
+
+<parameter name="user" unique="0" required="0">
+<longdesc lang="en">
+User running redis
+</longdesc>
+<shortdesc lang="en">redis user</shortdesc>
+<content type="string" default="${OCF_RESKEY_user_default}" />
+</parameter>
+
+<parameter name="group" unique="0" required="0">
+<longdesc lang="en">
+Group running redis (for logfile and directory permissions)
+</longdesc>
+<shortdesc lang="en">redis group</shortdesc>
+<content type="string" default="${OCF_RESKEY_group_default}"/>
+</parameter>
+
+<parameter name="log" unique="0" required="0">
+<longdesc lang="en">
+The logfile to be used for redis-server.
+</longdesc>
+<shortdesc lang="en">$REDIS_SERVER_NAME log file</shortdesc>
+<content type="string" default="${OCF_RESKEY_log_default}"/>
+</parameter>
+
+<parameter name="pid" unique="0" required="0">
+<longdesc lang="en">
+The pidfile to be used for redis-server.
+</longdesc>
+<shortdesc lang="en">$REDIS_SERVER_NAME pid file</shortdesc>
+<content type="string" default="${OCF_RESKEY_pid_default}"/>
+</parameter>
+
+<parameter name="tmp" unique="0" required="0">
+<longdesc lang="en">
+The tmpdir to be used for pacemaker managing.
+</longdesc>
+<shortdesc lang="en">pacemaker redis tmp file</shortdesc>
+<content type="string" default="${OCF_RESKEY_tmp_default}"/>
+</parameter>
+
+</parameters>
+
+<actions>
+<action name="start" timeout="120" />
+<action name="stop" timeout="120" />
+<action name="status" timeout="60" />
+<action name="monitor" depth="0" timeout="30" interval="20" />
+<action name="monitor" role="Master" depth="0" timeout="30" interval="10" />
+<action name="monitor" role="Slave" depth="0" timeout="30" interval="30" />
+<action name="promote" timeout="120" />
+<action name="demote" timeout="120" />
+<action name="notify" timeout="90" />
+<action name="validate-all" timeout="5" />
+<action name="meta-data" timeout="5" />
+</actions>
+</resource-agent>
+END
+}
+
+#######################################################################
+# Convenience variables
+
+CRM_MASTER="${HA_SBIN_DIR}/crm_master -l reboot "
+
+#######################################################################
+
+# Convenience functions
+
+config_get() {
+ grep "^\s*$1\s" $OCF_RESKEY_config | awk '{print $2}' | tail -n1
+}
+
+redis_cmd() {
+ local userun
+ local port
+ local password
+ userun=$1
+ shift
+ port=$(config_get port)
+ password=$(config_get requirepass)
+ if [ $userun -eq 0 ]; then
+ $OCF_RESKEY_client_binary -p "$port" -a "$password" "$@"
+ return $?
+ else
+ ocf_run -q $OCF_RESKEY_client_binary -p "$port" -a "$password" "$@"
+ return $?
+ fi
+}
+
+read_ms_status() {
+ local tmp
+ local has_slave_role
+ local master_host
+ local master_host_value
+ local should_be_slave
+
+ tmp=$(mktemp -p $HA_RSCTMP)
+ redis_cmd 0 info >$tmp
+ if [ $? -ne 0 ]; then
+ ocf_log info "Could not determine master/slave status";
+ rm -f $tmp
+ return $OCF_ERR_GENERIC;
+ fi
+
+ grep -e "role:slave" $tmp >/dev/null 2>&1
+ has_slave_role=$?
+
+ master_host_value=""
+ master_host=$(grep -e "master_host:" $tmp)
+ if [ $? -eq 0 ]; then
+ master_host_value=$(echo $master_host | cut -d':' -f2 | tr -d " ")
+ fi
+
+ test_slave
+ should_be_slave=$?
+
+ rm -f $tmp
+
+ if [ $has_slave_role -eq 0 -a "x$master_host_value" != "x" ]; then
+ ocf_log info "$REDIS_SERVER_NAME is running (as slave)";
+ return $OCF_SUCCESS;
+ elif [ $should_be_slave -eq 0 ]; then
+ ocf_log info "$REDIS_SERVER_NAME is running (as master, becoming slave when possible)";
+ return $OCF_SUCCESS;
+ else
+ ocf_log info "$REDIS_SERVER_NAME is running (as master)";
+ return $OCF_RUNNING_MASTER;
+ fi
+}
+
+read_pid() {
+ pid=""
+
+ if [ -e $OCF_RESKEY_pid ]; then
+ pid=$(cat $OCF_RESKEY_pid);
+ fi
+
+ if [ $? -ne 0 -o "x$pid" = "x" ]; then
+ pid=$(pidof -s $OCF_RESKEY_binary)
+ fi
+
+ if [ $? -eq 0 -a "x$pid" != "x" ]; then
+ kill -0 $pid
+ fi
+
+ if [ $? -ne 0 -o "x$pid" = "x" ]; then
+ ocf_log info "Could not read PID, $REDIS_SERVER_NAME is not running";
+ return $OCF_NOT_RUNNING
+ else
+ ocf_log info "$REDIS_SERVER_NAME is running (PID $pid)";
+ return $OCF_SUCCESS
+ fi
+}
+
+remove_pid() {
+ ocf_log debug "Removing PID file $OCF_RESKEY_pid"
+ rm -f $OCF_RESKEY_pid
+}
+
+mark_slave() {
+ ocf_log info "Mark $OCF_RESOURCE_INSTANCE to be a slave";
+ touch $OCF_RESKEY_tmp/$OCF_RESOURCE_INSTANCE.slave
+}
+
+unmark_slave() {
+ ocf_log info "Mark $OCF_RESOURCE_INSTANCE to be a master";
+ rm -f $OCF_RESKEY_tmp/$OCF_RESOURCE_INSTANCE.slave
+}
+
+test_slave() {
+ [ -e $OCF_RESKEY_tmp/$OCF_RESOURCE_INSTANCE.slave ]
+ return $?
+}
+
+set_master() {
+ local master_host=$1
+ local port
+ port=$(config_get port)
+
+ ocf_log info "Set $REDIS_SERVER_NAME to be a slave of $master_host";
+ redis_cmd 1 slaveof $master_host $port
+ return $?
+}
+
+unset_master() {
+ ocf_log info "Set $REDIS_SERVER_NAME to become a slave of no one";
+ redis_cmd 1 slaveof no one
+ return $?
+}
+
+#######################################################################
+
+# Functions invoked by resource manager actions
+
+redis_validate() {
+ check_binary $OCF_RESKEY_binary
+ check_binary $OCF_RESKEY_client_binary
+ check_binary start-stop-daemon
+
+ if [ ! -f $OCF_RESKEY_config ]; then
+ ocf_log err "Config $OCF_RESKEY_config doesn't exist";
+ return $OCF_ERR_INSTALLED;
+ fi
+
+ getent passwd $OCF_RESKEY_user >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ ocf_log err "User $OCF_RESKEY_user doesn't exit";
+ return $OCF_ERR_INSTALLED;
+ fi
+
+ getent group $OCF_RESKEY_group >/dev/null 2>&1
+ if [ $? -ne 0 ]; then
+ ocf_log err "Group $OCF_RESKEY_group doesn't exist";
+ return $OCF_ERR_INSTALLED;
+ fi
+
+ true
+}
+
+redis_status() {
+ local rc
+
+ read_pid
+ rc=$?
+
+ if [ $rc -ne $OCF_SUCCESS ]; then
+ ocf_log err "Removing PID"
+ remove_pid
+ return $rc
+ fi
+
+ read_ms_status
+ rc=$?
+ if ocf_is_ms; then
+ return $rc
+ else
+ if [ $rc -eq $OCF_SUCCESS -o $rc -eq $OCF_RUNNING_MASTER ]; then
+ ocf_log info "Redis is running"
+ return $OCF_SUCCESS
+ else
+ return $OCF_ERR_GENERIC
+ fi
+ fi
+}
+
+redis_start() {
+
+ local master_host
+ local rc
+ local append
+ local appendfilename
+
+ redis_status
+ rc=$?
+
+ if [ $rc -eq $OCF_RUNNING_MASTER -o $rc -eq $OCF_SUCCESS ]; then
+ ocf_log info "$REDIS_SERVER_NAME is already running"
+ else
+ touch $OCF_RESKEY_log
+ chown $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_log
+ chmod 0640 $OCF_RESKEY_log
+
+ touch $OCF_RESKEY_pid
+ chown $OCF_RESKEY_user:$OCF_RESKEY_group $OCF_RESKEY_pid
+
+ # repair AOF
+ append=$(config_get appendonly)
+ if [ -n "$append" -a "$append" = "yes" ]; then
+ appendfilename=$(config_get appendfilename)
+ if [ -z "$appendfilename" ]; then
+ appendfilename="appendonly.aof"
+ fi
+ if [ "{$appendfilename:0:1}" != "/" ]; then
+ appendfilename="$(config_get dir)/${appendfilename}"
+ fi
+ rc=0
+ if [ -e "$appendfilename" ]; then
+ ocf_log info "Redis is using $appendfilename as appendfilename"
+ ocf_run -q $OCF_RESKEY_aof_check_binary "$appendfilename"
+ rc=$?
+ fi
+ if [ $rc -ne 0 ]; then
+ ocf_log warn "Redis needs to fix $appendfilename"
+ echo y | $OCF_RESKEY_aof_check_binary --fix "$appendfilename"
+ fi
+ fi
+
+ start-stop-daemon --start --quiet --umask 007 --pidfile $OCF_RESKEY_pid --make-pidfile --chuid $OCF_RESKEY_user:$OCF_RESKEY_group --exec $(which $OCF_RESKEY_binary) -- $OCF_RESKEY_config
+ rc=$?
+
+ if [ $rc -ne 0 ]; then
+ ocf_log err "$OCF_RESKEY_binary start command failed: $rc"
+ return $OCF_NOT_RUNNING
+ fi
+
+ ocf_log info "$REDIS_SERVER_NAME started"
+ fi
+
+ # wait for redis to actually open the tcp port
+ # as redis starts but does not open this port if db files are corrupt
+ for i in $(seq 1 5); do
+ redis_cmd 0 info >/dev/null
+ if [ $? -eq 0 ]; then
+ break
+ fi
+ sleep 1
+ done
+ redis_cmd 1 info >/dev/null
+ if [ $? -ne 0 ]; then
+ return $OCF_ERR_GENERIC
+ fi
+
+ if ocf_is_ms; then
+ # Now, let's see whether there is a master. We might be a new
+ # node that is just joining the cluster, and the CRM may have
+ # promoted a master before.
+ master_host=$(echo $OCF_RESKEY_CRM_meta_notify_master_uname | tr -d " ")
+ if [ ! -z "$master_host" -a "$master_host" != $(uname -n) ]; then
+ ocf_log info "Changing redis configuration to replicate from host: $master_host"
+ while true; do
+ redis_cmd 0 info |grep 'loading:0'
+ if [ $? -eq 0 ]; then
+ break
+ else
+ ocf_log err "Redis still loading data, giving it a second to finish"
+ sleep 1
+ fi
+ done
+ set_master $master_host
+ fi
+ mark_slave
+
+ # We also need to set a master preference, otherwise Pacemaker
+ # won't ever promote us in the absence of any explicit
+ # preference set by the administrator. We choose a low
+ # greater-than-zero preference.
+ $CRM_MASTER -v 1
+ fi
+
+ return $OCF_SUCCESS
+}
+
+redis_stop() {
+ local rc
+
+ if ocf_is_ms; then
+ # clear preference for becoming master
+ $CRM_MASTER -D
+ fi
+
+ redis_status
+ rc=$?
+
+ if [ $rc -ne $OCF_RUNNING_MASTER -a $rc -ne $OCF_SUCCESS ]; then
+ ocf_log info "$REDIS_SERVER_NAME is not running";
+ return $OCF_SUCCESS
+ fi
+
+ start-stop-daemon --stop --retry 10 --quiet --oknodo --pidfile $OCF_RESKEY_pid
+ rc=$?
+
+ if [ $rc -ne 0 ]; then
+ ocf_log err "$OCF_RESKEY_binary stop command failed: $rc"
+ return $OCF_ERR_GENERIC
+ fi
+
+ ocf_log info "$REDIS_SERVER_NAME stopped";
+ remove_pid
+ unmark_slave
+ return $OCF_SUCCESS
+}
+
+redis_promote() {
+ local rc
+
+ redis_status
+ rc=$?
+
+ if [ $rc -ne $OCF_RUNNING_MASTER -a $rc -ne $OCF_SUCCESS ]; then
+ return $OCF_NOT_RUNNING
+ fi
+
+ unmark_slave
+ unset_master
+
+ # Existing master gets a higher-than-default master preference, so
+ # the cluster manager does not shuffle the master role around
+ # unnecessarily
+ $CRM_MASTER -v 10000
+
+ return $OCF_SUCCESS
+}
+
+redis_demote() {
+ local rc
+ local master_host
+
+ redis_status
+ rc=$?
+
+ if [ $rc -ne $OCF_RUNNING_MASTER -a $rc -ne $OCF_SUCCESS ]; then
+ return $OCF_NOT_RUNNING
+ fi
+
+ # Now, let's see whether there is a master. We might be a new
+ # node that is just joining the cluster, and the CRM may have
+ # promoted a master before.
+ master_host=$(echo $OCF_RESKEY_CRM_meta_notify_master_uname | tr -d " ")
+ if [ ! -z "$master_host" -a "$master_host" != $(uname -n) ]; then
+ ocf_log info "Changing redis configuration to replicate from host: $master_host"
+ while true; do
+ redis_cmd 0 info |grep 'loading:0'
+ if [ $? -eq 0 ]; then
+ break
+ else
+ ocf_log err "Redis still loading data, giving it a second to finish"
+ sleep 1
+ fi
+ done
+ set_master $master_host
+ fi
+ mark_slave
+
+ # Return master preference to default, so the cluster manager gets
+ # a chance to select a new master
+ $CRM_MASTER -v 1
+
+ return $OCF_SUCCESS
+}
+
+redis_notify() {
+ local rc
+
+ local master_host
+ local type_op
+
+ redis_status
+ rc=$?
+
+ if [ $rc -ne $OCF_RUNNING_MASTER -a $rc -ne $OCF_SUCCESS ]; then
+ return $OCF_NOT_RUNNING
+ fi
+
+ # If not configured as a Stateful resource, we make no sense of
+ # notifications.
+ if ! ocf_is_ms; then
+ ocf_log info "This agent makes no use of notifications unless running in master/slave mode."
+ return $OCF_SUCCESS
+ fi
+
+ type_op="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
+ ocf_log debug "Received $type_op notification."
+
+ case "$type_op" in
+ 'pre-promote')
+ # A node is about to being promoted to master.
+ master_host=$(echo $OCF_RESKEY_CRM_meta_notify_promote_uname | tr -d " ")
+ if [ -z "$master_host" ]; then
+ ocf_log err "Unable to determine host to be promoted!"
+ return $OCF_ERR_GENERIC
+ fi
+
+ if [ $master_host = $(uname -n) ]; then
+ ocf_log info "We are about to being promoted."
+ return $OCF_SUCCESS
+ fi
+
+ ocf_log info "Becoming a slave of $master_host"
+ set_master $master_host
+ if [ $? -ne 0 ]; then
+ return $OCF_ERR_GENERIC
+ else
+ return $OCF_SUCCESS
+ fi
+ ;;
+ 'pre-demote')
+ # A master is about to being demoted.
+ demote_host=$(echo $OCF_RESKEY_CRM_meta_notify_demote_uname | tr -d " ")
+ if [ -z "$demote_host" ]; then
+ ocf_log err "Unable to determine host to be demoted!"
+ return $OCF_ERR_GENERIC
+ fi
+
+ if [ $demote_host = $(uname -n) ]; then
+ ocf_log info "We are about to being demoted."
+ return $OCF_SUCCESS
+ fi
+
+ ocf_log info "Deslaving from $demote_host."
+ unset_master
+ return $OCF_SUCCESS
+ ;;
+ *)
+ return $OCF_SUCCESS
+ ;;
+ esac
+}
+
+#######################################################################
+
+# Make sure meta-data and usage always succeed
+case $__OCF_ACTION in
+meta-data) meta_data
+ exit $OCF_SUCCESS
+ ;;
+usage|help) usage
+ exit $OCF_SUCCESS
+ ;;
+esac
+
+# Anything other than meta-data and usage must pass validation
+redis_validate || exit $?
+
+# Translate each action into the appropriate function call
+case $__OCF_ACTION in
+start) redis_start;;
+stop) redis_stop;;
+status|monitor) redis_status;;
+promote) redis_promote;;
+demote) redis_demote;;
+notify) redis_notify;;
+validate-all) ;;
+*) usage
+ exit $OCF_ERR_UNIMPLEMENTED
+ ;;
+esac
+rc=$?
+
+# The resource agent may optionally log a debug message
+ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc"
+exit $rc