[MEDIUM] add the "fail" condition to monitor requests

Under certain circumstances, it is very useful to be able to fail some
monitor requests. One specific case is when the number of servers in
the backend falls below a certain level. The new "monitor fail" construct
followed by either "if"/"unless" <condition> makes it possible to specify
ACL-based conditions which will make the monitor return 503 instead of
200. Any number of conditions can be passed. Another use may be to limit
the requests to local networks only.
This commit is contained in:
Willy Tarreau
2007-11-30 20:51:32 +01:00
parent a9d3c1e6a3
commit b80c230f41
4 changed files with 59 additions and 0 deletions

View File

@ -168,6 +168,7 @@ struct proxy {
struct uri_auth *uri_auth; /* if non-NULL, the (list of) per-URI authentications */
char *monitor_uri; /* a special URI to which we respond with HTTP/200 OK */
int monitor_uri_len; /* length of the string above. 0 if unused */
struct list mon_fail_cond; /* list of conditions to fail monitoring requests (chained) */
struct timeval clitimeout; /* client I/O timeout (in milliseconds) */
struct timeval srvtimeout; /* server I/O timeout (in milliseconds) */
struct timeval contimeout; /* connect timeout (in milliseconds) */

View File

@ -564,6 +564,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
LIST_INIT(&curproxy->pendconns);
LIST_INIT(&curproxy->acl);
LIST_INIT(&curproxy->block_cond);
LIST_INIT(&curproxy->mon_fail_cond);
LIST_INIT(&curproxy->switching_rules);
/* Timeouts are defined as -1, so we cannot use the zeroed area
@ -1305,6 +1306,38 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
return -1;
}
}
else if (!strcmp(args[0], "monitor")) {
if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
return 0;
if (strcmp(args[1], "fail") == 0) {
/* add a condition to fail monitor requests */
int pol = ACL_COND_NONE;
struct acl_cond *cond;
if (!strcmp(args[2], "if"))
pol = ACL_COND_IF;
else if (!strcmp(args[2], "unless"))
pol = ACL_COND_UNLESS;
if (pol == ACL_COND_NONE) {
Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
file, linenum, args[0], args[1]);
return -1;
}
if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
file, linenum, args[0], args[1]);
return -1;
}
LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
}
else {
Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
return -1;
}
}
#ifdef TPROXY
else if (!strcmp(args[0], "transparent")) {
/* enable transparent proxy connections */

View File

@ -658,6 +658,12 @@ void deinit(void)
free(cond);
}
list_for_each_entry_safe(cond, condb, &p->mon_fail_cond, list) {
LIST_DEL(&cond->list);
prune_acl_cond(cond);
free(cond);
}
for (exp = p->req_exp; exp != NULL; ) {
if (exp->preg)
regfree((regex_t *)exp->preg);

View File

@ -1637,7 +1637,26 @@ int process_cli(struct session *t)
/*
* We have found the monitor URI
*/
struct acl_cond *cond;
cur_proxy = t->fe;
t->flags |= SN_MONITOR;
/* Check if we want to fail this monitor request or not */
list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) {
int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ);
if (cond->pol == ACL_COND_UNLESS)
ret = !ret;
if (ret) {
/* we fail this request, let's return 503 service unavail */
txn->status = 503;
client_retnclose(t, error_message(t, HTTP_ERR_503));
goto return_prx_cond;
}
}
/* nothing to fail, let's reply normaly */
txn->status = 200;
client_retnclose(t, &http_200_chunk);
goto return_prx_cond;