mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-05-04 20:46:11 +02:00
MEDIUM: tcpcheck: Add parsing support for healthcheck sections
tcpcheck_ruleset struct was extended to host a config part that will be used
for healthcheck sections. This config part is mainly used to store element
for the server's tcpcheck part.
When a healthcheck section is parsed, a ruleset is created with its name
(which must be unique). "*healthcheck-{NAME}" is used for these ruleset. So
it is not possible to mix them with regular rulesets.
For now, in a healthcheck section, the type must be defined, based on the
options name (tcp-check, httpchk, redis-check...). In addition, several
"tcp-check" or "http-check" rules can be specified, depending on the
healthcheck type.
This commit is contained in:
parent
9e92352967
commit
275bd9ec03
@ -238,6 +238,12 @@ struct tcpcheck_ruleset {
|
||||
struct list rules; /* the list of tcpcheck_rule */
|
||||
unsigned int flags; /* flags applied to the rules */
|
||||
struct ebpt_node node; /* node in the shared tree */
|
||||
struct {
|
||||
struct list preset_vars; /* The list of variable to preset for healthcheck sections */
|
||||
unsigned int flags; /* TCPCHECK_FL_* for healthcheck sections */
|
||||
const char *file; /* file where the section appears */
|
||||
int line; /* line where the section appears */
|
||||
} conf; /* config information */
|
||||
};
|
||||
|
||||
struct tcpcheck {
|
||||
|
||||
241
src/tcpcheck.c
241
src/tcpcheck.c
@ -52,7 +52,7 @@
|
||||
#include <haproxy/log.h>
|
||||
#include <haproxy/net_helper.h>
|
||||
#include <haproxy/protocol.h>
|
||||
#include <haproxy/proxy-t.h>
|
||||
#include <haproxy/proxy.h>
|
||||
#include <haproxy/regex.h>
|
||||
#include <haproxy/sample.h>
|
||||
#include <haproxy/server.h>
|
||||
@ -72,6 +72,8 @@
|
||||
/* Global tree to share all tcp-checks */
|
||||
struct eb_root shared_tcpchecks = EB_ROOT;
|
||||
|
||||
/* Proxy used during parsing of healtcheck sections */
|
||||
struct proxy *tcpchecks_proxy = NULL;
|
||||
|
||||
DECLARE_TYPED_POOL(pool_head_tcpcheck_rule, "tcpcheck_rule", struct tcpcheck_rule);
|
||||
|
||||
@ -314,6 +316,7 @@ struct tcpcheck_ruleset *create_tcpcheck_ruleset(const char *name)
|
||||
}
|
||||
rs->flags = 0;
|
||||
LIST_INIT(&rs->rules);
|
||||
LIST_INIT(&rs->conf.preset_vars);
|
||||
ebis_insert(&shared_tcpchecks, &rs->node);
|
||||
return rs;
|
||||
}
|
||||
@ -5669,7 +5672,241 @@ int proxy_parse_tcp_check_opt(char **args, int cur_arg, struct proxy *curpx, con
|
||||
|
||||
out:
|
||||
return err_code;
|
||||
}
|
||||
|
||||
int cfg_parse_healthchecks(const char *file, int linenum, char **args, int kwm)
|
||||
{
|
||||
static struct tcpcheck_ruleset *cur_rs = NULL;
|
||||
int rc, err_code = 0;
|
||||
char *errmsg = NULL;
|
||||
|
||||
if (strcmp(args[0], "healthcheck") == 0) { /* new healthcheck section */
|
||||
struct tcpcheck_ruleset *rs = NULL;
|
||||
const char *err;
|
||||
|
||||
if (!tcpchecks_proxy) {
|
||||
tcpchecks_proxy = alloc_new_proxy("TCPCHECKS", PR_CAP_BE|PR_CAP_INT, &errmsg);
|
||||
if (!tcpchecks_proxy) {
|
||||
ha_alert("parsing [%s:%d] : %s.\n", file, linenum, errmsg);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
tcpchecks_proxy->options2 &= ~PR_O2_CHK_ANY;
|
||||
tcpchecks_proxy->tcpcheck.flags = 0;
|
||||
tcpchecks_proxy->tcpcheck.rs = NULL;
|
||||
|
||||
if (!*args[1]) {
|
||||
ha_alert("parsing [%s:%d] : missing name for healthcheck section.\n", file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = invalid_char(args[1]);
|
||||
if (err) {
|
||||
ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
|
||||
file, linenum, *err, args[0], args[1]);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
chunk_printf(&trash, "*healthcheck-%s", args[1]);
|
||||
rs = find_tcpcheck_ruleset(b_orig(&trash));
|
||||
if (rs != NULL) {
|
||||
ha_alert("parsing [%s:%d] : healthcheck section '%s' already defined at %s:%d.\n",
|
||||
file, linenum, args[1], rs->conf.file, rs->conf.line);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cur_rs = create_tcpcheck_ruleset(b_orig(&trash));
|
||||
if (cur_rs == NULL) {
|
||||
ha_alert("parsing [%s:%d] : failed to allocate healthcheck %s.\n", file, linenum, args[1]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
cur_rs->conf.file = strdup(file);
|
||||
cur_rs->conf.line = linenum;
|
||||
|
||||
tcpchecks_proxy->tcpcheck.rs = cur_rs;
|
||||
}
|
||||
else if (strcmp(args[0], "type") == 0) {
|
||||
if (*(args[1]) == '\0') {
|
||||
ha_alert("parsing [%s:%d] : '%s' expects a healthcheck type.\n",
|
||||
file, linenum, args[0]);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tcpchecks_proxy->options2 & PR_O2_CHK_ANY) {
|
||||
ha_alert("parsing [%s:%d] : healthcheck type already defined.\n",
|
||||
file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(args[1], "tcp-check") != 0 && (tcpchecks_proxy->tcpcheck.flags & TCPCHK_FL_UNUSED_TCP_RS)) {
|
||||
ha_alert("parsing [%s:%d] : cannot set '%s' type with 'tcp-check' rules\n",
|
||||
file, linenum, args[1]);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(args[1], "httpchk") != 0 && (tcpchecks_proxy->tcpcheck.flags & TCPCHK_FL_UNUSED_HTTP_RS)) {
|
||||
ha_alert("parsing [%s:%d] : cannot set '%s' type with 'http-check' rules\n",
|
||||
file, linenum, args[1]);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(args[1], "tcp-check") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_TCP_CHK;
|
||||
err_code |= do_parse_tcp_check_opt(args, 2, tcpchecks_proxy, cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "httpchk") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_HTTP_CHK;
|
||||
err_code |= do_parse_httpchk_opt(args, 2, tcpchecks_proxy, cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "ssl-hello-chk") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_SSL3_CHK;
|
||||
err_code |= do_parse_ssl_hello_chk_opt(args, 2, tcpchecks_proxy, cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "smtpchk") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_SMTP_CHK;
|
||||
err_code |= do_parse_smtpchk_opt(args, 2, tcpchecks_proxy, cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "pgsql-check") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_PGSQL_CHK;
|
||||
err_code |= do_parse_pgsql_check_opt(args, 2, tcpchecks_proxy,cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "redis-check") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_REDIS_CHK;
|
||||
err_code |= do_parse_redis_check_opt(args, 2, tcpchecks_proxy,cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "mysql-check") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_MYSQL_CHK;
|
||||
err_code |= do_parse_mysql_check_opt(args, 2, tcpchecks_proxy,cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "ldap-check") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_LDAP_CHK;
|
||||
err_code |= do_parse_ldap_check_opt(args, 2, tcpchecks_proxy, cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[1], "spop-check") == 0) {
|
||||
cur_rs->flags |= TCPCHK_RULES_SPOP_CHK;
|
||||
err_code |= do_parse_spop_check_opt(args, 2, tcpchecks_proxy, cur_rs, file, linenum);
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
ha_alert("parsing [%s:%d] : unknown healthcheck type '%s (expects 'tcp-check', 'httpchk', 'ssl-hello-chk', "
|
||||
"'smtpchk', 'pgsql-check', 'redis-check', 'mysql-check', 'ldap-check', 'spop-check').\n",
|
||||
file, linenum, args[1]);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[0], "tcp-check") == 0) {
|
||||
if ((tcpchecks_proxy->options2 & PR_O2_CHK_ANY) &&
|
||||
(cur_rs->flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_TCP_CHK) {
|
||||
ha_alert("parsing [%s:%d] : unable to configure 'tcp-check' rule for '%s' healthcheck\n",
|
||||
file, linenum, tcpcheck_ruleset_type_to_str(cur_rs));
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tcpchecks_proxy->tcpcheck.flags & TCPCHK_FL_UNUSED_HTTP_RS) {
|
||||
ha_alert("parsing [%s:%d] : cannot mix 'tcp-check' and 'http-check' rules\n",
|
||||
file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = do_parse_tcpcheck(args, tcpchecks_proxy, cur_rs, file, linenum, &errmsg);
|
||||
if (rc < 0) {
|
||||
ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
}
|
||||
else if (rc > 0) {
|
||||
ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
|
||||
err_code |= ERR_WARN;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp(args[0], "http-check") == 0) {
|
||||
if ((tcpchecks_proxy->options2 & PR_O2_CHK_ANY) &&
|
||||
(cur_rs->flags & TCPCHK_RULES_PROTO_CHK) != TCPCHK_RULES_HTTP_CHK) {
|
||||
ha_alert("parsing [%s:%d] : unable to configure 'http-check' rule for '%s' healthcheck\n",
|
||||
file, linenum, tcpcheck_ruleset_type_to_str(cur_rs));
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tcpchecks_proxy->tcpcheck.flags & TCPCHK_FL_UNUSED_TCP_RS) {
|
||||
ha_alert("parsing [%s:%d] : cannot mix 'tcp-check' and 'http-check' rules\n",
|
||||
file, linenum);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = do_parse_httpcheck(args, tcpchecks_proxy, cur_rs, file, linenum, &errmsg);
|
||||
if (rc < 0) {
|
||||
ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
|
||||
err_code |= ERR_ALERT | ERR_ABORT;
|
||||
}
|
||||
else if (rc > 0) {
|
||||
ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
|
||||
err_code |= ERR_WARN;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
free(errmsg);
|
||||
return err_code;
|
||||
}
|
||||
|
||||
int cfg_post_parse_healthchecks()
|
||||
{
|
||||
struct tcpcheck_ruleset *rs;
|
||||
int err_code = 0;
|
||||
|
||||
BUG_ON(!tcpchecks_proxy);
|
||||
rs = tcpchecks_proxy->tcpcheck.rs;
|
||||
if (!rs)
|
||||
goto out;
|
||||
|
||||
if (tcpchecks_proxy->tcpcheck.flags & TCPCHK_FL_UNUSED_TCP_RS) {
|
||||
ha_alert("parsing [%s:%d] : healthcheck section '%s' : tcp-check rules without 'type tcp-check', so the rules are ignored.\n",
|
||||
rs->conf.file, rs->conf.line, (char *)rs->node.key);
|
||||
err_code |= ERR_WARN;
|
||||
}
|
||||
|
||||
if (tcpchecks_proxy->tcpcheck.flags & TCPCHK_FL_UNUSED_HTTP_RS) {
|
||||
ha_alert("parsing [%s:%d] : healthcheck section '%s' : http-check rules without 'type http-check', so the rules are ignored.\n",
|
||||
rs->conf.file, rs->conf.line, (char *)rs->node.key);
|
||||
err_code |= ERR_WARN;
|
||||
}
|
||||
|
||||
if (!dup_tcpcheck_vars(&rs->conf.preset_vars, &tcpchecks_proxy->tcpcheck.preset_vars)) {
|
||||
ha_alert("parsing [%s:%d] : unable to duplicate preset variables for healthcheck section '%s'.\n",
|
||||
rs->conf.file, rs->conf.line, (char *)rs->node.key);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
}
|
||||
rs->conf.flags = tcpchecks_proxy->tcpcheck.flags;
|
||||
|
||||
out:
|
||||
free_tcpcheck_vars(&tcpchecks_proxy->tcpcheck.preset_vars);
|
||||
tcpchecks_proxy->options2 &= ~PR_O2_CHK_ANY;
|
||||
tcpchecks_proxy->tcpcheck.flags = 0;
|
||||
tcpchecks_proxy->tcpcheck.rs = NULL;
|
||||
return err_code;
|
||||
}
|
||||
|
||||
static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
@ -5682,3 +5919,5 @@ REGISTER_POST_PROXY_CHECK(check_proxy_tcpcheck);
|
||||
REGISTER_PROXY_DEINIT(deinit_proxy_tcpcheck);
|
||||
REGISTER_POST_DEINIT(deinit_tcpchecks);
|
||||
INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
|
||||
|
||||
REGISTER_CONFIG_SECTION("healthcheck", cfg_parse_healthchecks, cfg_post_parse_healthchecks);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user