MINOR: server/event_hdl: add support for SERVER_ADD and SERVER_DEL events

Basic support for ADD and DEL server events are added through this commit:
	SERVER_ADD is published on dynamic server addition through cli.
	SERVER_DEL is published on dynamic server deletion through cli.

This work depends on:
	"MINOR: event_hdl: add event handler base api"
	"MINOR: server: add srv->rid (revision id) value"
This commit is contained in:
Aurelien DARRAGON 2022-11-17 10:37:58 +01:00 committed by Christopher Faulet
parent 745ce8e8ad
commit 129ecf441f
2 changed files with 72 additions and 0 deletions

View File

@ -40,6 +40,7 @@
#include <haproxy/stats-t.h>
#include <haproxy/task-t.h>
#include <haproxy/thread-t.h>
#include <haproxy/event_hdl-t.h>
/* server states. Only SRV_ST_STOPPED indicates a down server. */
@ -403,6 +404,8 @@ struct server {
} op_st_chg; /* operational status change's reason */
char adm_st_chg_cause[48]; /* administrative status change's cause */
event_hdl_sub_list e_subs; /* event_hdl: server's subscribers list (atomically updated) */
/* warning, these structs are huge, keep them at the bottom */
struct conn_src conn_src; /* connection source settings */
struct sockaddr_storage addr; /* the address to connect to, doesn't include the port */
@ -411,6 +414,35 @@ struct server {
EXTRA_COUNTERS(extra_counters);
};
/* data provided to EVENT_HDL_SUB_SERVER handlers through event_hdl facility */
struct event_hdl_cb_data_server {
/* provided by:
* EVENT_HDL_SUB_SERVER_ADD
* EVENT_HDL_SUB_SERVER_DOWN
*/
struct {
/* safe data can be safely used from both
* sync and async handlers
* data consistency is guaranteed
*/
char name[64]; /* server name/id */
char proxy_name[64]; /* id of proxy the server belongs to */
int puid; /* proxy-unique server ID */
int rid; /* server id revision */
unsigned int flags; /* server flags */
} safe;
struct {
/* unsafe data may only be used from sync handlers:
* in async mode, data consistency cannot be guaranteed
* and unsafe data may already be stale, thus using
* it is highly discouraged because it
* could lead to undefined behavior (UAF, null dereference...)
*/
struct server *ptr; /* server live ptr */
/* lock hints */
uint8_t thread_isolate; /* 1 = thread_isolate is on, no locking required */
} unsafe;
};
/* Storage structure to load server-state lines from a flat file into
* an ebtree, for faster processing

View File

@ -47,6 +47,7 @@
#include <haproxy/time.h>
#include <haproxy/tools.h>
#include <haproxy/xxhash.h>
#include <haproxy/event_hdl.h>
static void srv_update_status(struct server *s);
@ -132,6 +133,33 @@ int srv_getinter(const struct check *check)
return (check->fastinter)?(check->fastinter):(check->inter);
}
/*
* Use this to publish EVENT_HDL_SUB_SERVER family type event
* from srv facility
* Event will be published in both global subscription list and
* server dedicated subscription list
* server ptr must be valid
*/
static inline void srv_event_hdl_publish(struct event_hdl_sub_type event, struct server *srv, uint8_t thread_isolate)
{
struct event_hdl_cb_data_server cb_data;
/* safe data assignments */
cb_data.safe.puid = srv->puid;
cb_data.safe.rid = srv->rid;
cb_data.safe.flags = srv->flags;
snprintf(cb_data.safe.name, sizeof(cb_data.safe.name), "%s", srv->id);
if (srv->proxy)
snprintf(cb_data.safe.proxy_name, sizeof(cb_data.safe.proxy_name), "%s", srv->proxy->id);
/* unsafe data assignments */
cb_data.unsafe.ptr = srv;
cb_data.unsafe.thread_isolate = thread_isolate;
/* publish in server dedicated sub list */
event_hdl_publish(&srv->e_subs, event, EVENT_HDL_CB_DATA(&cb_data));
/* publish in global subscription list */
event_hdl_publish(NULL, event, EVENT_HDL_CB_DATA(&cb_data));
}
/*
* Check that we did not get a hash collision.
* Unlikely, but it can happen. The server's proxy must be at least
@ -2337,6 +2365,7 @@ struct server *new_server(struct proxy *proxy)
LIST_APPEND(&servers_list, &srv->global_list);
LIST_INIT(&srv->srv_rec_item);
LIST_INIT(&srv->ip_rec_item);
event_hdl_sub_list_init(&srv->e_subs);
srv->next_state = SRV_ST_RUNNING; /* early server setup */
srv->last_change = now.tv_sec;
@ -2419,6 +2448,7 @@ struct server *srv_drop(struct server *srv)
HA_SPIN_DESTROY(&srv->lock);
LIST_DELETE(&srv->global_list);
event_hdl_sub_list_destroy(&srv->e_subs);
EXTRA_COUNTERS_FREE(srv->extra_counters);
@ -4893,6 +4923,11 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
*/
srv->rid = (srv_id_reuse_cnt) ? (srv_id_reuse_cnt / 2) : 0;
/* adding server cannot fail when we reach this:
* publishing EVENT_HDL_SUB_SERVER_ADD
*/
srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_ADD, srv, 1);
thread_release();
/* Start the check task. The server must be fully initialized.
@ -5020,6 +5055,11 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
goto out;
}
/* removing cannot fail anymore when we reach this:
* publishing EVENT_HDL_SUB_SERVER_DEL
*/
srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_DEL, srv, 1);
/* remove srv from tracking list */
if (srv->track)
release_server_track(srv);