MINOR: cli/wait: add a condition to wait on a server to become unused
The "wait" command now supports a condition, "srv-unused", which waits for the designated server to become totally unused, indicating that it is removable. Upon each wakeup it calls srv_check_for_deletion() to verify if conditions are met, if not if it's recoverable, or if it's not recoverable, and proceeds according to this, never waiting for a final decision longer than the configured delay. The purpose is to make it possible to remove servers from the CLI after waiting for their sessions to be terminated: $ socat -t5 /path/to/socket - <<< " disable server px/srv1 shutdown sessions server px/srv1 wait 2s srv-unused px/srv1 del server px/srv1" Or even wait for connections to terminate themselves: $ socat -t70 /path/to/socket - <<< " disable server px/srv1 wait 1m srv-unused px/srv1 del server px/srv1"
This commit is contained in:
parent
66989ff426
commit
613e959c7b
|
@ -3997,15 +3997,36 @@ update ssl ocsp-response <certfile>
|
||||||
local tree, its contents will be displayed on the standard output. The format
|
local tree, its contents will be displayed on the standard output. The format
|
||||||
is the same as the one described in "show ssl ocsp-response".
|
is the same as the one described in "show ssl ocsp-response".
|
||||||
|
|
||||||
wait { -h | <delay> }
|
wait { -h | <delay> } [<condition> [<args>...]]
|
||||||
This simply waits for the requested delay before continuing. This can be used
|
In its simplest form without any condition, this simply waits for the
|
||||||
to collect metrics around a specific interval. The default unit for the delay
|
requested delay before continuing. This can be used to collect metrics around
|
||||||
is milliseconds, though other units are accepted if suffixed with the usual
|
a specific interval.
|
||||||
timer units (us, ms, s, m, h, d). When used with the 'socat' utility, do not
|
|
||||||
forget to extend socat's close timeout to cover the wait time. Passing "-h"
|
With a condition and optional arguments, the command will wait for the
|
||||||
as the first or second argument provides the command's usage.
|
specified condition to be satisfied, to unrecoverably fail, or to remain
|
||||||
|
unsatisfied for the whole <delay> duration. The supported conditions are:
|
||||||
|
|
||||||
|
- srv-unused <proxy>/<server> : this will wait for the specified server to be
|
||||||
|
removable, i.e. be in maintenance and no longer have any connection on it.
|
||||||
|
Some conditions will never be accepted (e.g. not in maintenance) and will
|
||||||
|
cause the report of a specific error message indicating what condition is
|
||||||
|
not met. The server might even have been removed in parallel and no longer
|
||||||
|
exit. If everything is OK before the delay, a success is returned and the
|
||||||
|
operation is terminated.
|
||||||
|
|
||||||
|
The default unit for the delay is milliseconds, though other units are
|
||||||
|
accepted if suffixed with the usual timer units (us, ms, s, m, h, d). When
|
||||||
|
used with the 'socat' utility, do not forget to extend socat's close timeout
|
||||||
|
to cover the wait time. Passing "-h" as the first or second argument provides
|
||||||
|
the command's usage.
|
||||||
Example:
|
Example:
|
||||||
$ socat -t20 /path/to/socket <<< "show activity; wait 10s; show activity"
|
$ socat -t20 /path/to/socket - <<< "show activity; wait 10s; show activity"
|
||||||
|
|
||||||
|
$ socat -t5 /path/to/socket - <<< "
|
||||||
|
disable server px/srv1
|
||||||
|
shutdown sessions server px/srv1
|
||||||
|
wait 2s srv-unused px/srv1
|
||||||
|
del server px/srv1"
|
||||||
|
|
||||||
|
|
||||||
9.4. Master CLI
|
9.4. Master CLI
|
||||||
|
|
|
@ -95,6 +95,7 @@ enum cli_wait_err {
|
||||||
|
|
||||||
enum cli_wait_cond {
|
enum cli_wait_cond {
|
||||||
CLI_WAIT_COND_NONE, // no condition to wait on
|
CLI_WAIT_COND_NONE, // no condition to wait on
|
||||||
|
CLI_WAIT_COND_SRV_UNUSED,// wait for server to become unused
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cli_wait_ctx {
|
struct cli_wait_ctx {
|
||||||
|
|
53
src/cli.c
53
src/cli.c
|
@ -2035,14 +2035,40 @@ static int cli_parse_wait(char **args, char *payload, struct appctx *appctx, voi
|
||||||
return cli_err(appctx, "Invalid duration.\n");
|
return cli_err(appctx, "Invalid duration.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*args[2]) {
|
if (strcmp(args[2], "srv-unused") == 0) {
|
||||||
|
struct ist be_name, sv_name;
|
||||||
|
|
||||||
|
if (!*args[3])
|
||||||
|
return cli_err(appctx, "Missing server name (<backend>/<server>).\n");
|
||||||
|
|
||||||
|
sv_name = ist(args[3]);
|
||||||
|
be_name = istsplit(&sv_name, '/');
|
||||||
|
if (!istlen(sv_name))
|
||||||
|
return cli_err(appctx, "Require 'backend/server'.\n");
|
||||||
|
|
||||||
|
be_name = istdup(be_name);
|
||||||
|
sv_name = istdup(sv_name);
|
||||||
|
if (!isttest(be_name) || !isttest(sv_name)) {
|
||||||
|
free(istptr(be_name));
|
||||||
|
free(istptr(sv_name));
|
||||||
|
return cli_err(appctx, "Out of memory trying to clone the server name.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->args[0] = ist0(be_name);
|
||||||
|
ctx->args[1] = ist0(sv_name);
|
||||||
|
ctx->cond = CLI_WAIT_COND_SRV_UNUSED;
|
||||||
|
}
|
||||||
|
else if (*args[2]) {
|
||||||
/* show the command's help either upon request (-h) or error */
|
/* show the command's help either upon request (-h) or error */
|
||||||
err = "Usage: wait {-h|<duration>} [condition [args...]]\n"
|
err = "Usage: wait {-h|<duration>} [condition [args...]]\n"
|
||||||
" - '-h' displays this help\n"
|
" - '-h' displays this help\n"
|
||||||
" - <duration> is the maximum wait time, optionally suffixed by the unit among\n"
|
" - <duration> is the maximum wait time, optionally suffixed by the unit among\n"
|
||||||
" 'us', 'ms', 's', 'm', 'h', and 'd'. ; the default unit is milliseconds.\n"
|
" 'us', 'ms', 's', 'm', 'h', and 'd'. ; the default unit is milliseconds.\n"
|
||||||
" - <condition> indicates what to wait for. By default, no events aborts the\n"
|
" - <condition> indicates what to wait for, no longer than the specified\n"
|
||||||
" operation, which makes it reliably pause for the specified duration.\n";
|
" duration. Supported conditions are:\n"
|
||||||
|
" - <none> : by default, just sleep for the specified duration.\n"
|
||||||
|
" - srv-unused <px>/<sv> : wait for this server to become unused.\n"
|
||||||
|
"";
|
||||||
|
|
||||||
if (strcmp(args[2], "-h") == 0)
|
if (strcmp(args[2], "-h") == 0)
|
||||||
return cli_msg(appctx, LOG_INFO, err);
|
return cli_msg(appctx, LOG_INFO, err);
|
||||||
|
@ -2069,6 +2095,7 @@ static int cli_io_handler_wait(struct appctx *appctx)
|
||||||
struct cli_wait_ctx *ctx = appctx->svcctx;
|
struct cli_wait_ctx *ctx = appctx->svcctx;
|
||||||
struct stconn *sc = appctx_sc(appctx);
|
struct stconn *sc = appctx_sc(appctx);
|
||||||
uint total, elapsed, left, wait;
|
uint total, elapsed, left, wait;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* note: upon first invocation, the timeout is not set */
|
/* note: upon first invocation, the timeout is not set */
|
||||||
if (tick_isset(appctx->t->expire) &&
|
if (tick_isset(appctx->t->expire) &&
|
||||||
|
@ -2077,6 +2104,24 @@ static int cli_io_handler_wait(struct appctx *appctx)
|
||||||
|
|
||||||
/* here we should evaluate our waiting conditions, if any */
|
/* here we should evaluate our waiting conditions, if any */
|
||||||
|
|
||||||
|
if (ctx->cond == CLI_WAIT_COND_SRV_UNUSED) {
|
||||||
|
/* check if the server in args[0]/args[1] can be released now */
|
||||||
|
thread_isolate();
|
||||||
|
ret = srv_check_for_deletion(ctx->args[0], ctx->args[1], NULL, NULL, NULL);
|
||||||
|
thread_release();
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
/* unrecoverable failure */
|
||||||
|
ctx->error = CLI_WAIT_ERR_FAIL;
|
||||||
|
return 1;
|
||||||
|
} else if (ret > 0) {
|
||||||
|
/* immediate success */
|
||||||
|
ctx->error = CLI_WAIT_ERR_DONE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* let's check the timer */
|
||||||
|
}
|
||||||
|
|
||||||
/* and here we recalculate the new wait time or abort */
|
/* and here we recalculate the new wait time or abort */
|
||||||
left = tick_remain(now_ms, ctx->deadline);
|
left = tick_remain(now_ms, ctx->deadline);
|
||||||
if (!left) {
|
if (!left) {
|
||||||
|
@ -3530,7 +3575,7 @@ static struct cli_kw_list cli_kws = {{ },{
|
||||||
{ { "show", "version", NULL }, "show version : show version of the current process", cli_parse_show_version, NULL, NULL, NULL, ACCESS_MASTER },
|
{ { "show", "version", NULL }, "show version : show version of the current process", cli_parse_show_version, NULL, NULL, NULL, ACCESS_MASTER },
|
||||||
{ { "operator", NULL }, "operator : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
|
{ { "operator", NULL }, "operator : lower the level of the current CLI session to operator", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
|
||||||
{ { "user", NULL }, "user : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
|
{ { "user", NULL }, "user : lower the level of the current CLI session to user", cli_parse_set_lvl, NULL, NULL, NULL, ACCESS_MASTER},
|
||||||
{ { "wait", NULL }, "wait {-h|<delay_ms>} : wait the specified delay (-h to see usage)", cli_parse_wait, cli_io_handler_wait, cli_release_wait, NULL },
|
{ { "wait", NULL }, "wait {-h|<delay_ms>} cond [args...] : wait the specified delay or condition (-h to see list)", cli_parse_wait, cli_io_handler_wait, cli_release_wait, NULL },
|
||||||
{{},}
|
{{},}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue