[MINOR] checks: add PostgreSQL health check
I have written a small patch to enable a correct PostgreSQL health check
It works similar to mysql-check with the very same parameters.
E.g.:
listen pgsql 127.0.0.1:5432
mode tcp
option pgsql-check user pgsql
server masterdb pgsql.server.com:5432 check inter 10000
diff --git a/doc/configuration.txt b/doc/configuration.txt
index cc4ecad..bb25448 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -993,6 +993,7 @@
option log-separate-errors (*) X X X -
option logasap (*) X X X -
option mysql-check X - X X
+option pgsql-check X - X X
option nolinger (*) X X X X
option originalto X X X X
option persist (*) X - X X
@@ -3266,7 +3267,8 @@
server apache1 192.168.1.1:443 check port 80
See also : "option ssl-hello-chk", "option smtpchk", "option mysql-check",
- "http-check" and the "check", "port" and "inter" server options.
+ "option pgsql-check", "http-check" and the "check", "port" and
+ "inter" server options.
option httpclose
@@ -3540,6 +3542,20 @@
See also: "option httpchk"
+option pgsql-check [ user <username> ]
+ Use PostgreSQL health checks for server testing
+ May be used in sections : defaults | frontend | listen | backend
+ yes | no | yes | yes
+ Arguments :
+ user <username> This is the username which will be used when connecting
+ to PostgreSQL server.
+
+ The check sends a PostgreSQL StartupMessage and waits for either
+ Authentication request or ErrorResponse message. It is a basic but useful
+ test which does not produce error nor aborted connect on the server.
+ This check is identical with the "mysql-check".
+
+ See also: "option httpchk"
option nolinger
no option nolinger
@@ -6457,8 +6473,8 @@
"port" parameter, the source address using the "source" address, and the
interval and timers using the "inter", "rise" and "fall" parameters. The
request method is define in the backend using the "httpchk", "smtpchk",
- "mysql-check" and "ssl-hello-chk" options. Please refer to those options and
- parameters for more information.
+ "mysql-check", "pgsql-check" and "ssl-hello-chk" options. Please refer to
+ those options and parameters for more information.
Supported in default-server: No
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 8da98a6..7a3276e 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -149,6 +149,8 @@
#define PR_O2_EXP_TYPE 0x03800000 /* mask for http-check expect type */
#define PR_O2_EXP_INV 0x04000000 /* http-check expect !<rule> */
#define PR_O2_COOK_PSV 0x08000000 /* cookie ... preserve */
+
+#define PR_O2_PGSQL_CHK 0x10000000 /* use PGSQL check for server health */
/* end of proxy->options2 */
/* bits for sticking rules */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 28eb1ca..dd266af 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3312,6 +3312,7 @@
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
+ curproxy->options2 &= ~PR_O2_PGSQL_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options |= PR_O_HTTP_CHK;
if (!*args[2]) { /* no argument */
@@ -3344,6 +3345,7 @@
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
+ curproxy->options2 &= ~PR_O2_PGSQL_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options2 |= PR_O2_SSL3_CHK;
}
@@ -3354,6 +3356,7 @@
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
+ curproxy->options2 &= ~PR_O2_PGSQL_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
curproxy->options |= PR_O_SMTP_CHK;
@@ -3374,6 +3377,69 @@
}
}
}
+ else if (!strcmp(args[1], "pgsql-check")) {
+ /* use PostgreSQL request to check servers' health */
+ if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
+ err_code |= ERR_WARN;
+
+ free(curproxy->check_req);
+ curproxy->check_req = NULL;
+ curproxy->options &= ~PR_O_HTTP_CHK;
+ curproxy->options &= ~PR_O_SMTP_CHK;
+ curproxy->options2 &= ~PR_O2_SSL3_CHK;
+ curproxy->options2 &= ~PR_O2_LDAP_CHK;
+ curproxy->options2 &= ~PR_O2_MYSQL_CHK;
+ curproxy->options2 |= PR_O2_PGSQL_CHK;
+
+ if (*(args[2])) {
+ int cur_arg = 2;
+
+ while (*(args[cur_arg])) {
+ if (strcmp(args[cur_arg], "user") == 0) {
+ char * packet;
+ uint32_t packet_len;
+ uint32_t pv;
+
+ /* suboption header - needs additional argument for it */
+ if (*(args[cur_arg+1]) == 0) {
+ Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
+ file, linenum, args[0], args[1], args[cur_arg]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
+ packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
+ pv = htonl(0x30000); /* protocol version 3.0 */
+
+ packet = (char*) calloc(1, packet_len);
+
+ memcpy(packet + 4, &pv, 4);
+
+ /* copy "user" */
+ memcpy(packet + 8, "user", 4);
+
+ /* copy username */
+ memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
+
+ free(curproxy->check_req);
+ curproxy->check_req = packet;
+ curproxy->check_len = packet_len;
+
+ packet_len = htonl(packet_len);
+ memcpy(packet, &packet_len, 4);
+ cur_arg += 2;
+ } else {
+ /* unknown suboption - catchall */
+ Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
+ file, linenum, args[0], args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ } /* end while loop */
+ }
+ }
+
else if (!strcmp(args[1], "mysql-check")) {
/* use MYSQL request to check servers' health */
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
@@ -3385,6 +3451,7 @@
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_LDAP_CHK;
+ curproxy->options2 &= ~PR_O2_PGSQL_CHK;
curproxy->options2 |= PR_O2_MYSQL_CHK;
/* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
@@ -3454,6 +3521,7 @@
curproxy->options &= ~PR_O_SMTP_CHK;
curproxy->options2 &= ~PR_O2_SSL3_CHK;
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
+ curproxy->options2 &= ~PR_O2_PGSQL_CHK;
curproxy->options2 |= PR_O2_LDAP_CHK;
curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
diff --git a/src/checks.c b/src/checks.c
index a23fd41..ee0b97b 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -747,6 +747,7 @@
(s->proxy->options & PR_O_SMTP_CHK) ||
(s->proxy->options2 & PR_O2_SSL3_CHK) ||
(s->proxy->options2 & PR_O2_MYSQL_CHK) ||
+ (s->proxy->options2 & PR_O2_PGSQL_CHK) ||
(s->proxy->options2 & PR_O2_LDAP_CHK)) {
int ret;
const char *check_req = s->proxy->check_req;
@@ -1001,6 +1002,22 @@
else
set_server_check_status(s, HCHK_STATUS_L7STS, desc);
}
+ else if (s->proxy->options2 & PR_O2_PGSQL_CHK) {
+ if (!done && s->check_data_len < 9)
+ goto wait_more_data;
+
+ if (s->check_data[0] == 'R') {
+ set_server_check_status(s, HCHK_STATUS_L7OKD, "PostgreSQL server is ok");
+ }
+ else {
+ if ((s->check_data[0] == 'E') && (s->check_data[5]!=0) && (s->check_data[6]!=0))
+ desc = &s->check_data[6];
+ else
+ desc = "PostgreSQL unknown error";
+
+ set_server_check_status(s, HCHK_STATUS_L7STS, desc);
+ }
+ }
else if (s->proxy->options2 & PR_O2_MYSQL_CHK) {
if (!done && s->check_data_len < 5)
goto wait_more_data;