mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-03 10:01:27 +00:00
REORG: cli: move 'show servers' to proxy.c
Move 'show servers' CLI functions to proxy.c and use the cli keyword API to register it on the CLI.
This commit is contained in:
parent
e7ed8855de
commit
a6c5f3372d
@ -117,7 +117,6 @@ enum {
|
||||
STAT_CLI_O_CLR, /* clear tables */
|
||||
STAT_CLI_O_SET, /* set entries in tables */
|
||||
STAT_CLI_O_STAT, /* dump stats */
|
||||
STAT_CLI_O_SERVERS_STATE, /* dump server state and changing information */
|
||||
STAT_CLI_O_BACKEND, /* dump backend list */
|
||||
STAT_CLI_O_ENV, /* dump environment */
|
||||
STAT_CLI_O_CUSTOM, /* custom callback pointer */
|
||||
|
134
src/cli.c
134
src/cli.c
@ -136,13 +136,11 @@ static struct field info[INF_TOTAL_FIELDS];
|
||||
static int stats_dump_backend_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_env_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_info_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_servers_state_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct stream *sess);
|
||||
static int stats_dump_sess_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_errors_to_buffer(struct stream_interface *si);
|
||||
static int stats_table_request(struct stream_interface *si, int show);
|
||||
|
||||
static int dump_servers_state(struct stream_interface *si, struct chunk *buf);
|
||||
|
||||
static struct applet cli_applet;
|
||||
|
||||
@ -160,7 +158,6 @@ static const char stats_sock_usage_msg[] =
|
||||
" show errors : report last request and response errors for each proxy\n"
|
||||
" show sess [id] : report the list of current sessions or dump this session\n"
|
||||
" show table [id]: report table usage stats or dump this table's contents\n"
|
||||
" show servers state [id]: dump volatile server information (for backend <id>)\n"
|
||||
" get weight : report a server's current weight\n"
|
||||
" set weight : change a server's weight\n"
|
||||
" set table [id] : update or create a table entry's data\n"
|
||||
@ -1113,27 +1110,6 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
appctx->st2 = STAT_ST_INIT;
|
||||
appctx->st0 = STAT_CLI_O_INFO; // stats_dump_info_to_buffer
|
||||
}
|
||||
else if (strcmp(args[1], "servers") == 0 && strcmp(args[2], "state") == 0) {
|
||||
appctx->ctx.server_state.iid = 0;
|
||||
appctx->ctx.server_state.px = NULL;
|
||||
appctx->ctx.server_state.sv = NULL;
|
||||
|
||||
/* check if a backend name has been provided */
|
||||
if (*args[3]) {
|
||||
/* read server state from local file */
|
||||
appctx->ctx.server_state.px = proxy_be_by_name(args[3]);
|
||||
|
||||
if (!appctx->ctx.server_state.px) {
|
||||
appctx->ctx.cli.msg = "Can't find backend.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
appctx->ctx.server_state.iid = appctx->ctx.server_state.px->uuid;
|
||||
}
|
||||
appctx->st2 = STAT_ST_INIT;
|
||||
appctx->st0 = STAT_CLI_O_SERVERS_STATE; // stats_dump_servers_state_to_buffer
|
||||
return 1;
|
||||
}
|
||||
else if (strcmp(args[1], "sess") == 0) {
|
||||
appctx->st2 = STAT_ST_INIT;
|
||||
if (strm_li(s)->bind_conf->level < ACCESS_LVL_OPER) {
|
||||
@ -1934,10 +1910,6 @@ static void cli_io_handler(struct appctx *appctx)
|
||||
if (stats_dump_info_to_buffer(si))
|
||||
appctx->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
case STAT_CLI_O_SERVERS_STATE:
|
||||
if (stats_dump_servers_state_to_buffer(si))
|
||||
appctx->st0 = STAT_CLI_PROMPT;
|
||||
break;
|
||||
case STAT_CLI_O_STAT:
|
||||
if (stats_dump_stat_to_buffer(si, NULL))
|
||||
appctx->st0 = STAT_CLI_PROMPT;
|
||||
@ -2189,65 +2161,6 @@ static int stats_dump_info_to_buffer(struct stream_interface *si)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* dumps server state information into <buf> for all the servers found in <backend>
|
||||
* These information are all the parameters which may change during HAProxy runtime.
|
||||
* By default, we only export to the last known server state file format.
|
||||
* These information can be used at next startup to recover same level of server state.
|
||||
*/
|
||||
static int dump_servers_state(struct stream_interface *si, struct chunk *buf)
|
||||
{
|
||||
struct appctx *appctx = __objt_appctx(si->end);
|
||||
struct server *srv;
|
||||
char srv_addr[INET6_ADDRSTRLEN + 1];
|
||||
time_t srv_time_since_last_change;
|
||||
int bk_f_forced_id, srv_f_forced_id;
|
||||
|
||||
|
||||
/* we don't want to report any state if the backend is not enabled on this process */
|
||||
if (appctx->ctx.server_state.px->bind_proc && !(appctx->ctx.server_state.px->bind_proc & (1UL << (relative_pid - 1))))
|
||||
return 1;
|
||||
|
||||
if (!appctx->ctx.server_state.sv)
|
||||
appctx->ctx.server_state.sv = appctx->ctx.server_state.px->srv;
|
||||
|
||||
for (; appctx->ctx.server_state.sv != NULL; appctx->ctx.server_state.sv = srv->next) {
|
||||
srv = appctx->ctx.server_state.sv;
|
||||
srv_addr[0] = '\0';
|
||||
|
||||
switch (srv->addr.ss_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(srv->addr.ss_family, &((struct sockaddr_in *)&srv->addr)->sin_addr,
|
||||
srv_addr, INET_ADDRSTRLEN + 1);
|
||||
break;
|
||||
case AF_INET6:
|
||||
inet_ntop(srv->addr.ss_family, &((struct sockaddr_in6 *)&srv->addr)->sin6_addr,
|
||||
srv_addr, INET6_ADDRSTRLEN + 1);
|
||||
break;
|
||||
}
|
||||
srv_time_since_last_change = now.tv_sec - srv->last_change;
|
||||
bk_f_forced_id = appctx->ctx.server_state.px->options & PR_O_FORCED_ID ? 1 : 0;
|
||||
srv_f_forced_id = srv->flags & SRV_F_FORCED_ID ? 1 : 0;
|
||||
|
||||
chunk_appendf(buf,
|
||||
"%d %s "
|
||||
"%d %s %s "
|
||||
"%d %d %d %d %ld "
|
||||
"%d %d %d %d %d "
|
||||
"%d %d"
|
||||
"\n",
|
||||
appctx->ctx.server_state.px->uuid, appctx->ctx.server_state.px->id,
|
||||
srv->puid, srv->id, srv_addr,
|
||||
srv->state, srv->admin, srv->uweight, srv->iweight, (long int)srv_time_since_last_change,
|
||||
srv->check.status, srv->check.result, srv->check.health, srv->check.state, srv->agent.state,
|
||||
bk_f_forced_id, srv_f_forced_id);
|
||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||
si_applet_cant_put(si);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parses backend list and simply report backend names */
|
||||
static int stats_dump_backend_to_buffer(struct stream_interface *si)
|
||||
{
|
||||
@ -2287,53 +2200,6 @@ static int stats_dump_backend_to_buffer(struct stream_interface *si)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parses backend list or simply use backend name provided by the user to return
|
||||
* states of servers to stdout.
|
||||
*/
|
||||
static int stats_dump_servers_state_to_buffer(struct stream_interface *si)
|
||||
{
|
||||
struct appctx *appctx = __objt_appctx(si->end);
|
||||
extern struct proxy *proxy;
|
||||
struct proxy *curproxy;
|
||||
|
||||
chunk_reset(&trash);
|
||||
|
||||
if (appctx->st2 == STAT_ST_INIT) {
|
||||
if (!appctx->ctx.server_state.px)
|
||||
appctx->ctx.server_state.px = proxy;
|
||||
appctx->st2 = STAT_ST_HEAD;
|
||||
}
|
||||
|
||||
if (appctx->st2 == STAT_ST_HEAD) {
|
||||
chunk_printf(&trash, "%d\n# %s\n", SRV_STATE_FILE_VERSION, SRV_STATE_FILE_FIELD_NAMES);
|
||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||
si_applet_cant_put(si);
|
||||
return 0;
|
||||
}
|
||||
appctx->st2 = STAT_ST_INFO;
|
||||
}
|
||||
|
||||
/* STAT_ST_INFO */
|
||||
for (; appctx->ctx.server_state.px != NULL; appctx->ctx.server_state.px = curproxy->next) {
|
||||
curproxy = appctx->ctx.server_state.px;
|
||||
/* servers are only in backends */
|
||||
if (curproxy->cap & PR_CAP_BE) {
|
||||
if (!dump_servers_state(si, &trash))
|
||||
return 0;
|
||||
|
||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||
si_applet_cant_put(si);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* only the selected proxy is dumped */
|
||||
if (appctx->ctx.server_state.iid)
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline const char *get_conn_ctrl_name(const struct connection *conn)
|
||||
{
|
||||
if (!conn_ctrl_ready(conn))
|
||||
|
142
src/proxy.c
142
src/proxy.c
@ -33,7 +33,10 @@
|
||||
#include <types/global.h>
|
||||
#include <types/obj_type.h>
|
||||
#include <types/peers.h>
|
||||
#include <types/stats.h>
|
||||
|
||||
#include <proto/applet.h>
|
||||
#include <proto/cli.h>
|
||||
#include <proto/backend.h>
|
||||
#include <proto/fd.h>
|
||||
#include <proto/filters.h>
|
||||
@ -45,6 +48,7 @@
|
||||
#include <proto/proxy.h>
|
||||
#include <proto/signal.h>
|
||||
#include <proto/stream.h>
|
||||
#include <proto/stream_interface.h>
|
||||
#include <proto/task.h>
|
||||
|
||||
|
||||
@ -1240,10 +1244,148 @@ struct proxy *cli_find_frontend(struct appctx *appctx, const char *arg)
|
||||
return px;
|
||||
}
|
||||
|
||||
/* parse a "show servers" CLI line, returns 0 if it wants to start the dump or
|
||||
* 1 if it stops immediately.
|
||||
*/
|
||||
static int cli_parse_show_servers(char **args, struct appctx *appctx, void *private)
|
||||
{
|
||||
appctx->ctx.server_state.iid = 0;
|
||||
appctx->ctx.server_state.px = NULL;
|
||||
appctx->ctx.server_state.sv = NULL;
|
||||
|
||||
/* check if a backend name has been provided */
|
||||
if (*args[3]) {
|
||||
/* read server state from local file */
|
||||
appctx->ctx.server_state.px = proxy_be_by_name(args[3]);
|
||||
|
||||
if (!appctx->ctx.server_state.px) {
|
||||
appctx->ctx.cli.msg = "Can't find backend.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
appctx->ctx.server_state.iid = appctx->ctx.server_state.px->uuid;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dumps server state information into <buf> for all the servers found in <backend>
|
||||
* These information are all the parameters which may change during HAProxy runtime.
|
||||
* By default, we only export to the last known server state file format.
|
||||
* These information can be used at next startup to recover same level of server state.
|
||||
*/
|
||||
static int dump_servers_state(struct stream_interface *si, struct chunk *buf)
|
||||
{
|
||||
struct appctx *appctx = __objt_appctx(si->end);
|
||||
struct server *srv;
|
||||
char srv_addr[INET6_ADDRSTRLEN + 1];
|
||||
time_t srv_time_since_last_change;
|
||||
int bk_f_forced_id, srv_f_forced_id;
|
||||
|
||||
|
||||
/* we don't want to report any state if the backend is not enabled on this process */
|
||||
if (appctx->ctx.server_state.px->bind_proc && !(appctx->ctx.server_state.px->bind_proc & (1UL << (relative_pid - 1))))
|
||||
return 1;
|
||||
|
||||
if (!appctx->ctx.server_state.sv)
|
||||
appctx->ctx.server_state.sv = appctx->ctx.server_state.px->srv;
|
||||
|
||||
for (; appctx->ctx.server_state.sv != NULL; appctx->ctx.server_state.sv = srv->next) {
|
||||
srv = appctx->ctx.server_state.sv;
|
||||
srv_addr[0] = '\0';
|
||||
|
||||
switch (srv->addr.ss_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(srv->addr.ss_family, &((struct sockaddr_in *)&srv->addr)->sin_addr,
|
||||
srv_addr, INET_ADDRSTRLEN + 1);
|
||||
break;
|
||||
case AF_INET6:
|
||||
inet_ntop(srv->addr.ss_family, &((struct sockaddr_in6 *)&srv->addr)->sin6_addr,
|
||||
srv_addr, INET6_ADDRSTRLEN + 1);
|
||||
break;
|
||||
}
|
||||
srv_time_since_last_change = now.tv_sec - srv->last_change;
|
||||
bk_f_forced_id = appctx->ctx.server_state.px->options & PR_O_FORCED_ID ? 1 : 0;
|
||||
srv_f_forced_id = srv->flags & SRV_F_FORCED_ID ? 1 : 0;
|
||||
|
||||
chunk_appendf(buf,
|
||||
"%d %s "
|
||||
"%d %s %s "
|
||||
"%d %d %d %d %ld "
|
||||
"%d %d %d %d %d "
|
||||
"%d %d"
|
||||
"\n",
|
||||
appctx->ctx.server_state.px->uuid, appctx->ctx.server_state.px->id,
|
||||
srv->puid, srv->id, srv_addr,
|
||||
srv->state, srv->admin, srv->uweight, srv->iweight, (long int)srv_time_since_last_change,
|
||||
srv->check.status, srv->check.result, srv->check.health, srv->check.state, srv->agent.state,
|
||||
bk_f_forced_id, srv_f_forced_id);
|
||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||
si_applet_cant_put(si);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parses backend list or simply use backend name provided by the user to return
|
||||
* states of servers to stdout.
|
||||
*/
|
||||
static int cli_io_handler_servers_state(struct appctx *appctx)
|
||||
{
|
||||
struct stream_interface *si = appctx->owner;
|
||||
extern struct proxy *proxy;
|
||||
struct proxy *curproxy;
|
||||
|
||||
chunk_reset(&trash);
|
||||
|
||||
if (appctx->st2 == STAT_ST_INIT) {
|
||||
if (!appctx->ctx.server_state.px)
|
||||
appctx->ctx.server_state.px = proxy;
|
||||
appctx->st2 = STAT_ST_HEAD;
|
||||
}
|
||||
|
||||
if (appctx->st2 == STAT_ST_HEAD) {
|
||||
chunk_printf(&trash, "%d\n# %s\n", SRV_STATE_FILE_VERSION, SRV_STATE_FILE_FIELD_NAMES);
|
||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||
si_applet_cant_put(si);
|
||||
return 0;
|
||||
}
|
||||
appctx->st2 = STAT_ST_INFO;
|
||||
}
|
||||
|
||||
/* STAT_ST_INFO */
|
||||
for (; appctx->ctx.server_state.px != NULL; appctx->ctx.server_state.px = curproxy->next) {
|
||||
curproxy = appctx->ctx.server_state.px;
|
||||
/* servers are only in backends */
|
||||
if (curproxy->cap & PR_CAP_BE) {
|
||||
if (!dump_servers_state(si, &trash))
|
||||
return 0;
|
||||
|
||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||
si_applet_cant_put(si);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* only the selected proxy is dumped */
|
||||
if (appctx->ctx.server_state.iid)
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* register cli keywords */
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
{ { "show","servers", "state", NULL }, "show servers state [id]: dump volatile server information (for backend <id>)", cli_parse_show_servers, cli_io_handler_servers_state },
|
||||
{{},}
|
||||
}};
|
||||
|
||||
__attribute__((constructor))
|
||||
static void __proxy_module_init(void)
|
||||
{
|
||||
cfg_register_keywords(&cfg_kws);
|
||||
cli_register_kw(&cli_kws);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user