#!/bin/bash # # OCF Resource Agent for pgpool-II 2.x # # Copyright 2012-2013 PgPool Global Development Group # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice appear in all # copies and that both that copyright notice and this permission # notice appear in supporting documentation, and that the name of the # author not be used in advertising or publicity pertaining to # distribution of the software without specific, written prior # permission. The author makes no representations about the # suitability of this software for any purpose. It is provided "as # is" without express or implied warranty. # # Support: pgpool-general@pgpool.net # # OCF parameters are as below # # pgpoolconf path of pgpool.conf # (default: @_PGPOOL_DIR_@/etc/pgpool.conf) # # pcpconf path of pcp.conf # # hbaconf path of pool_hba.conf # # logfile log file for stdout and stderr redirection; # or a program for log collecting by a pipeline. # (e.g.) # "/var/log/pgpool.log" # "| logger -t pgpool -p local3.info" # # options pgpool start options (except configuration file options). # "-D" is recommended if pgpool_status is not in shared space. # # pgpooluser pgpool start user # # checkmethod monitoring method: # "pid" process existence check only (default). # "pcp" check by pcp_node_count command. # "psql" check by psql command. # # checkstring parameter for monitoring method # checkmetod="pid" : pidfile # (default: parse from pgpool.conf file) # checkmetod="pcp" : parameter string for pcp_node_count # (default: "10 localhost 9898 postgres pass") # checkmetod="psql" : parameter string for psql # (default: "-U postgres -h localhost -l -p 9999") # VERSION=2.1 ##### Source function library. : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat} . ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs ###### Parameter defaults OCF_RESKEY_pgpoolconf_default="@_PGPOOL_DIR_@/etc/pgpool.conf" OCF_RESKEY_pcpconf_default="" OCF_RESKEY_hbaconf_default="" OCF_RESKEY_logfile_default="" OCF_RESKEY_options_default="" OCF_RESKEY_pgpooluser_default="postgres" OCF_RESKEY_checkmethod_default="pid" OCF_RESKEY_checkstring_default="" OCF_RESKEY_pgpoolcmd_default=@_PGPOOL_DIR_@/bin/pgpool OCF_RESKEY_psqlcmd_default=@_PGSQL_DIR_@/bin/psql OCF_RESKEY_pcpnccmd_default=@_PGPOOL_DIR_@/bin/pcp_node_count : ${OCF_RESKEY_pgpoolconf=${OCF_RESKEY_pgpoolconf_default}} : ${OCF_RESKEY_pcpconf=${OCF_RESKEY_pcpconf_default}} : ${OCF_RESKEY_hbaconf=${OCF_RESKEY_hbaconf_default}} : ${OCF_RESKEY_logfile=${OCF_RESKEY_logfile_default}} : ${OCF_RESKEY_options=${OCF_RESKEY_options_default}} : ${OCF_RESKEY_pgpooluser=${OCF_RESKEY_pgpooluser_default}} : ${OCF_RESKEY_checkmethod=${OCF_RESKEY_checkmethod_default}} : ${OCF_RESKEY_pgpoolcmd=${OCF_RESKEY_pgpoolcmd_default}} : ${OCF_RESKEY_psqlcmd=${OCF_RESKEY_psqlcmd_default}} : ${OCF_RESKEY_pcpnccmd=${OCF_RESKEY_pcpnccmd_default}} if [ ! -e $OCF_RESKEY_pgpoolconf ]; then ocf_log warn "${OCF_RESOURCE_INSTANCE}: file '$OCF_RESKEY_pgpoolconf' (pgpoolconf) does not exists." fi PIDFILE=$(cat "$OCF_RESKEY_pgpoolconf" | grep "^pid_file_name" | cut -d "'" -f 2) if [ "x$OCF_RESKEY_checkstring" = "x" ] ; then case "$OCF_RESKEY_checkmethod" in pcp) OCF_RESKEY_checkstring="10 localhost 9898 postgres pass" ;; psql) OCF_RESKEY_checkstring="-h localhost -U postgres -p 9999 -l" ;; esac else case "$OCF_RESKEY_checkmethod" in pid) PIDFILE=$OCF_RESKEY_checkstring ;; esac fi ###### Build Start command PGPOOL="$OCF_RESKEY_pgpoolcmd -f $OCF_RESKEY_pgpoolconf" PGPOOL_START_ARG="" if [ "x$OCF_RESKEY_hbaconf" != 'x' ]; then PGPOOL="$PGPOOL -a $OCF_RESKEY_hbaconf" fi if [ "x$OCF_RESKEY_pcpconf" != 'x' ]; then PGPOOL="$PGPOOL -F $OCF_RESKEY_pcpconf" fi if [ "x$OPTIONS" != 'x' ]; then PGPOOL_START_ARG="$PGPOOL_START_ARG $OPTIONS" fi if [ "x$OCF_RESKEY_logfile" != 'x' ]; then PGPOOL="nohup $PGPOOL" if [ $(echo $OCF_RESKEY_logfile | cut -c 1) = '|' ]; then PGPOOL_START_ARG="$PGPOOL_START_ARG -n 2>&1 $OCF_RESKEY_logfile &" else PGPOOL_START_ARG="$PGPOOL_START_ARG -n >> $OCF_RESKEY_logfile 2>&1 &" fi fi PGPOOL_STOP_ARG=" -m fast stop" ###### Functions do_monitor() { if ! pidfile_process_exists_p then return $OCF_NOT_RUNNING fi case "$OCF_RESKEY_checkmethod" in pid) return $OCF_SUCCESS ;; pcp) do_pcp_check return $? ;; psql) do_psql_check return $? ;; esac ocf_log err "${OCF_RESOURCE_INSTANCE}: Invalid checkmethod parameter" return $OCF_ERR_GENERIC } do_pcp_check() { ocf_run -q $OCF_RESKEY_pcpnccmd $OCF_RESKEY_checkstring rc=$? if [ $rc -eq 0 ] then return $OCF_SUCCESS else ocf_log err "${OCF_RESOURCE_INSTANCE}: pcp_check fail" return $OCF_NOT_RUNNING fi } do_psql_check() { ocf_run -q $OCF_RESKEY_psqlcmd $OCF_RESKEY_checkstring rc=$? if [ $rc -eq 0 ] then return $OCF_SUCCESS else ocf_log err "${OCF_RESOURCE_INSTANCE}: psql_check fail" return $OCF_NOT_RUNNING fi } do_start() { if pidfile_process_exists_p then ocf_log info "${OCF_RESOURCE_INSTANCE}: pgpool is already running." return $OCF_SUCCESS fi ocf_log info \ "${OCF_RESOURCE_INSTANCE}: $PGPOOL $PGPOOL_START_ARG AS $OCF_RESKEY_pgpooluser" su $OCF_RESKEY_pgpooluser -c "$PGPOOL $PGPOOL_START_ARG" if [ $? -ne 0 ] then ocf_log err "${OCF_RESOURCE_INSTANCE}: Can't start pgpool." return $OCF_ERR_GENERIC fi while ( ! pidfile_process_exists_p ) ; do ocf_log debug "${OCF_RESOURCE_INSTANCE}: not started yet, waiting" sleep 1 done return $OCF_SUCCESS } do_stop() { if ! pidfile_process_exists_p then ocf_log info "${OCF_RESOURCE_INSTANCE}: pgpool is already stopped." return $OCF_SUCCESS fi su -c "$PGPOOL $PGPOOL_STOP_ARG" if [ $? -ne 0 ] then ocf_log err "${OCF_RESOURCE_INSTANCE}: Can't stop pgpool." return $OCF_ERR_GENERIC fi while pidfile_process_exists_p ; do ocf_log debug "${OCF_RESOURCE_INSTANCE}: not stopped yet, waiting" sleep 1 done return $OCF_SUCCESS } do_reload() { su -c "$PGPOOL reload" return $OCF_SUCCESS } # - has side effect: kills zombie immediately # - dependency: /proc/PID/status file # pidfile_process_exists_p() { if [ -f $PIDFILE ]; then RPID=`cat $PIDFILE` if kill -0 $RPID then if grep -E "^State:.*zombie" /proc/$RPID/status then pkill -QUIT -P $RPID kill -QUIT $RPID return 1 else return 0 # ok, process exists fi else return 1 fi else ocf_log debug "${OCF_RESOURCE_INSTANCE}: PIDFILE $PIDFILE doesn't exist" return 1 fi } do_metadata() { cat < ${VERSION} This is an OCF Resource Agent for pgpool-II. OCF Resource Agent for pgpool-II Path to pgpool.conf of pgpool. pgpool.conf path Path to pcp.conf of pgpool. pcp.conf path Path to pool_hba.conf of pgpool. pool_hba.conf path pgpool log file for stdout and stderr redirection; or a program for log collecting by a pipeline. (e.g.) "/var/log/pgpool.log" "| logger -t pgpool -p local3.info" pgpool logfile pgpool command line options (except configuration file options). pgpool command line options pgpool run as this user. pgpool user monitoring method type. "pid" process existence check only. "pcp" check by pcp_node_count command. "psql" check by psql command. monitoring method type parameter for monitoring method. when checkmetod="pid", this means pidfile path. (e.g.) "/var/run/pgpool/pgpool.pid" when checkmetod="pcp", this means a parameter string for pcp_node_count. (e.g.) "10 localhost 9898 postgres pass" when checkmetod="psql", this means a parameter string for psql. (e.g.) "-U postgres -h localhost -l -p 9999" a parameter for monitoring method pgpool command. psql command. psql command pcp_node_count command. pcp_node_count command EOF return $OCF_SUCCESS } do_help() { echo "pgpool (start|stop|reload|monitor|meta-data|validate-all|help)" return $OCF_SUCCESS } do_validate_all() { if [ "x$OCF_RESKEY_pgpoolconf" = "x" ] ; then return $OCF_ERR_CONFIGURED fi if [ ! -e $OCF_RESKEY_pgpoolconf ] ; then return $OCF_ERR_CONFIGURED fi if [ ! -x $OCF_RESKEY_pgpoolcmd ] ; then return $OCF_ERR_INSALLED fi if [ ! -x $OCF_RESKEY_psqlcmd -a $OCF_RESKEY_checkmethod = "psql" ] ; then return $OCF_ERR_INSALLED fi if [ ! -x $OCF_RESKEY_pcpnccmd -a $OCF_RESKEY_checkmethod = "pcp" ] ; then return $OCF_ERR_INSALLED fi if [ "x$PIDFILE" = "x" -a $OCF_RESKEY_checkmethod = "pid" ] then return $OCF_ERR_CONFIGURED fi return $OCF_SUCCESS } ###### main case "$1" in start) do_start ;; stop) do_stop ;; reload) do_reload ;; monitor|status) do_monitor ;; meta-data) do_metadata ;; promote|demote|migrate_to|migrate_from) exit $OCF_ERR_UNIMPLEMENTED ;; validate-all) do_validate_all ;; usage|help) do_help ;; esac RC=$? ocf_log debug "${OCF_RESOURCE_INSTANCE}: $__OCF_ACTION returned $RC" exit $RC