[MINOR] acl: add srv_is_up() to check that a specific server is up or not

This ACL was missing in complex setups where the status of a remote site
has to be considered in switching decisions. Until there, using a server's
status in an ACL required to have a dedicated backend, which is a bit heavy
when multiple servers have to be monitored.
This commit is contained in:
Willy Tarreau 2010-05-16 22:18:27 +02:00
parent 020534d6f7
commit 0b1cd94c8b
4 changed files with 81 additions and 1 deletions

View File

@ -6156,6 +6156,17 @@ src <ip_address>
src_port <integer>
Applies to the client's TCP source port. This has a very limited usage.
srv_is_up(<server>)
srv_is_up(<backend>/<server>)
Returns true when the designated server is UP, and false when it is either
DOWN or in maintenance mode. If <backend> is omitted, then the server is
looked up in the current backend. The function takes no arguments since it
is used as a boolean. It is mainly used to take action based on an external
status reported via a health check (eg: a geographical site's availability).
Another possible use which is more of a hack consists in using dummy servers
as boolean variables that can be enabled or disabled from the CLI, so that
rules depending on those ACLs can be tweaked in realtime.
7.5.2. Matching contents at Layer 4
-----------------------------------

View File

@ -2,7 +2,7 @@
* include/types/acl.h
* This file provides structures and types for ACLs.
*
* Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,6 +28,7 @@
#include <types/auth.h>
#include <types/proxy.h>
#include <types/server.h>
#include <types/session.h>
#include <ebmbtree.h>
@ -304,6 +305,7 @@ struct acl_expr {
union { /* optional argument of the subject (eg: header or cookie name) */
char *str;
struct userlist *ul;
struct server *srv;
} arg;
int arg_len; /* optional argument length */
struct list patterns; /* list of acl_patterns */

View File

@ -24,6 +24,7 @@
#include <proto/acl.h>
#include <proto/auth.h>
#include <proto/log.h>
#include <proto/proxy.h>
#include <ebsttree.h>
@ -1428,6 +1429,53 @@ acl_find_targets(struct proxy *p)
list_for_each_entry(acl, &p->acl, list) {
list_for_each_entry(expr, &acl->expr, list) {
if (strcmp(expr->kw->kw, "srv_is_up") == 0) {
struct proxy *px;
struct server *srv;
char *pname, *sname;
if (!expr->arg.str || !*expr->arg.str) {
Alert("proxy %s: acl %s %s(): missing server name.\n",
p->id, acl->name, expr->kw->kw);
cfgerr++;
continue;
}
pname = expr->arg.str;
sname = strrchr(pname, '/');
if (sname)
*sname++ = '\0';
else {
sname = pname;
pname = NULL;
}
px = p;
if (pname) {
px = findproxy(pname, PR_CAP_BE);
if (!px) {
Alert("proxy %s: acl %s %s(): unable to find proxy '%s'.\n",
p->id, acl->name, expr->kw->kw, pname);
cfgerr++;
continue;
}
}
srv = findserver(px, sname);
if (!srv) {
Alert("proxy %s: acl %s %s(): unable to find server '%s'.\n",
p->id, acl->name, expr->kw->kw, sname);
cfgerr++;
continue;
}
free(expr->arg.str);
expr->arg_len = 0;
expr->arg.srv = srv;
continue;
}
if (strstr(expr->kw->kw, "http_auth") == expr->kw->kw) {
if (!expr->arg.str || !*expr->arg.str) {

View File

@ -1232,6 +1232,24 @@ acl_fetch_nbsrv(struct proxy *px, struct session *l4, void *l7, int dir,
return 1;
}
/* report in test->flags a success or failure depending on the designated
* server's state. There is no match function involved since there's no pattern.
*/
static int
acl_fetch_srv_is_up(struct proxy *px, struct session *l4, void *l7, int dir,
struct acl_expr *expr, struct acl_test *test)
{
struct server *srv = expr->arg.srv;
test->flags = ACL_TEST_F_VOL_TEST;
if (!(srv->state & SRV_MAINTAIN) &&
(!(srv->state & SRV_CHECKED) || (srv->state & SRV_RUNNING)))
test->flags |= ACL_TEST_F_SET_RES_PASS;
else
test->flags |= ACL_TEST_F_SET_RES_FAIL;
return 1;
}
/* set test->i to the number of enabled servers on the proxy */
static int
acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir,
@ -1410,6 +1428,7 @@ static struct acl_kw_list acl_kws = {{ },{
{ "be_conn", acl_parse_int, acl_fetch_be_conn, acl_match_int, ACL_USE_NOTHING },
{ "queue", acl_parse_int, acl_fetch_queue_size, acl_match_int, ACL_USE_NOTHING },
{ "avg_queue", acl_parse_int, acl_fetch_avg_queue_size, acl_match_int, ACL_USE_NOTHING },
{ "srv_is_up", acl_parse_nothing, acl_fetch_srv_is_up, acl_match_nothing, ACL_USE_NOTHING },
{ NULL, NULL, NULL, NULL },
}};