From b7bcf0d7b833559962cde8c5f4dfe3f5c07dda3c Mon Sep 17 00:00:00 2001 From: Takuma Hoshiai Date: Fri, 4 Nov 2022 11:07:09 +0900 Subject: [PATCH] Add trusted_server_command parameter This patch be able to specify a command that is used by trusted_servers for checking up stream connection. Previously, ping command was only used, and it was hard coded. Default is 'ping -q -c3 %h' which means same as before. --- doc.ja/src/sgml/watchdog.sgml | 47 +++++++-- doc/src/sgml/watchdog.sgml | 30 ++++-- src/config/pool_config_variables.c | 10 ++ src/include/pool_config.h | 1 + src/include/watchdog/wd_utils.h | 3 +- src/sample/pgpool.conf.sample-stream | 12 ++- .../tests/036.trusted_servers/test.sh | 75 +++++++++++++++ src/utils/pool_process_reporting.c | 5 + src/watchdog/wd_lifecheck.c | 16 ++-- src/watchdog/wd_ping.c | 95 ++++++++++++++++++- 10 files changed, 267 insertions(+), 27 deletions(-) create mode 100755 src/test/regression/tests/036.trusted_servers/test.sh diff --git a/doc.ja/src/sgml/watchdog.sgml b/doc.ja/src/sgml/watchdog.sgml index f212d105a..50556a193 100644 --- a/doc.ja/src/sgml/watchdog.sgml +++ b/doc.ja/src/sgml/watchdog.sgml @@ -327,24 +327,26 @@ - - ping_path (string) + + trusted_server_command (string) - ping_path設定パラメータ + trusted_server_command設定パラメータ - 上位サーバへの接続監視に利用するpingコマンドのパスを指定します。 - "/bin"のようにパスだけを指定します。 + 信頼できるサーバのping応答を確認するユーザコマンドを指定します。 + %hはtrusted_serversで指定された各ホスト名に置換されます。 + デフォルトはping -q -c3 %hです。 + ping_path設定パラメータ + + + + + + 仮想IPの起動を確認するために利用するpingコマンドのパスを指定します。 + "/bin"のようにパスだけを指定します。 + + + + このパラメータは、サーバ起動時にのみ設定できます。 + + + diff --git a/doc/src/sgml/watchdog.sgml b/doc/src/sgml/watchdog.sgml index e8d5f6d7f..fdd23224d 100644 --- a/doc/src/sgml/watchdog.sgml +++ b/doc/src/sgml/watchdog.sgml @@ -232,17 +232,18 @@ pgpool_port2 = 9999 - - ping_path (string) + + trusted_server_command (string) - ping_path configuration parameter + trusted_server_command configuration parameter - Specifies the path of a ping command for monitoring - connection to the upper servers. Set the only path of the directory containing the - ping utility, such as "/bin" or such directory. + Specifies a user command to run when Pgpool-II check + that trusted servers respond to ping. Any %h in the string is replaced by each host + name specified trusted_servers. Default is + ping -q -c3 %h. This parameter can only be set at server start. @@ -398,6 +399,23 @@ pgpool_port2 = 9999 + + ping_path (string) + + ping_path configuration parameter + + + + + Specifies the path of a ping command to check startup of the virtual IP. + Set the only path of the directory containing the ping utility, + such as "/bin" or such directory. + + + This parameter can only be set at server start. + + + diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index fe1bfd718..25d7ac29e 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -1041,6 +1041,16 @@ static struct config_string ConfigureNamesString[] = NULL, NULL, NULL, NULL }, + { + {"trusted_server_command", CFGCXT_RELOAD, WATCHDOG_CONFIG, + "Command to excute when communicate with trusted server.", + CONFIG_VAR_TYPE_STRING, false, 0 + }, + &g_pool_config.trusted_server_command, + "ping -q -c3 %h", + NULL, NULL, NULL, NULL + }, + { {"delegate_IP", CFGCXT_INIT, WATCHDOG_CONFIG, "Old config parameter for delegate_ip.", diff --git a/src/include/pool_config.h b/src/include/pool_config.h index b6967cf28..142c6fab1 100644 --- a/src/include/pool_config.h +++ b/src/include/pool_config.h @@ -579,6 +579,7 @@ typedef struct int pgpool_node_id; /* pgpool (watchdog) node id */ WdNodesConfig wd_nodes; /* watchdog lists */ char *trusted_servers; /* icmp reachable server list (A,B,C) */ + char *trusted_server_command; /* Executes this command when upper servers are observed */ char *delegate_ip; /* delegate IP address */ int wd_interval; /* lifecheck interval (sec) */ char *wd_authkey; /* Authentication key for watchdog diff --git a/src/include/watchdog/wd_utils.h b/src/include/watchdog/wd_utils.h index cdf829c63..414376a16 100644 --- a/src/include/watchdog/wd_utils.h +++ b/src/include/watchdog/wd_utils.h @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2018 PgPool Global Development Group + * Copyright (c) 2003-2022 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -52,6 +52,7 @@ extern int wd_is_upper_ok(char *server_list); extern bool wd_is_ip_exists(char *ip); extern bool wd_get_ping_result(char *hostname, int exit_status, int outfd); extern pid_t wd_issue_ping_command(char *hostname, int *outfd); +extern pid_t wd_trusted_server_command(char *hostname); /* wd_if.c */ extern List *get_all_local_ips(void); diff --git a/src/sample/pgpool.conf.sample-stream b/src/sample/pgpool.conf.sample-stream index 87678c7ec..b87bb8da2 100644 --- a/src/sample/pgpool.conf.sample-stream +++ b/src/sample/pgpool.conf.sample-stream @@ -654,9 +654,11 @@ backend_clustering_mode = 'streaming_replication' # to confirm network connection # (hostA,hostB,hostC,...) # (change requires restart) -#ping_path = '/bin' - # ping command path - # (change requires restart) + +#trusted_server_command = 'ping -q -c3 %h' + # Command to excute when communicate trusted server. + # Special values: + # %h = host name specified by trusted_servers # - Watchdog communication Settings - @@ -718,6 +720,10 @@ hostname0 = '' # arping command # (change requires restart) +#ping_path = '/bin' + # ping command path + # (change requires restart) + # - Behaivor on escalation Setting - #clear_memqcache_on_escalation = on diff --git a/src/test/regression/tests/036.trusted_servers/test.sh b/src/test/regression/tests/036.trusted_servers/test.sh new file mode 100755 index 000000000..5679dd3e6 --- /dev/null +++ b/src/test/regression/tests/036.trusted_servers/test.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------- +# test script for trusted_server_command +# +source $TESTLIBS +TESTDIR=testdir +PSQL=$PGBIN/psql + +# set trusted_servers and trusted_server_command +function set_param +{ + n=0 + while [ $n -lt 2 ] + do + echo "trusted_servers = 'localhost'" >> pgpool$n/etc/pgpool.conf + echo "trusted_server_command = 'ping -q -c3 %h'" >> pgpool$n/etc/pgpool.conf + n=`expr $n + 1` + done +} + +# wait for watchdog starting up by looking for "lifecheck started" in +# the pgpool.log. argument: $log: absolute path to the pgpool.log. +function wait_for_watchdog_startup +{ + while : + do + grep "lifecheck started" $log >/dev/null + if [ $? = 0 ];then + break; + fi + sleep 1 + done +} + + +#------------------------------------------------------------------- +dir=`pwd` + +failed=false +export PCPPASSFILE=$dir/$TESTDIR/pgpool0/pcppass + +cd $dir +rm -fr $TESTDIR +mkdir $TESTDIR +cd $TESTDIR + +$WATCHDOG_SETUP -wn 2 || exit 1 + +set_param + +./startall + +cd pgpool0 +source ./bashrc.ports +export PGPORT=$PGPOOL_PORT +cd .. + +echo -n "waiting for watchdog node 0 starting up... " +log=$dir/$TESTDIR/pgpool0/log/pgpool.log +wait_for_watchdog_startup $log +echo "done." + +sleep 10 + +grep "watchdog failed to ping host:" $log >/dev/null +if [ $? -eq 0 ];then + failed=true +fi + +./shutdownall + +if [ $failed = "true" ];then + exit 1 +fi +exit 0 diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index 268c1748f..acb32c726 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -820,6 +820,11 @@ get_config(int *nrows) StrNCpy(status[i].desc, "upper server list to observe connection", POOLCONFIG_MAXDESCLEN); i++; + StrNCpy(status[i].name, "trusted_server_command", POOLCONFIG_MAXNAMELEN); + snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->trusted_server_command); + StrNCpy(status[i].desc, "command executed when upper servers are observed", POOLCONFIG_MAXDESCLEN); + i++; + StrNCpy(status[i].name, "delegate_ip", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->delegate_ip); StrNCpy(status[i].desc, "delegate IP address of leader pgpool", POOLCONFIG_MAXDESCLEN); diff --git a/src/watchdog/wd_lifecheck.c b/src/watchdog/wd_lifecheck.c index e62ca0142..c399128b4 100644 --- a/src/watchdog/wd_lifecheck.c +++ b/src/watchdog/wd_lifecheck.c @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2020 PgPool Global Development Group + * Copyright (c) 2003-2022 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -72,7 +72,6 @@ typedef struct WdUpstreamConnectionData char *hostname; /* host name of server */ pid_t pid; /* pid of ping process */ bool reachable; /* true if last ping was successful */ - int outputfd; /* pipe fd linked to output of ping process */ } WdUpstreamConnectionData; @@ -168,9 +167,8 @@ reaper(void) if (server) { - server->reachable = wd_get_ping_result(server->hostname, status, server->outputfd); + server->reachable = (status == 0); server->pid = 0; - close(server->outputfd); } else wd_reaper_lifecheck(pid, status); @@ -1118,7 +1116,7 @@ wd_ping_all_server(void) WdUpstreamConnectionData *server = (WdUpstreamConnectionData *) lfirst(lc); if (server->pid <= 0) - server->pid = wd_issue_ping_command(server->hostname, &server->outputfd); + server->pid = wd_trusted_server_command(server->hostname); if (server->pid > 0) ping_process++; @@ -1135,15 +1133,19 @@ wd_ping_all_server(void) if (server) { ping_process--; - server->reachable = wd_get_ping_result(server->hostname, status, server->outputfd); + server->reachable = (status == 0); server->pid = 0; - close(server->outputfd); if (server->reachable) { /* one reachable server is all we need */ POOL_SETMASK(&UnBlockSig); return true; } + if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0) + { + ereport(WARNING, + (errmsg("watchdog failed to ping host: \"%s\"", server->hostname))); + } } else { diff --git a/src/watchdog/wd_ping.c b/src/watchdog/wd_ping.c index 6e758c448..89bbe0b3f 100644 --- a/src/watchdog/wd_ping.c +++ b/src/watchdog/wd_ping.c @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2020 PgPool Global Development Group + * Copyright (c) 2003-2022 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "pool.h" #include "utils/elog.h" #include "pool_config.h" @@ -154,6 +156,97 @@ wd_issue_ping_command(char *hostname, int *outfd) return pid; } +/* + * execute specified command for trusted servers and return the + * pid of the process. + */ +pid_t +wd_trusted_server_command(char *hostname) +{ + int status; + int pid; + StringInfoData exec_cmd_data; + StringInfo exec_cmd = &exec_cmd_data; + char *command_line = pstrdup(pool_config->trusted_server_command); + + initStringInfo(exec_cmd); + + while (*command_line) + { + if (*command_line == '%') + { + if (*(command_line + 1)) + { + char val = *(command_line + 1); + + switch (val) + { + case 'h': /* trusted server host name */ + appendStringInfoString(exec_cmd, hostname); + break; + + case '%': /* escape */ + appendStringInfoString(exec_cmd, "%"); + break; + + default: /* ignore */ + break; + } + command_line++; + } + } + else + appendStringInfoChar(exec_cmd, *command_line); + + command_line++; + } + + pid = fork(); + if (pid == -1) + { + ereport(WARNING, + (errmsg("watchdog failed to ping host\"%s\"", hostname), + errdetail("fork() failed. reason: %m"))); + return -1; + } + if (pid == 0) + { + /* CHILD */ + int fd; + + on_exit_reset(); + SetProcessGlobalVariables(PT_WATCHDOG_UTILITY); + if (strlen(exec_cmd->data) != 0) + elog(DEBUG1, "trusted_server_command: %s", exec_cmd->data); + + fd = open("/dev/null", O_RDWR); + if (fd < 0) + { + ereport(ERROR, + (errmsg("failed to open \"/dev/null\""), + errdetail("%m"))); + } + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + if (strlen(exec_cmd->data) != 0) + { + status = system(exec_cmd->data); + } + pfree(exec_cmd->data); + + if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0) + { + exit(EXIT_FAILURE); + } + exit(0); + } + + return pid; +} + /* * The function is helper function and can be used with the * wd_issue_ping_command() function to identify if the ping command -- 2.39.5