Add trusted_server_command parameter
authorTakuma Hoshiai <takuma.hoshiai@gmail.com>
Fri, 4 Nov 2022 02:07:09 +0000 (11:07 +0900)
committerTakuma Hoshiai <takuma.hoshiai@gmail.com>
Fri, 4 Nov 2022 02:07:09 +0000 (11:07 +0900)
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
doc/src/sgml/watchdog.sgml
src/config/pool_config_variables.c
src/include/pool_config.h
src/include/watchdog/wd_utils.h
src/sample/pgpool.conf.sample-stream
src/test/regression/tests/036.trusted_servers/test.sh [new file with mode: 0755]
src/utils/pool_process_reporting.c
src/watchdog/wd_lifecheck.c
src/watchdog/wd_ping.c

index f212d105a082f5d7f56a3c67d05727f23a9adc30..50556a193232c51e1eeaaf46ecbf7f10d4a697a0 100644 (file)
     </listitem>
    </varlistentry>
 
-   <varlistentry id="guc-ping-path" xreflabel="ping_path">
-    <term><varname>ping_path</varname> (<type>string</type>)
+   <varlistentry id="guc-trusted-server-command" xreflabel="trusted_server_command">
+    <term><varname>trusted_server_command</varname> (<type>string</type>)
      <indexterm>
       <!--
-      <primary><varname>ping_path</varname> configuration parameter</primary>
+      <primary><varname>trusted_server_command</varname> configuration parameter</primary>
       -->
-      <primary><varname>ping_path</varname>設定パラメータ</primary>
+      <primary><varname>trusted_server_command</varname>設定パラメータ</primary>
      </indexterm>
     </term>
     <listitem>
      <para>
       <!--
-      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 <literal>"/bin"</literal> or such directory.
+      Specifies a user command to run when <productname>Pgpool-II</productname> check
+      that trusted servers respond to ping. Any %h in the string is replaced by each host
+      name specified <varname>trusted_servers</varname>. Default is
+      <literal>ping -q -c3 %h</literal>.
       -->
-      上位サーバへの接続監視に利用するpingコマンドのパスを指定します。
-      <literal>"/bin"</literal>のようにパスだけを指定します。
+      信頼できるサーバのping応答を確認するユーザコマンドを指定します。
+      %hは<varname>trusted_servers</varname>で指定された各ホスト名に置換されます。
+      デフォルトは<literal>ping -q -c3 %h</literal>です。
      </para>
      <para>
       <!--
     </listitem>
    </varlistentry>
 
+   <varlistentry id="guc-ping-path" xreflabel="ping_path">
+    <term><varname>ping_path</varname> (<type>string</type>)
+     <indexterm>
+      <!--
+      <primary><varname>ping_path</varname> configuration parameter</primary>
+      -->
+      <primary><varname>ping_path</varname>設定パラメータ</primary>
+     </indexterm>
+    </term>
+    <listitem>
+     <para>
+      <!--
+      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 <literal>"/bin"</literal> or such directory.
+      -->
+      仮想IPの起動を確認するために利用するpingコマンドのパスを指定します。
+      <literal>"/bin"</literal>のようにパスだけを指定します。
+     </para>
+     <para>
+      <!--
+      This parameter can only be set at server start.
+      -->
+      このパラメータは、サーバ起動時にのみ設定できます。
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </sect2>
 
index e8d5f6d7f0828043a18aa81bf068945b462276f1..fdd23224dcdd604fb5aa64017ffb807a97780bc4 100644 (file)
@@ -232,17 +232,18 @@ pgpool_port2 = 9999
     </listitem>
    </varlistentry>
 
-   <varlistentry id="guc-ping-path" xreflabel="ping_path">
-    <term><varname>ping_path</varname> (<type>string</type>)
+   <varlistentry id="guc-trusted-server-command" xreflabel="trusted_server_command">
+    <term><varname>trusted_server_command</varname> (<type>string</type>)
      <indexterm>
-      <primary><varname>ping_path</varname> configuration parameter</primary>
+      <primary><varname>trusted_server_command</varname> configuration parameter</primary>
      </indexterm>
     </term>
     <listitem>
      <para>
-      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 <literal>"/bin"</literal> or such directory.
+      Specifies a user command to run when <productname>Pgpool-II</productname> check
+      that trusted servers respond to ping. Any %h in the string is replaced by each host
+      name specified <varname>trusted_servers</varname>. Default is
+      <literal>ping -q -c3 %h</literal>.
      </para>
      <para>
       This parameter can only be set at server start.
@@ -398,6 +399,23 @@ pgpool_port2 = 9999
     </listitem>
    </varlistentry>
 
+   <varlistentry id="guc-ping-path" xreflabel="ping_path">
+    <term><varname>ping_path</varname> (<type>string</type>)
+     <indexterm>
+      <primary><varname>ping_path</varname> configuration parameter</primary>
+     </indexterm>
+    </term>
+    <listitem>
+     <para>
+      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 <literal>"/bin"</literal> or such directory.
+     </para>
+     <para>
+      This parameter can only be set at server start.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </sect2>
 
index fe1bfd7181e72e21bf7dfb968d22a7f2e1f349b2..25d7ac29ef0aed302d9d41da8d6f7a1164452114 100644 (file)
@@ -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.",
index b6967cf281e917aad8c3ff42770679c17b1d6fd3..142c6fab144b1ed2724da159c530a06dc02c2150 100644 (file)
@@ -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
index cdf829c63e5356066ef9bd35046457e46ab0b794..414376a16def75089af64e57db57bcbbd19f03d7 100644 (file)
@@ -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);
index 87678c7ec052725dceffec087cd39ec902fcb76e..b87bb8da25a0cdc73f7ce3e08918f291ea645c3a 100644 (file)
@@ -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 (executable)
index 0000000..5679dd3
--- /dev/null
@@ -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
index 268c1748fe57b3e7f44333a38195c7f00d7fa624..acb32c7269f8e13465146662dfc5f7b1dd7a6874 100644 (file)
@@ -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);
index e62ca01428cb7d82bc1140cf7c03e9b277664de3..c399128b4c5f2bd15cdf6b4ea2840ce36b4ef321 100644 (file)
@@ -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
                        {
index 6e758c4480483e57307e409572020633999dfc41..89bbe0b3f3f0b2b2a2783e6d6081257c873a1c94 100644 (file)
@@ -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"
@@ -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