Hi everybody,
Please find in attachment a patch which provides IMAP health checking.
Note that it provides also a clean application logout :)
it applies on HAProxy HEAD git.
I've tested it on my courier IMAP server and it works as expected.
You can test it with the simple conf below:
listen imap
bind 0.0.0.0:1143
mode tcp
option imapchk
server imapserver <IP>:143 check
Your feedback are welcome.
cheers
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 28e7330..a54d834 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1024,6 +1024,7 @@ option httpchk X - X X
option httpclose (*) X X X X
option httplog X X X X
option http_proxy (*) X X X X
+option imapchk X - X X
option independant-streams (*) X X X X
option ldap-check X - X X
option log-health-checks (*) X - X X
@@ -3393,8 +3394,8 @@ option httpchk <method> <uri> <version>
server apache1 192.168.1.1:443 check port 80
See also : "option ssl-hello-chk", "option smtpchk", "option mysql-check",
- "option pgsql-check", "http-check" and the "check", "port" and
- "inter" server options.
+ "option pgsql-check", "http-check", "option imapchk" and the
+ "check", "port" and "inter" server options.
option httpclose
@@ -3494,6 +3495,23 @@ no option http_proxy
See also : "option httpclose"
+option imapchk
+ Use imap health checks for server testing
+ May be used in sections : defaults | frontend | listen | backend
+ yes | no | yes | yes
+ Arguments : none
+
+ It is possible to test that an IMAP server seems opperating correctly by
+ checking the banner it sends when connecting: "* OK".
+ This check will consider the server IMAP as up and running if in the 4 first
+ characters of its banner are the ones listed above.
+
+ Example :
+ option imapchk
+
+ See also : "option httpchk"
+
+
option independant-streams
no option independant-streams
Enable or disable independant timeout processing for both directions
diff --git a/include/types/proxy.h b/include/types/proxy.h
index d0bc51c..a99343e 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -159,6 +159,7 @@ enum {
#define PR_O2_MYSQL_CHK 0x50000000 /* use MYSQL check for server health */
#define PR_O2_LDAP_CHK 0x60000000 /* use LDAP check for server health */
#define PR_O2_SSL3_CHK 0x70000000 /* use SSLv3 CLIENT_HELLO packets for server health */
+#define PR_O2_IMAP_CHK 0x80000000 /* use IMAP check for server health */
/* unused: 0x80000000 to 0xF000000, reserved for health checks */
#define PR_O2_CHK_ANY 0xF0000000 /* Mask to cover any check */
/* end of proxy->options2 */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4fed92e..ee41d0b 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3530,6 +3530,13 @@ stats_error_parsing:
memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
}
+ else if (!strcmp(args[1], "imapchk")) {
+ /* use IMAP connection to check server status */
+ free(curproxy->check_req);
+ curproxy->check_req = NULL;
+ curproxy->options2 &= ~PR_O2_CHK_ANY;
+ curproxy->options2 |= PR_O2_IMAP_CHK;
+ }
else if (!strcmp(args[1], "forwardfor")) {
int cur_arg;
diff --git a/src/checks.c b/src/checks.c
index 7a9b56d..6d6303c 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1194,8 +1194,23 @@ static int event_srv_chk_r(int fd)
}
break;
+ case PR_O2_IMAP_CHK:
+ /* IMAP welcome banner: '* OK ' */
+ if (!done && s->check_data_len < 5)
+ goto wait_more_data;
+
+ desc = ltrim(s->check_data + 4, ' ');
+ cut_crlf(desc);
+
+ if (*s->check_data == '*' && *(s->check_data + 2) == 'O' && *(s->check_data + 3) == 'K')
+ set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
+ else
+ set_server_check_status(s, HCHK_STATUS_L7STS, desc);
+
+ break;
+
default:
- /* other checks are valid if the connection succeeded anyway */
+ /* checks are valid if the connection succeeded anyway */
set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
break;
} /* switch */
@@ -1209,6 +1224,13 @@ static int event_srv_chk_r(int fd)
s->check_data_len = 0;
/* Close the connection... */
+ switch (s->proxy->options2 & PR_O2_CHK_ANY) {
+ case PR_O2_IMAP_CHK:
+ write(fd, "1 LOGOUT\r\n", strlen("1 LOGOUT\r\n"));
+ break;
+ default:
+ break;
+ }
shutdown(fd, SHUT_RDWR);
EV_FD_CLR(fd, DIR_RD);
task_wakeup(t, TASK_WOKEN_IO);