mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
MINOR: server/event_hdl: add SERVER_INETADDR event
In this patch we add the support for a new SERVER event in the event_hdl API. SERVER_INETADDR is implemented as an advanced server event. It is published each time the server's ip address or port is about to change. (ie: from the cli, dns, lua...) SERVER_INETADDR data is an event_hdl_cb_data_server_inetaddr struct that provides additional info related to the server inet addr change, but can be casted as a regular event_hdl_cb_data_server struct if additional info is not needed.
This commit is contained in:
parent
0e1f389fe9
commit
683b2ae013
@ -274,6 +274,8 @@ struct event_hdl_sub {
|
|||||||
#define EVENT_HDL_SUB_SERVER_ADMIN EVENT_HDL_SUB_TYPE(1,6)
|
#define EVENT_HDL_SUB_SERVER_ADMIN EVENT_HDL_SUB_TYPE(1,6)
|
||||||
/* server check-related (agent or health) event */
|
/* server check-related (agent or health) event */
|
||||||
#define EVENT_HDL_SUB_SERVER_CHECK EVENT_HDL_SUB_TYPE(1,7)
|
#define EVENT_HDL_SUB_SERVER_CHECK EVENT_HDL_SUB_TYPE(1,7)
|
||||||
|
/* server inet addr (addr:svc_port tuple) change event */
|
||||||
|
#define EVENT_HDL_SUB_SERVER_INETADDR EVENT_HDL_SUB_TYPE(1,8)
|
||||||
|
|
||||||
/* --------------------------------------- */
|
/* --------------------------------------- */
|
||||||
|
|
||||||
|
@ -477,6 +477,7 @@ struct event_hdl_cb_data_server {
|
|||||||
* EVENT_HDL_SUB_SERVER_STATE
|
* EVENT_HDL_SUB_SERVER_STATE
|
||||||
* EVENT_HDL_SUB_SERVER_ADMIN
|
* EVENT_HDL_SUB_SERVER_ADMIN
|
||||||
* EVENT_HDL_SUB_SERVER_CHECK
|
* EVENT_HDL_SUB_SERVER_CHECK
|
||||||
|
* EVENT_HDL_SUB_SERVER_INETADDR
|
||||||
*/
|
*/
|
||||||
struct {
|
struct {
|
||||||
/* safe data can be safely used from both
|
/* safe data can be safely used from both
|
||||||
@ -596,6 +597,39 @@ struct event_hdl_cb_data_server_check {
|
|||||||
} unsafe;
|
} unsafe;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* data provided to EVENT_HDL_SUB_SERVER_INETADDR handlers through
|
||||||
|
* event_hdl facility
|
||||||
|
*
|
||||||
|
* Note that this may be casted to regular event_hdl_cb_data_server if
|
||||||
|
* you don't care about inetaddr related optional info
|
||||||
|
*/
|
||||||
|
struct event_hdl_cb_data_server_inetaddr {
|
||||||
|
/* provided by:
|
||||||
|
* EVENT_HDL_SUB_SERVER_INETADDR
|
||||||
|
*/
|
||||||
|
struct event_hdl_cb_data_server server; /* must be at the beginning */
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
int family; /* AF_INET or AF_INET6 */
|
||||||
|
union {
|
||||||
|
struct in_addr v4;
|
||||||
|
struct in6_addr v6;
|
||||||
|
} addr; /* may hold v4 or v6 addr */
|
||||||
|
unsigned int svc_port;
|
||||||
|
} prev;
|
||||||
|
struct {
|
||||||
|
int family; /* AF_INET or AF_INET6 */
|
||||||
|
union {
|
||||||
|
struct in_addr v4;
|
||||||
|
struct in6_addr v6;
|
||||||
|
} addr; /* may hold v4 or v6 addr */
|
||||||
|
unsigned int svc_port;
|
||||||
|
} next;
|
||||||
|
uint8_t purge_conn; /* set to 1 if the network change will force a connection cleanup */
|
||||||
|
} safe;
|
||||||
|
/* no unsafe data */
|
||||||
|
};
|
||||||
|
|
||||||
/* Storage structure to load server-state lines from a flat file into
|
/* Storage structure to load server-state lines from a flat file into
|
||||||
* an ebtree, for faster processing
|
* an ebtree, for faster processing
|
||||||
*/
|
*/
|
||||||
|
@ -32,6 +32,7 @@ static struct event_hdl_sub_type_map event_hdl_sub_type_map[] = {
|
|||||||
{"SERVER_STATE", EVENT_HDL_SUB_SERVER_STATE},
|
{"SERVER_STATE", EVENT_HDL_SUB_SERVER_STATE},
|
||||||
{"SERVER_ADMIN", EVENT_HDL_SUB_SERVER_ADMIN},
|
{"SERVER_ADMIN", EVENT_HDL_SUB_SERVER_ADMIN},
|
||||||
{"SERVER_CHECK", EVENT_HDL_SUB_SERVER_CHECK},
|
{"SERVER_CHECK", EVENT_HDL_SUB_SERVER_CHECK},
|
||||||
|
{"SERVER_INETADDR", EVENT_HDL_SUB_SERVER_INETADDR},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* internal types (only used in this file) */
|
/* internal types (only used in this file) */
|
||||||
|
125
src/server.c
125
src/server.c
@ -234,6 +234,54 @@ void _srv_event_hdl_prepare_state(struct event_hdl_cb_data_server_state *cb_data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare SERVER_INETADDR event
|
||||||
|
*
|
||||||
|
* This special event will contain extra hints related to the addr change
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void _srv_event_hdl_prepare_inetaddr(struct event_hdl_cb_data_server_inetaddr *cb_data,
|
||||||
|
struct sockaddr_storage *prev_addr, unsigned int prev_port,
|
||||||
|
struct sockaddr_storage *next_addr, unsigned int next_port,
|
||||||
|
uint8_t purge_conn)
|
||||||
|
{
|
||||||
|
/* only INET families are supported */
|
||||||
|
BUG_ON((prev_addr->ss_family != AF_UNSPEC &&
|
||||||
|
prev_addr->ss_family != AF_INET && prev_addr->ss_family != AF_INET6) ||
|
||||||
|
(next_addr->ss_family != AF_UNSPEC &&
|
||||||
|
next_addr->ss_family != AF_INET && next_addr->ss_family != AF_INET6));
|
||||||
|
|
||||||
|
/* prev */
|
||||||
|
if (prev_addr->ss_family == AF_INET) {
|
||||||
|
cb_data->safe.prev.family = AF_INET;
|
||||||
|
cb_data->safe.prev.addr.v4.s_addr =
|
||||||
|
((struct sockaddr_in *)prev_addr)->sin_addr.s_addr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cb_data->safe.prev.family = AF_INET6;
|
||||||
|
memcpy(&cb_data->safe.prev.addr.v6.s6_addr,
|
||||||
|
((struct sockaddr_in6 *)prev_addr)->sin6_addr.s6_addr,
|
||||||
|
sizeof(struct sockaddr_in6));
|
||||||
|
}
|
||||||
|
cb_data->safe.prev.svc_port = prev_port;
|
||||||
|
|
||||||
|
/* next */
|
||||||
|
if (next_addr->ss_family == AF_INET) {
|
||||||
|
cb_data->safe.next.family = AF_INET;
|
||||||
|
cb_data->safe.next.addr.v4.s_addr =
|
||||||
|
((struct sockaddr_in *)next_addr)->sin_addr.s_addr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cb_data->safe.next.family = AF_INET6;
|
||||||
|
memcpy(&cb_data->safe.next.addr.v6.s6_addr,
|
||||||
|
((struct sockaddr_in6 *)next_addr)->sin6_addr.s6_addr,
|
||||||
|
sizeof(struct sockaddr_in6));
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_data->safe.next.svc_port = next_port;
|
||||||
|
|
||||||
|
cb_data->safe.purge_conn = purge_conn;
|
||||||
|
}
|
||||||
|
|
||||||
/* server event publishing helper: publish in both global and
|
/* server event publishing helper: publish in both global and
|
||||||
* server dedicated subscription list.
|
* server dedicated subscription list.
|
||||||
*/
|
*/
|
||||||
@ -3465,6 +3513,12 @@ struct server *server_find_best_match(struct proxy *bk, char *name, int id, int
|
|||||||
*/
|
*/
|
||||||
int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater)
|
int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *updater)
|
||||||
{
|
{
|
||||||
|
union {
|
||||||
|
struct event_hdl_cb_data_server_inetaddr addr;
|
||||||
|
struct event_hdl_cb_data_server common;
|
||||||
|
} cb_data;
|
||||||
|
struct sockaddr_storage new_addr;
|
||||||
|
|
||||||
/* save the new IP family & address if necessary */
|
/* save the new IP family & address if necessary */
|
||||||
switch (ip_sin_family) {
|
switch (ip_sin_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
@ -3523,16 +3577,25 @@ int srv_update_addr(struct server *s, void *ip, int ip_sin_family, const char *u
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* save the new IP family */
|
/* save the new IP family */
|
||||||
s->addr.ss_family = ip_sin_family;
|
new_addr.ss_family = ip_sin_family;
|
||||||
/* save the new IP address */
|
/* save the new IP address */
|
||||||
switch (ip_sin_family) {
|
switch (ip_sin_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
memcpy(&((struct sockaddr_in *)&s->addr)->sin_addr.s_addr, ip, 4);
|
memcpy(&((struct sockaddr_in *)&new_addr)->sin_addr.s_addr, ip, 4);
|
||||||
break;
|
break;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
memcpy(((struct sockaddr_in6 *)&s->addr)->sin6_addr.s6_addr, ip, 16);
|
memcpy(((struct sockaddr_in6 *)&new_addr)->sin6_addr.s6_addr, ip, 16);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_srv_event_hdl_prepare(&cb_data.common, s, 0);
|
||||||
|
_srv_event_hdl_prepare_inetaddr(&cb_data.addr, &s->addr, s->svc_port, &new_addr, s->svc_port, 0);
|
||||||
|
|
||||||
|
/* apply the new IP address */
|
||||||
|
ipcpy(&new_addr, &s->addr);
|
||||||
|
|
||||||
|
_srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_INETADDR, cb_data, s);
|
||||||
|
|
||||||
srv_set_dyncookie(s);
|
srv_set_dyncookie(s);
|
||||||
srv_set_addr_desc(s, 1);
|
srv_set_addr_desc(s, 1);
|
||||||
|
|
||||||
@ -3659,12 +3722,17 @@ const char *srv_update_check_addr_port(struct server *s, const char *addr, const
|
|||||||
*/
|
*/
|
||||||
const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater)
|
const char *srv_update_addr_port(struct server *s, const char *addr, const char *port, char *updater)
|
||||||
{
|
{
|
||||||
|
union {
|
||||||
|
struct event_hdl_cb_data_server_inetaddr addr;
|
||||||
|
struct event_hdl_cb_data_server common;
|
||||||
|
} cb_data;
|
||||||
struct sockaddr_storage sa;
|
struct sockaddr_storage sa;
|
||||||
int ret, port_change_required;
|
int ret;
|
||||||
char current_addr[INET6_ADDRSTRLEN];
|
char current_addr[INET6_ADDRSTRLEN];
|
||||||
uint16_t current_port, new_port;
|
uint16_t current_port, new_port;
|
||||||
struct buffer *msg;
|
struct buffer *msg;
|
||||||
int changed = 0;
|
int ip_change = 0;
|
||||||
|
int port_change = 0;
|
||||||
|
|
||||||
msg = get_trash_chunk();
|
msg = get_trash_chunk();
|
||||||
chunk_reset(msg);
|
chunk_reset(msg);
|
||||||
@ -3698,8 +3766,7 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
chunk_appendf(msg, "no need to change the addr");
|
chunk_appendf(msg, "no need to change the addr");
|
||||||
goto port;
|
goto port;
|
||||||
}
|
}
|
||||||
ipcpy(&sa, &s->addr);
|
ip_change = 1;
|
||||||
changed = 1;
|
|
||||||
|
|
||||||
/* update report for caller */
|
/* update report for caller */
|
||||||
chunk_printf(msg, "IP changed from '%s' to '%s'", current_addr, addr);
|
chunk_printf(msg, "IP changed from '%s' to '%s'", current_addr, addr);
|
||||||
@ -3716,9 +3783,6 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
/* collecting data currently setup */
|
/* collecting data currently setup */
|
||||||
current_port = s->svc_port;
|
current_port = s->svc_port;
|
||||||
|
|
||||||
/* check if PORT change is required */
|
|
||||||
port_change_required = 0;
|
|
||||||
|
|
||||||
sign = *port;
|
sign = *port;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
new_port = strtol(port, &endptr, 10);
|
new_port = strtol(port, &endptr, 10);
|
||||||
@ -3731,9 +3795,6 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
if (sign == '-' || (sign == '+')) {
|
if (sign == '-' || (sign == '+')) {
|
||||||
/* check if server currently uses port map */
|
/* check if server currently uses port map */
|
||||||
if (!(s->flags & SRV_F_MAPPORTS)) {
|
if (!(s->flags & SRV_F_MAPPORTS)) {
|
||||||
/* switch from fixed port to port map mandatorily triggers
|
|
||||||
* a port change */
|
|
||||||
port_change_required = 1;
|
|
||||||
/* check is configured
|
/* check is configured
|
||||||
* we're switching from a fixed port to a SRV_F_MAPPORTS (mapped) port
|
* we're switching from a fixed port to a SRV_F_MAPPORTS (mapped) port
|
||||||
* prevent PORT change if check doesn't have it's dedicated port while switching
|
* prevent PORT change if check doesn't have it's dedicated port while switching
|
||||||
@ -3742,22 +3803,23 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
chunk_appendf(msg, "can't change <port> to port map because it is incompatible with current health check port configuration (use 'port' statement from the 'server' directive.");
|
chunk_appendf(msg, "can't change <port> to port map because it is incompatible with current health check port configuration (use 'port' statement from the 'server' directive.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* switch from fixed port to port map mandatorily triggers
|
||||||
|
* a port change */
|
||||||
|
port_change = 1;
|
||||||
}
|
}
|
||||||
/* we're already using port maps */
|
/* we're already using port maps */
|
||||||
else {
|
else {
|
||||||
port_change_required = current_port != new_port;
|
port_change = current_port != new_port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* fixed port */
|
/* fixed port */
|
||||||
else {
|
else {
|
||||||
port_change_required = current_port != new_port;
|
port_change = current_port != new_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* applying PORT changes if required and update response message */
|
/* applying PORT changes if required and update response message */
|
||||||
if (port_change_required) {
|
if (port_change) {
|
||||||
/* apply new port */
|
uint16_t new_port_print = new_port;
|
||||||
s->svc_port = new_port;
|
|
||||||
changed = 1;
|
|
||||||
|
|
||||||
/* prepare message */
|
/* prepare message */
|
||||||
chunk_appendf(msg, "port changed from '");
|
chunk_appendf(msg, "port changed from '");
|
||||||
@ -3769,7 +3831,7 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
s->flags |= SRV_F_MAPPORTS;
|
s->flags |= SRV_F_MAPPORTS;
|
||||||
chunk_appendf(msg, "%c", sign);
|
chunk_appendf(msg, "%c", sign);
|
||||||
/* just use for result output */
|
/* just use for result output */
|
||||||
new_port = -new_port;
|
new_port_print = -new_port_print;
|
||||||
}
|
}
|
||||||
else if (sign == '+') {
|
else if (sign == '+') {
|
||||||
s->flags |= SRV_F_MAPPORTS;
|
s->flags |= SRV_F_MAPPORTS;
|
||||||
@ -3779,7 +3841,7 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
s->flags &= ~SRV_F_MAPPORTS;
|
s->flags &= ~SRV_F_MAPPORTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_appendf(msg, "%d'", new_port);
|
chunk_appendf(msg, "%d'", new_port_print);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
chunk_appendf(msg, "no need to change the port");
|
chunk_appendf(msg, "no need to change the port");
|
||||||
@ -3787,7 +3849,26 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (changed) {
|
if (ip_change || port_change) {
|
||||||
|
_srv_event_hdl_prepare(&cb_data.common, s, 0);
|
||||||
|
_srv_event_hdl_prepare_inetaddr(&cb_data.addr, &s->addr, s->svc_port,
|
||||||
|
((ip_change) ? &sa : &s->addr),
|
||||||
|
((port_change) ? new_port : s->svc_port),
|
||||||
|
1);
|
||||||
|
|
||||||
|
if (ip_change) {
|
||||||
|
/* apply new ip */
|
||||||
|
ipcpy(&sa, &s->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (port_change) {
|
||||||
|
/* apply new port */
|
||||||
|
s->svc_port = new_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
_srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_INETADDR, cb_data, s);
|
||||||
|
|
||||||
/* force connection cleanup on the given server */
|
/* force connection cleanup on the given server */
|
||||||
srv_cleanup_connections(s);
|
srv_cleanup_connections(s);
|
||||||
srv_set_dyncookie(s);
|
srv_set_dyncookie(s);
|
||||||
|
Loading…
Reference in New Issue
Block a user