From 3115eb82a694d5dd37e67386f909f1a90fd5554e Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 18 Dec 2025 09:51:27 +0100 Subject: [PATCH] MEDIUM: proxy: implement dynamic backend creation Implement the required operations for "add backend" handler. This requires a new proxy allocation, settings copy from the specified default instance and proxy config finalization. All handlers registered via REGISTER_POST_PROXY_CHECK() are also called on the newly created instance. If no error were encountered, the newly created proxy is finally attached in the proxies list. --- src/proxy.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/src/proxy.c b/src/proxy.c index 292e72f8d..695470c06 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,7 @@ #include #include #include -#include +#include #include #include #include @@ -3023,8 +3024,10 @@ void defaults_px_unref_all(void) /* Add a reference on the default proxy for the proxy Nothing is * done if already references . Otherwise, the default proxy - * refcount is incremented by one. For now, this operation is not thread safe - * and is perform during init stage only. + * refcount is incremented by one. + * + * This operation is not thread safe. It must only be performed during init + * stage or under thread isolation. */ static inline void defaults_px_ref(struct proxy *defpx, struct proxy *px) { @@ -4786,10 +4789,12 @@ static int cli_parse_shutdown_frontend(char **args, char *payload, struct appctx */ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appctx, void *private) { - struct proxy *px, *defpx; + struct proxy *px, *defpx, *next; + struct post_proxy_check_fct *ppcf; const char *be_name, *def_name, *guid = NULL, *err; char *msg = NULL; enum pr_mode mode = 0; + int err_code = ERR_NONE; usermsgs_clr("CLI"); @@ -4872,15 +4877,81 @@ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appc goto err; } + px = alloc_new_proxy(be_name, PR_CAP_BE, &msg); + if (!px) + goto err; + + if (guid && guid_insert(&px->obj_type, guid, &msg)) { + memprintf(&msg, "GUID insertion : %s", msg); + goto err; + } + + if (proxy_defproxy_cpy(px, defpx, &msg)) + goto err; + + /* Override default-proxy mode if defined. */ + if (mode) + px->mode = mode; + + if (proxy_ref_defaults(px, defpx, &msg)) + goto err; + + proxy_init_per_thr(px); + + if (proxy_finalize(px, &err_code)) + goto err; + + list_for_each_entry(ppcf, &post_proxy_check_list, list) { + err_code |= ppcf->fct(px); + if (err_code & (ERR_ABORT|ERR_FATAL)) + goto err; + } + + px->flags |= PR_FL_BE_UNPUBLISHED; + + if (!stats_allocate_proxy_counters_internal(&px->extra_counters_be, + COUNTERS_BE, + STATS_PX_CAP_BE)) { + memprintf(&msg, "failed to allocate extra counters"); + goto err; + } + + if (!proxies_list) { + proxies_list->next = px; + } + else { + for (next = proxies_list; next->next; next = next->next) + ; + next->next = px; + } + px->next = NULL; + thread_release(); - ha_notice("New backend registered.\n"); + + if (unlikely(!be_supports_dynamic_srv(px, &msg))) + memprintf(&msg, "New backend registered (no support for dynamic servers: %s).\n", msg); + else + memprintf(&msg, "New backend registered.\n"); + ha_notice(msg); + ha_free(&msg); cli_umsg(appctx, LOG_INFO); + return 1; err: + /* free_proxy() ensures any potential refcounting on defpx is decremented. */ + free_proxy(px); thread_release(); - if (msg) + + if (msg) { + memprintf(&msg, "Error during backend creation : %s.\n", msg); cli_dynerr(appctx, msg); + } + else { + ha_alert("Error during backend creation.\n"); + cli_umsgerr(appctx); + } + return 1; } -- 2.47.3