|
|
ede1e2 |
From 7b952299ea7dbe17289d5f34d5c2867a8077fb19 Mon Sep 17 00:00:00 2001
|
|
|
ede1e2 |
From: Ryan O'Hara <rohara@redhat.com>
|
|
|
ede1e2 |
Date: Thu, 28 Feb 2019 08:22:45 -0600
|
|
|
ede1e2 |
Subject: [PATCH] BUG/MEDIUM: tcp-check: single connect rule can't detect DOWN
|
|
|
ede1e2 |
servers
|
|
|
ede1e2 |
|
|
|
ede1e2 |
When tcpcheck is used to do TCP port monitoring only and the script is
|
|
|
ede1e2 |
composed by a single "tcp-check connect" rule (whatever port and ssl
|
|
|
ede1e2 |
options enabled), then the server can't be seen as DOWN.
|
|
|
ede1e2 |
Simple configuration to reproduce:
|
|
|
ede1e2 |
|
|
|
ede1e2 |
backend b
|
|
|
ede1e2 |
[...]
|
|
|
ede1e2 |
option tcp-check
|
|
|
ede1e2 |
tcp-check connect
|
|
|
ede1e2 |
server s1 127.0.0.1:22 check
|
|
|
ede1e2 |
|
|
|
ede1e2 |
The main reason for this issue is that the piece of code which validates
|
|
|
ede1e2 |
that we're not at the end of the chained list (of rules) prevents
|
|
|
ede1e2 |
executing the validation of the establishment of the TCP connection.
|
|
|
ede1e2 |
Since validation is not executed, the rule is terminated and the report
|
|
|
ede1e2 |
says no errors were encountered, hence the server is UP all the time.
|
|
|
ede1e2 |
|
|
|
ede1e2 |
The workaround is simple: move the connection validation outsied the
|
|
|
ede1e2 |
CONNECT rule processing loop, into the main function.
|
|
|
ede1e2 |
That way, if the connection status is not CONNECTED, then HAProxy will
|
|
|
ede1e2 |
now add more time to wait for it. If the time is expired, an error is
|
|
|
ede1e2 |
now well reported.
|
|
|
ede1e2 |
---
|
|
|
ede1e2 |
src/checks.c | 19 +++++++++++++++++++
|
|
|
ede1e2 |
1 file changed, 19 insertions(+)
|
|
|
ede1e2 |
|
|
|
ede1e2 |
diff --git a/src/checks.c b/src/checks.c
|
|
|
ede1e2 |
index 27a23b21..f280367b 100644
|
|
|
ede1e2 |
--- a/src/checks.c
|
|
|
ede1e2 |
+++ b/src/checks.c
|
|
|
ede1e2 |
@@ -2246,6 +2246,25 @@ static void tcpcheck_main(struct connection *conn)
|
|
|
ede1e2 |
} /* end expect */
|
|
|
ede1e2 |
} /* end loop over double chained step list */
|
|
|
ede1e2 |
|
|
|
ede1e2 |
+ /* don't do anything until the connection is established */
|
|
|
ede1e2 |
+ if (!(conn->flags & CO_FL_CONNECTED)) {
|
|
|
ede1e2 |
+ /* update expire time, should be done by process_chk */
|
|
|
ede1e2 |
+ /* we allow up to min(inter, timeout.connect) for a connection
|
|
|
ede1e2 |
+ * to establish but only when timeout.check is set
|
|
|
ede1e2 |
+ * as it may be to short for a full check otherwise
|
|
|
ede1e2 |
+ */
|
|
|
ede1e2 |
+ while (tick_is_expired(t->expire, now_ms)) {
|
|
|
ede1e2 |
+ int t_con;
|
|
|
ede1e2 |
+
|
|
|
ede1e2 |
+ t_con = tick_add(t->expire, s->proxy->timeout.connect);
|
|
|
ede1e2 |
+ t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
|
|
|
ede1e2 |
+
|
|
|
ede1e2 |
+ if (s->proxy->timeout.check)
|
|
|
ede1e2 |
+ t->expire = tick_first(t->expire, t_con);
|
|
|
ede1e2 |
+ }
|
|
|
ede1e2 |
+ return;
|
|
|
ede1e2 |
+ }
|
|
|
ede1e2 |
+
|
|
|
ede1e2 |
/* We're waiting for some I/O to complete, we've reached the end of the
|
|
|
ede1e2 |
* rules, or both. Do what we have to do, otherwise we're done.
|
|
|
ede1e2 |
*/
|
|
|
ede1e2 |
--
|
|
|
ede1e2 |
2.20.1
|
|
|
ede1e2 |
|