There is currently an srv_queue converter which is capable of taking the output of a dynamic name and determining the queue length for a given server. In addition there is a sample fetcher for whether a server is currently up. This simply combines the two such that srv_is_up can be used as a converter too.
To avoid code duplication, extract the server lookup into a function from the existing converter and re-use in both implementations. Future work might extend this to other sample fetchers for servers, but this is probably the most useful for acl routing. --- doc/configuration.txt | 8 ++++++++ src/backend.c | 35 +++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 946ce8ace..ca71348df 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -20144,6 +20144,7 @@ secure_memcmp(var) string boolean set-var(var[,cond...]) any same sha1 binary binary sha2([bits]) binary binary +srv_is_up string boolean srv_queue string integer strcmp(var) string boolean sub(value) integer integer @@ -21405,6 +21406,13 @@ sha2([<bits>]) Please note that this converter is only available when HAProxy has been compiled with USE_OPENSSL. +srv_is_up + Takes an input value of type string, either a server name or <backend>/<server> + format and returns true when the designated server is currently UP. Can be used + in places where we want to look up a server status from a dynamic name, like a + cookie value (e.g. req.cook(SRVID),srv_is_up) and then make a decision to + direct a request elsewhere. + srv_queue Takes an input value of type string, either a server name or <backend>/<server> format and returns the number of queued streams on that server. Can be used diff --git a/src/backend.c b/src/backend.c index bee6277a5..135b2c4a0 100644 --- a/src/backend.c +++ b/src/backend.c @@ -3738,11 +3738,9 @@ static int sample_conv_nbsrv(const struct arg *args, struct sample *smp, void *p return 1; } -static int -sample_conv_srv_queue(const struct arg *args, struct sample *smp, void *private) +static struct server *sample_conv_srv(struct sample *smp) { struct proxy *px; - struct server *srv; char *bksep; if (!smp_make_safe(smp)) @@ -3754,15 +3752,39 @@ sample_conv_srv_queue(const struct arg *args, struct sample *smp, void *private) *bksep = '\0'; px = proxy_find_by_name(smp->data.u.str.area, PR_CAP_BE, 0); if (!px) - return 0; + return NULL; smp->data.u.str.area = bksep + 1; } else { if (!(smp->px->cap & PR_CAP_BE)) - return 0; + return NULL; px = smp->px; } - srv = server_find(px, smp->data.u.str.area); + return server_find(px, smp->data.u.str.area); +} + +static int +sample_conv_srv_is_up(const struct arg *args, struct sample *smp, void *private) +{ + struct server *srv = sample_conv_srv(smp); + + if (!srv) + return 0; + + smp->data.type = SMP_T_BOOL; + if (!(srv->cur_admin & SRV_ADMF_MAINT) && + (!(srv->check.state & CHK_ST_CONFIGURED) || (srv->cur_state != SRV_ST_STOPPED))) + smp->data.u.sint = 1; + else + smp->data.u.sint = 0; + return 1; +} + +static int +sample_conv_srv_queue(const struct arg *args, struct sample *smp, void *private) +{ + struct server *srv = sample_conv_srv(smp); + if (!srv) return 0; @@ -3804,6 +3826,7 @@ INITCALL1(STG_REGISTER, sample_register_fetches, &smp_kws); /* Note: must not be declared <const> as its list will be overwritten */ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "nbsrv", sample_conv_nbsrv, 0, NULL, SMP_T_STR, SMP_T_SINT }, + { "srv_is_up", sample_conv_srv_is_up, 0, NULL, SMP_T_STR, SMP_T_BOOL }, { "srv_queue", sample_conv_srv_queue, 0, NULL, SMP_T_STR, SMP_T_SINT }, { /* END */ }, }}; -- 2.49.0