From: Amaury Denoyelle Date: Mon, 21 Sep 2026 08:36:36 +0000 (+0200) Subject: MINOR: server: set maintenance mode on "purge server" X-Git-Tag: v3.5-dev9~16 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=a5adffde2c174e5e4d7437f5e0ee43361c3701b4;p=haproxy.git MINOR: server: set maintenance mode on "purge server" This patch changes behavior of "purge server" to automatically set a server in maintenance mode if needed. This is not performed if a server cannot be removed due to a configuration limitation. The objective is to improve the user API. While not a big change in the context of a single "purge server", automatic maintenance mode will become a must have for the future "purge all servers". Thus, this change allow guaranteeing a similar behavior between these two commands. To implement it, a new argument is added to srv_check_for_deletion(), indicating the deletion mode. For better code clarity, this is defined as an enum type pr_del_mode. --- diff --git a/doc/management.txt b/doc/management.txt index 3e2cca5c8..7d41abd68 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -2601,8 +2601,9 @@ purge server / This is an alternative command to "del server". Its main difference is that if the server cannot be immediately removed due to remaining active or idle connections, the server is flagged for background deletion instead of - rejecting the command. A scheduled deletion is cancelled if the server state - is explicitly reset, even if still in maintenance mode. + rejecting the command. To succeed, this also automatically puts the server + into maintenance if needed. A scheduled deletion is cancelled if the server + state is explicitly reset, even if still in maintenance mode. quit Close the connection when in interactive mode. diff --git a/include/haproxy/proxy-t.h b/include/haproxy/proxy-t.h index d45d8731d..7b1b0148f 100644 --- a/include/haproxy/proxy-t.h +++ b/include/haproxy/proxy-t.h @@ -60,6 +60,12 @@ enum pr_mode { PR_MODE_SPOP = 0x20, } __attribute__((packed)); +/* Runtime deletion mode of operation */ +enum pr_del_mode { + PR_DEL_MODE_SYNC, + PR_DEL_MODE_ASYNC, +}; + enum PR_SRV_STATE_FILE { PR_SRV_STATE_FILE_UNSPEC = 0, PR_SRV_STATE_FILE_NONE, diff --git a/include/haproxy/server.h b/include/haproxy/server.h index 0f80a9467..6044152f2 100644 --- a/include/haproxy/server.h +++ b/include/haproxy/server.h @@ -96,7 +96,8 @@ const char *srv_adm_st_chg_cause(enum srv_adm_st_chg_cause cause); const char *srv_op_st_chg_cause(enum srv_op_st_chg_cause cause); void srv_event_hdl_publish_check(struct server *srv, struct check *check); -int srv_check_for_deletion(const char *bename, const char *svname, struct proxy **pb, struct server **ps, const char **pm); +int srv_check_for_deletion(const char *bename, const char *svname, enum pr_del_mode del_mode, + struct proxy **pb, struct server **ps, const char **pm); void srv_unregister(struct server *srv); /* functions related to server name resolution */ diff --git a/src/cli.c b/src/cli.c index 21a23a1fb..f7ad9cf79 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2545,7 +2545,7 @@ static int cli_io_handler_wait(struct appctx *appctx) ctx->cond == CLI_WAIT_COND_BE_UNUSED) { if (ctx->cond == CLI_WAIT_COND_SRV_UNUSED) { /* check if the server in args[0]/args[1] can be released now */ - ret = srv_check_for_deletion(ctx->args[0], ctx->args[1], NULL, NULL, &ctx->msg); + ret = srv_check_for_deletion(ctx->args[0], ctx->args[1], PR_DEL_MODE_SYNC, NULL, NULL, &ctx->msg); } else { ret = be_check_for_deletion(ctx->args[0], NULL, &ctx->msg); diff --git a/src/server.c b/src/server.c index e29b9e7a6..f9fe785c6 100644 --- a/src/server.c +++ b/src/server.c @@ -6909,19 +6909,29 @@ out: return 1; } -/* Check if the server / exists and is ready for being deleted. - * This means that the server is in maintenance with no streams attached to it, - * no queue and no used idle conns. This is not supposed to change during all - * the maintenance phase (except for force-persist etc, which are not covered). - * Both and must be valid strings. If pb/ps are not null, +/* Checks if the server / exists and is ready for being + * deleted. This means that the server is in maintenance with no streams + * attached to it, no queue and no used idle conns. This is not supposed to + * change during all the maintenance phase (except for force-persist etc, which + * are not covered). Both and must be valid strings. + * + * Input parameter indicates if the server deletion should be + * conducted immediately or could be performed in background. In the latter + * case, maintenance mode is set on the server if needed, instead of rejecting + * the deletion. + * + * If / are not null, * upon success, the pointer to the backend and server respectively will be put - * there. If pm is not null, a pointer to an error/success message is returned - * there (possibly NULL if nothing to say). Returned values: - * >0 if OK - * 0 if not yet (should wait if it can) - * <0 if not possible + * there. If is not null, a pointer to an error/success message is returned + * there (possibly NULL if nothing to say). + * + * Returns a positive value if server can be deleted. If not possible, 0 is + * returned if removal is temporarily blocked. A negative value is used if + * removal is blocked indefinitely due to its configuration or that it requires + * an administrative interaction. */ -int srv_check_for_deletion(const char *bename, const char *svname, struct proxy **pb, struct server **ps, const char **pm) +int srv_check_for_deletion(const char *bename, const char *svname, enum pr_del_mode del_mode, + struct proxy **pb, struct server **ps, const char **pm) { struct server *srv = NULL; struct proxy *be = NULL; @@ -6951,8 +6961,13 @@ int srv_check_for_deletion(const char *bename, const char *svname, struct proxy * lbprm.ops->set_server_status_down). */ if (!(srv->cur_admin & SRV_ADMF_MAINT)) { - msg = "Only servers in maintenance mode can be deleted."; - goto leave; + if (del_mode == PR_DEL_MODE_SYNC) { + msg = "Only servers in maintenance mode can be deleted."; + goto leave; + } + + /* Automatically set server in maintenance for background deletion. */ + srv_adm_set_maint(srv); } /* Second, conditions that may change over time */ @@ -7088,7 +7103,7 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap goto out; } - ret = srv_check_for_deletion(be_name, sv_name, &be, &srv, &msg); + ret = srv_check_for_deletion(be_name, sv_name, PR_DEL_MODE_SYNC, &be, &srv, &msg); if (ret <= 0) { /* failure (recoverable or not) */ cli_err(appctx, msg); @@ -7129,7 +7144,7 @@ static int cli_parse_purge_server(char **args, char *payload, struct appctx *app goto out; } - ret = srv_check_for_deletion(be_name, sv_name, &be, &srv, &msg); + ret = srv_check_for_deletion(be_name, sv_name, PR_DEL_MODE_ASYNC, &be, &srv, &msg); if (ret < 0) { /* Unremovable server, cancel purge. */ cli_err(appctx, msg);