[pgpool-hackers: 4216] Re: Proposal: Add trusted_server_command parameter
Takuma Hoshiai
hoshiai.takuma at nttcom.co.jp
Fri Oct 28 15:28:43 JST 2022
Hi,
On 2022/10/27 16:38, Takuma Hoshiai wrote:
> Hi Ishii-san,
>
> On 2022/10/27 16:20, Tatsuo Ishii wrote:
>> Hoshiai-san,
>>
>>>> Hi all,
>>>>
>>>> I create a patch about trusted_servers for v4.4.
>>>> Add new parameter 'trusted_server_command'.
>>>>
>>>> Currently, only 'ping' command is used by trusted_servers for checking
>>>> up stream
>>>> connection, and number of sending packets is hard coded. In some
>>>> cases, user maybe
>>>> want to use other command.
>>>>
>>>> The trusted_server_command allow users to any specify command.
>>>> Default is
>>>> 'ping -q -c %h' which means same as before. Pgpool-II replaces the
>>>> special
>>>> characters(%h) with the host name in trusted_servers.
>>>
>>> I have tested your patch and encountered an issue. Can you please
>>> help?
>>>
>>> I ran watchdog_setup to create a 3-pgpool-node cluster. And added
>>> following two lined to each pgpool.conf then ran ./startall.
>>>
>>> trusted_servers = 'localhost'
>>> trusted_server_command = 'ping -q -c3 %h'
>>>
>>> However the cluster did not start. I found following in the
>>> pgpool.log.
>>>
>>> ping: write error: Bad file descriptor
>>> 2022-10-27 13:35:29.855: watchdog_utility pid 326297: FATAL:
>>> watchdog failed to ping host"localhost"
>>> 2022-10-27 13:35:29.855: watchdog_utility pid 326297: DETAIL:
>>> system(ping -q -c3 localhost) failed. reason: Success
>>> 2022-10-27 13:35:29.856: life_check pid 326157: WARNING: watchdog
>>> lifecheck, failed to connect to any trusted servers
>>> 2022-10-27 13:35:29.856: life_check pid 326157: LOG: informing the
>>> node status change to watchdog
>>> 2022-10-27 13:35:29.856: life_check pid 326157: DETAIL: node id :0
>>> status = "NODE DEAD" message:"trusted server is unreachable"
>>>
>>> If I ran "ping -q -c3 localhost" manually, it works fine.
>>>
>>> $ ping -q -c3 localhost
>>> PING localhost (127.0.0.1) 56(84) bytes of data.
>>>
>>> --- localhost ping statistics ---
>>> 3 packets transmitted, 3 received, 0% packet loss, time 2034ms
>>> rtt min/avg/max/mdev = 0.082/0.087/0.095/0.005 ms
>>
>> I think wd_trusted_server_command() needs to assign appropreate fd
>> (/dev/null) to stdin, stdout and stderr. Attached is the revised
>> patch. Can you please check?
I think it's good!
But pgpool log messeges are suppressed, I fix debug and error messages
to your patch.
In addition, I add a regression test for trusted_server.
> Thank you for your suggestion. I will check it.
>
>> Best reagards,
>> --
>> Tatsuo Ishii
>> SRA OSS LLC
>> English: http://www.sraoss.co.jp/index_en/
>> Japanese:http://www.sraoss.co.jp
>>
>
> Best Regards,
>
Best Regards,
--
Takuma Hoshiai <hoshiai.takuma at nttcom.co.jp>
-------------- next part --------------
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 | 6 ++
.../regression/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 +++++++++++++++++++++-
8 files changed, 202 insertions(+), 9 deletions(-)
diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c
index fe1bfd7..c804ee1 100644
--- a/src/config/pool_config_variables.c
+++ b/src/config/pool_config_variables.c
@@ -1042,6 +1042,16 @@ static struct config_string ConfigureNamesString[] =
},
{
+ {"trusted_server_command", CFGCXT_RELOAD, WATCHDOG_CONFIG,
+ "Command to excute when communicate 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.",
CONFIG_VAR_TYPE_STRING, false, VAR_HIDDEN_IN_SHOW_ALL
diff --git a/src/include/pool_config.h b/src/include/pool_config.h
index b6967cf..142c6fa 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 cdf829c..414376a 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 87678c7..fd34eb8 100644
--- a/src/sample/pgpool.conf.sample-stream
+++ b/src/sample/pgpool.conf.sample-stream
@@ -654,6 +654,12 @@ backend_clustering_mode = 'streaming_replication'
# to confirm network connection
# (hostA,hostB,hostC,...)
# (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
+
#ping_path = '/bin'
# ping command path
# (change requires restart)
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 0000000..b3a9515
--- /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 268c174..acb32c7 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 e62ca01..b697d84 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 6e758c4..89bbe0b 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 <netdb.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
#include "pool.h"
#include "utils/elog.h"
#include "pool_config.h"
@@ -155,6 +157,97 @@ wd_issue_ping_command(char *hostname, int *outfd)
}
/*
+ * 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
* was successful */
More information about the pgpool-hackers
mailing list