#!/usr/bin/bash # # pgpool-II resource agent. # # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # Further, this software is distributed without any warranty that it is # free of the rightful claim of any third person regarding infringement # or the like. Any license provided herein, whether implied or # otherwise, applies only to this software file. Patent licenses, if # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # ####################################################################### # # This resource agent was written by Eliot Gable # ####################################################################### ####################################################################### # Initialization: : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/resource.d/heartbeat} . ${OCF_FUNCTIONS_DIR}/.ocf-shellfuncs ####################################################################### meta_data() { cat < 1.0 This resource agent provides basic management of pgpool-II. It starts and stops pgpool-II and monitors its status. It will also monitor the status of each connection and can optionally attempt to automatically reconnect detached nodes or can mark the service as failed if there are any detached nodes. Manages pgpool-II Administrative username for pgpool-II control. Administrative username. Administrative password for pgpool-II control. Administrative password. Administrative port for pgpool-II control. Administrative port for PCP commands. Administrative host for pgpool-II control. Administrative host for PCP commands. Path to the pgpool-II binary. Path to pgpool. Path to the pcp_attach_node binary. Path to pcp_attach_node. Path to the pcp_detach_node binary. Path to pcp_detach_node. Path to the pcp_node_count binary. Path to pcp_node_count. Path to the pcp_node_info binary. Path to pcp_node_info. Stop mode to use when stopping pgpool-II. Stop mode for pgpool-II. If "true", then during monitoring actions, the resource agent will attempt to re-attach any disconnected nodes. No error will be reported if re-attachment fails. Automatically reattach failed nodes This instructs the resource agent to mark pgpool-II in a failed state if one or more of the nodes is detached. The monitor action will always mark pgpool-II in a failed state if all nodes are detached, so this is only useful if you want to mark pgpool-II in a failed state if at least one node is detached. The auto_reconnect option will always try to reconnect detached nodes (if enabled) before this fail_on_detached mechanism triggers. Marks resource as failed if at least one node is detached. This is similar to fail_on_detached, except you can specify a comma-seperated list of node IDs. If specified, pgpool2 will only be marked as "failed" if one of the nodes in the list is detached or if all nodes are detached. Specify a list of nodes to monitor for failure. END } ####################################################################### pgpool2_usage() { cat <> /tmp/pgpool sleep 2 if pgpool2_status; then ocf_log info "${OCF_RESOURCE_INSTANCE} Successfully started pgpool-II" return $OCF_SUCCESS else #echo "pgpool couldn't be started, why?" /tmp/pgpool ocf_log error "${OCF_RESOURCE_INSTANCE} Failed to start pgpool-II" return $OCF_ERR_GENERIC fi else ocf_log error "${OCF_RESOURCE_INSTANCE} Failed to start pgpool-II" fi return $OCF_ERR_GENERIC } pgpool2_stop() { ocf_log info "Using $PGPOOL -m $STOP_MODE stop to stop pgpool-II" if $PGPOOL -m $STOP_MODE stop; then ocf_log info "${OCF_RESOURCE_INSTANCE} Successfully stopped pgpool-II" return $OCF_SUCCESS else ocf_log info "${OCF_RESOURCE_INSTANCE} Already stopped pgpool-II" return $OCF_SUCCESS fi } pgpool2_status() { if [ ! -r "/var/postgres/pgpool-II/pgpool.pid" ]; then return $OCF_NOT_RUNNING fi ps_info=$(ps ax | grep "pgpool" | grep $(cat /var/postgres/pgpool-II/pgpool.pid)) #echo "ps_info: $ps_info" >> /tmp/pgpool if [ -z "$ps_info" ]; then #echo "Found pgpool is NOT running..." >> /tmp/pgpool return $OCF_NOT_RUNNING else #echo "Found pgpool is running..." >> /tmp/pgpool # Try to reconnect any detached nodes if ocf_is_true ${OCF_RESKEY_auto_reconnect} ; then NODE_COUNT=$($PCP_NODE_COUNT 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password) for node in `seq 0 $((NODE_COUNT-1))`; do NODE_INFO=$($PCP_NODE_INFO 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password $node | awk '{print $3}') if [ "$NODE_INFO" = "3" ]; then ocf_log info "Node $node is currently detached. Attempting to reattach the node." $PCP_ATTACH_NODE 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password $node ATTACHED="1" fi done if [ -n "${ATTACHED}" ]; then sleep 1 fi fi # Fail if configured to fail on one or more detached nodes and a node is still detached if ocf_is_true ${OCF_RESKEY_fail_on_detached} ; then NODE_COUNT=$($PCP_NODE_COUNT 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password) for node in `seq 0 $((NODE_COUNT-1))`; do NODE_INFO=$($PCP_NODE_INFO 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password $node | awk '{print $3}') if [ "$NODE_INFO" = "3" ]; then ocf_log error "Node $node is detached. The pgpool-II service has failed." return $OCF_ERR_GENERIC fi done fi # Fail if one of the specifically configured nodes is detached at this point if [ -n "${OCF_RESKEY_fail_on_node_detached}" ]; then NODE_COUNT=$($PCP_NODE_COUNT 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password) for node in `seq 0 $((NODE_COUNT-1))`; do NODE_INFO=$($PCP_NODE_INFO 1 $OCF_RESKEY_pcp_admin_host $OCF_RESKEY_pcp_admin_port $OCF_RESKEY_pcp_admin_username $OCF_RESKEY_pcp_admin_password $node | awk '{print $3}') if [ "$NODE_INFO" = "3" ]; then TOKEN=${OCF_RESKEY_fail_on_node_detached%%,*} TOKEN_STRING=${OCF_RESKEY_fail_on_node_detached#*,} while [ -n "$TOKEN" ] && [ "${TOKEN}" != "${TOKEN_STRING}" ]; do if [ "$TOKEN" -eq $node ]; then ocf_log error "Node $node is detached. The pgpool-II service has failed." return $OCF_ERR_GENERIC fi TOKEN=${TOKEN_STRING%%,*} if [ "${TOKEN_STRING}" == "${TOKEN_STRING#*,}" ]; then TOKEN_STRING="" else TOKEN_STRING=${TOKEN_STRING#*,} fi done fi done fi fi # Service is running and there is no reason to fail #echo "pgpool should be running..." >> /tmp/pgpool return $OCF_SUCCESS } pgpool2_validate() { # If we're running as a clone, are the clone meta attrs OK? # if [ "${OCF_RESKEY_CRM_meta_clone}" ]; then # if [ "${OCF_RESKEY_CRM_meta_clone_node_max}" != 1 ]; then # ocf_log error "Misconfigured clone parameters. Must set meta attribute \"clone_node_max\" to 1, got ${OCF_RESKEY_CRM_meta_clone_node_max}." # return $OCF_ERR_ARGS # fi # fi if [ -z "$OCF_RESKEY_pcp_admin_username" ]; then ocf_log error "Missing required parameter \"pcp_admin_username\"." return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_pcp_admin_password" ]; then ocf_log error "Missing required parameter \"pcp_admin_password\"." return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_pcp_admin_host" ]; then ocf_log error "Missing required parameter \"pcp_admin_host\"." return $OCF_ERR_ARGS fi if [ -z "$OCF_RESKEY_pcp_admin_port" ]; then ocf_log error "Missing required parameter \"pcp_admin_port\"." return $OCF_ERR_ARGS fi # Did we get a path for the pgpool binary? if [ -z "$OCF_RESKEY_pgpool_bin" ]; then ocf_log error "Missing required parameter \"pgpool_bin\"." return $OCF_ERR_ARGS else if [ -x "$PGPOOL" ]; then ocf_log error "The pgpool binary is not executable or is not installed." return $OCF_ERR_INSTALLED fi fi # Did we get a path for the pcp_attach_node binary? if [ -z "$OCF_RESKEY_pcp_attach_node_bin" ]; then ocf_log error "Missing required parameter \"pcp_attach_node_bin\"." return $OCF_ERR_ARGS else if [ -x "$PCP_ATTACH_NODE" ]; then ocf_log error "The pcp_attach_node binary is not executable or is not installed." return $OCF_ERR_INSTALLED fi fi # Did we get a path for the pcp_detach_node binary? if [ -z "$OCF_RESKEY_pcp_detach_node_bin" ]; then ocf_log error "Missing required parameter \"pcp_detach_node_bin\"." return $OCF_ERR_ARGS else if [ -x "$PCP_DETACH_NODE" ]; then ocf_log error "The pcp_detach_node binary is not executable or is not installed." return $OCF_ERR_INSTALLED fi fi # Did we get a path for the pcp_node_count binary? if [ -z "$OCF_RESKEY_pcp_node_count_bin" ]; then ocf_log error "Missing required parameter \"pcp_node_count_bin\"." return $OCF_ERR_ARGS else if [ -x "$PCP_NODE_COUNT" ]; then ocf_log error "The pcp_node_count binary is not executable or is not installed." return $OCF_ERR_INSTALLED fi fi # Did we get a path for the pcp_node_info binary? if [ -z "$OCF_RESKEY_pcp_node_info_bin" ]; then ocf_log error "Missing required parameter \"pcp_node_info_bin\"." return $OCF_ERR_ARGS else if [ -x "$PCP_NODE_INFO" ]; then ocf_log error "The pcp_node_info binary is not executable or is not installed." return $OCF_ERR_INSTALLED fi fi if [ -n "$OCF_RESKEY_stop_mode" ]; then if ! echo "$OCF_RESKEY_stop_mode" | grep -E '[fsi]|fast|start|immediate' >> /dev/null; then ocf_log error "Stop mode is invalid." return $OCF_ERR_ARGS fi else ocf_log error "Stop mode was not specified." return $OCF_ERR_ARGS fi if [ -n "$OCF_RESKEY_auto_reconnect" ] && [ "$OCF_RESKEY_auto_reconnect" != "true" ] && [ "$OCF_RESKEY_auto_reconnect" != "false" ]; then ocf_log error "Parameter 'auto_reconnect' must be empty, 'true', or 'false'." return $OCF_ERR_ARGS fi if [ -n "$OCF_RESKEY_fail_on_detached" ] && [ "$OCF_RESKEY_fail_on_detached" != "true" ] && [ "${OCF_RESKEY_fail_on_detached}" != "false" ]; then ocf_log error "Parameter 'fail_on_detached' must be empty, 'true', or 'false'." return $OCF_ERR_ARGS fi shopt -s extglob if [ -n "$OCF_RESKEY_fail_on_node_detached" ]; then TOKEN=${OCF_RESKEY_fail_on_node_detached%%,*} TOKEN_STRING=${OCF_RESKEY_fail_on_node_detached#*,} while [ -n $TOKEN ] && [ "${TOKEN}" != "${TOKEN_STRING}" ]; do case $TOKEN in [^0-9]) ocf_log error "Invalid token '${TOKEN}' in parameter 'fail_on_node_detached'." return $OCF_ERR_ARGS ;; esac TOKEN=${TOKEN_STRING%%,*} if [ "${TOKEN_STRING}" == "${TOKEN_STRING#*,}" ]; then TOKEN_STRING="" else TOKEN_STRING=${TOKEN_STRING#*,} fi done fi return $OCF_SUCCESS } # These two actions must always succeed case $__OCF_ACTION in meta-data) meta_data # OCF variables are not set when querying meta-data exit 0 ;; usage|help) pgpool2_usage exit $OCF_SUCCESS ;; esac pgpool2_validate || exit $? PGPOOL=$OCF_RESKEY_pgpool_bin PCP_ATTACH_NODE=$OCF_RESKEY_pcp_attach_node_bin PCP_DETACH_NODE=$OCF_RESKEY_pcp_detach_node_bin PCP_NODE_COUNT=$OCF_RESKEY_pcp_node_count_bin PCP_NODE_INFO=$OCF_RESKEY_pcp_node_info_bin STOP_MODE=$OCF_RESKEY_stop_mode #echo "$(date)" >> /tmp/pgpool case $__OCF_ACTION in start) pgpool2_start;; stop) pgpool2_stop;; status|monitor) pgpool2_status;; validate-all) ;; *) pgpool2_usage exit $OCF_ERR_UNIMPLEMENTED ;; esac rc=$? ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION returned $rc" exit $rc