Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

redis RA: bring up in slave mode #132

Closed
wants to merge 16 commits into from

4 participants

@michael-dev

This pull requests is based on the last redis pull request here and makes the RA adhere to the pacemaker spec, that multi-state resources need to be brought up in slave mode. This fixes a race-condition when pacemaker has not yet promoted a master and thus restarts all instances infinitely, as they come up as masters instead of slaves.

Further, it autodetects port and password required for redis-cli from the config file.

@krig

This request should be closed as it is superseded by the request in #212.

@dmuhamedagic

Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 15, 2011
  1. The deletion of the primary IP via the ip command will also remove th…

    Martin Walter authored
    …e secondary IP. Thus, trying to delete the secondary IP after the primary IP was deleted will result in an error. This fix assures that delete_interface() will only result in an error if ' addr delete' has failed and the ip is still listed in addr show.
  2. Adds the RA for the redis service, based on that of mysql. Supports m…

    Martin Walter authored
    …aster/slave configurations of a depth of 1.
Commits on Nov 23, 2011
  1. @coredump
Commits on Nov 28, 2011
  1. @coredump
Commits on Aug 30, 2012
  1. @michael-dev
  2. @michael-dev

    fix typo

    michael-dev authored
  3. @michael-dev
Commits on Sep 2, 2012
  1. @michael-dev
  2. @michael-dev
Commits on Sep 3, 2012
  1. @michael-dev
Commits on Sep 4, 2012
  1. @michael-dev
Commits on Sep 11, 2012
  1. @michael-dev
Commits on Sep 18, 2012
  1. @michael-dev

    fix typo

    michael-dev authored
Commits on Jan 22, 2013
  1. detect crashed redis instance

    mbr authored
Commits on Jan 23, 2013
  1. add IPv6addr script which does not ping

    mbr authored
Commits on Jan 29, 2013
  1. @michael-dev

    fix ms/state detection

    michael-dev authored mbr committed
This page is out of date. Refresh to see the latest.
Showing with 949 additions and 1 deletion.
  1. +9 −1 heartbeat/IPaddr2
  2. +271 −0 heartbeat/IPv6addr2
  3. +669 −0 heartbeat/redis
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
Something went wrong with that request. Please try again.