From: Aurelien DARRAGON Date: Mon, 23 Jun 2025 20:32:08 +0000 (+0200) Subject: MAJOR: mailers: remove native mailers support X-Git-Tag: v3.3-dev2~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5694a9874436f4ed229cdb2ce3c8b30c9fdd4a3f;p=thirdparty%2Fhaproxy.git MAJOR: mailers: remove native mailers support As mentioned in 2.8 announce on the mailing list [1] and on the wiki [2] native mailers were deprecated and planned for removal in 3.3. Now is the time to drop the legacy code for native mailers which is based on a tcpcheck "hack" and cannot be maintained. Lua mailers should be used as a drop in replacement. Indeed, "mailers" and associated config directives are preserved because mailers config is exposed to Lua, which helps smoothing the transition from native mailers to Lua based ones. As a reminder, to keep mailers configuration working as before without making changes to the config file, simply add the line below to the global section: lua-load examples/lua/mailers.lua mailers.lua script (provided in the git repository, adjust path as needed) may be customized by users familiar with Lua, by default it emulates the behavior of the native (now removed) mailers. [1]: https://www.mail-archive.com/haproxy@formilux.org/msg43600.html [2]: https://github.com/haproxy/wiki/wiki/Breaking-changes --- diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index 347de92a0..7f9627452 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -1089,19 +1089,6 @@ Core class perform the heavy job in a dedicated task and allow remaining events to be processed more quickly. -.. js:function:: core.disable_legacy_mailers() - - **LEGACY** - - **context**: body, init - - Disable the sending of email alerts through the legacy email sending - function when mailers are used in the configuration. - - Use this when sending email alerts directly from lua. - - :see: :js:func:`Proxy.get_mailers()` - .. _proxy_class: Proxy class @@ -1247,10 +1234,6 @@ ProxyMailers class This class provides mailers config for a given proxy. - If sending emails directly from lua, please consider - :js:func:`core.disable_legacy_mailers()` to disable the email sending from - haproxy. (Or email alerts will be sent twice...) - .. js:attribute:: ProxyMailers.track_server_health Boolean set to true if the option "log-health-checks" is configured on diff --git a/examples/lua/mailers.lua b/examples/lua/mailers.lua index 47a835606..b1201fffd 100644 --- a/examples/lua/mailers.lua +++ b/examples/lua/mailers.lua @@ -3,7 +3,7 @@ -- Provides a pure lua alternative to tcpcheck mailers. -- -- To be loaded using "lua-load" from haproxy configuration to handle --- email-alerts directly from lua and disable legacy tcpcheck implementation. +-- email-alerts directly from lua local SYSLOG_LEVEL = { ["EMERG"] = 0, @@ -364,10 +364,6 @@ local function srv_event_add(event, data) mailers_track_server_events(data.reference) end - --- disable legacy email-alerts since email-alerts will be sent from lua directly -core.disable_legacy_mailers() - -- event subscriptions are purposely performed in an init function to prevent -- email alerts from being generated too early (when process is starting up) core.register_init(function() diff --git a/include/haproxy/mailers-t.h b/include/haproxy/mailers-t.h index 5df95a977..44f50fdf9 100644 --- a/include/haproxy/mailers-t.h +++ b/include/haproxy/mailers-t.h @@ -71,20 +71,5 @@ struct mailers { } timeout; }; -struct email_alert { - struct list list; - struct tcpcheck_rules rules; - struct server *srv; -}; - -struct email_alertq { - struct list email_alerts; - struct check check; /* Email alerts are implemented using existing check - * code even though they are not checks. This structure - * is as a parameter to the check code. - * Each check corresponds to a mailer */ - __decl_thread(HA_SPINLOCK_T lock); -}; - #endif /* _HAPROXY_MAILERS_T_H */ diff --git a/include/haproxy/mailers.h b/include/haproxy/mailers.h index ad5fd437f..509224ac6 100644 --- a/include/haproxy/mailers.h +++ b/include/haproxy/mailers.h @@ -32,12 +32,8 @@ #include extern struct mailers *mailers; -extern int send_email_disabled; int init_email_alert(struct mailers *mailers, struct proxy *p, char **err); void free_email_alert(struct proxy *p); -void send_email_alert(struct server *s, int priority, const char *format, ...) - __attribute__ ((format(printf, 3, 4))); - #endif /* _HAPROXY_MAILERS_H */ diff --git a/include/haproxy/thread-t.h b/include/haproxy/thread-t.h index 0d8cf3b39..2c99a4cb9 100644 --- a/include/haproxy/thread-t.h +++ b/include/haproxy/thread-t.h @@ -201,7 +201,6 @@ enum lock_label { SPOE_APPLET_LOCK, DNS_LOCK, PID_LIST_LOCK, - EMAIL_ALERTS_LOCK, PIPES_LOCK, TLSKEYS_REF_LOCK, AUTH_LOCK, diff --git a/src/check.c b/src/check.c index f20213167..2689eddc0 100644 --- a/src/check.c +++ b/src/check.c @@ -190,19 +190,16 @@ static void check_trace(enum trace_level level, uint64_t mask, if (!check || src->verbosity < CHK_VERB_CLEAN) return; - if (srv) { - chunk_appendf(&trace_buf, " : [%c] SRV=%s", - ((check->type == PR_O2_EXT_CHK) ? 'E' : (check->state & CHK_ST_AGENT ? 'A' : 'H')), - srv->id); + BUG_ON(!srv); + chunk_appendf(&trace_buf, " : [%c] SRV=%s", + ((check->type == PR_O2_EXT_CHK) ? 'E' : (check->state & CHK_ST_AGENT ? 'A' : 'H')), + srv->id); - chunk_appendf(&trace_buf, " status=%d/%d %s exp=%d", - (check->health >= check->rise) ? check->health - check->rise + 1 : check->health, - (check->health >= check->rise) ? check->fall : check->rise, - (check->health >= check->rise) ? (srv->uweight ? "UP" : "DRAIN") : "DOWN", - (check->task->expire ? TICKS_TO_MS(check->task->expire - now_ms) : 0)); - } - else - chunk_appendf(&trace_buf, " : [EMAIL]"); + chunk_appendf(&trace_buf, " status=%d/%d %s exp=%d", + (check->health >= check->rise) ? check->health - check->rise + 1 : check->health, + (check->health >= check->rise) ? check->fall : check->rise, + (check->health >= check->rise) ? (srv->uweight ? "UP" : "DRAIN") : "DOWN", + (check->task->expire ? TICKS_TO_MS(check->task->expire - now_ms) : 0)); switch (check->result) { case CHK_RES_NEUTRAL: res = "-"; break; @@ -564,7 +561,6 @@ void set_server_check_status(struct check *check, short status, const char *desc ha_warning("%s.\n", trash.area); send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.area); - send_email_alert(s, LOG_INFO, "%s", trash.area); } } @@ -1057,17 +1053,15 @@ int wake_srv_chk(struct stconn *sc) { struct connection *conn; struct check *check = __sc_check(sc); - struct email_alertq *q = container_of(check, typeof(*q), check); int ret = 0; + BUG_ON(!check->server); + TRACE_ENTER(CHK_EV_HCHK_WAKE, check); if (check->result != CHK_RES_UNKNOWN) goto end; - if (check->server) - HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock); - else - HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock); + HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock); /* we may have to make progress on the TCP checks */ ret = tcpcheck_main(check); @@ -1099,10 +1093,7 @@ int wake_srv_chk(struct stconn *sc) task_queue(check->task); } - if (check->server) - HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock); - else - HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock); + HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock); end: TRACE_LEAVE(CHK_EV_HCHK_WAKE, check); diff --git a/src/hlua.c b/src/hlua.c index 8e1a54d3a..25df95690 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -2384,21 +2384,6 @@ __LJMP static int hlua_core_get_var(lua_State *L) return MAY_LJMP(hlua_smp2lua(L, &smp)); } -/* This function disables the sending of email through the - * legacy email sending function which is implemented using - * checks. - * - * It may not be used during runtime. - */ -__LJMP static int hlua_disable_legacy_mailers(lua_State *L) -{ - if (hlua_gethlua(L)) - WILL_LJMP(luaL_error(L, "disable_legacy_mailers: " - "not available outside of init or body context")); - send_email_disabled = 1; - return 0; -} - /* A class is a lot of memory that contain data. This data can be a table, * an integer or user data. This data is associated with a metatable. This * metatable have an original version registered in the global context with @@ -14123,7 +14108,6 @@ lua_State *hlua_init_state(int thread_num) hlua_class_function(L, "Warning", hlua_log_warning); hlua_class_function(L, "Alert", hlua_log_alert); hlua_class_function(L, "done", hlua_done); - hlua_class_function(L, "disable_legacy_mailers", hlua_disable_legacy_mailers); hlua_fcn_reg_core_fcn(L); lua_setglobal(L, "core"); diff --git a/src/mailers.c b/src/mailers.c index 1e61842f4..7d3fe3839 100644 --- a/src/mailers.c +++ b/src/mailers.c @@ -15,92 +15,17 @@ #include #include -#include #include -#include #include -#include #include #include #include -#include -#include #include #include struct mailers *mailers = NULL; -/* Set to 1 to disable email sending through checks even if the - * mailers are configured to do so. (e.g.: disable from lua) - */ -int send_email_disabled = 0; - -DECLARE_STATIC_POOL(pool_head_email_alert, "email_alert", sizeof(struct email_alert)); - -/****************************** Email alerts ******************************/ -/* NOTE: It may be pertinent to use an applet to handle email alerts */ -/* instead of a tcp-check ruleset */ -/**************************************************************************/ -void email_alert_free(struct email_alert *alert) -{ - struct tcpcheck_rule *rule, *back; - - if (!alert) - return; - - if (alert->rules.list) { - list_for_each_entry_safe(rule, back, alert->rules.list, list) { - LIST_DELETE(&rule->list); - free_tcpcheck(rule, 1); - } - free_tcpcheck_vars(&alert->rules.preset_vars); - ha_free(&alert->rules.list); - } - pool_free(pool_head_email_alert, alert); -} - -static struct task *process_email_alert(struct task *t, void *context, unsigned int state) -{ - struct check *check = context; - struct email_alertq *q; - struct email_alert *alert; - - q = container_of(check, typeof(*q), check); - - HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock); - while (1) { - if (!(check->state & CHK_ST_ENABLED)) { - if (LIST_ISEMPTY(&q->email_alerts)) { - /* All alerts processed, queue the task */ - t->expire = TICK_ETERNITY; - task_queue(t); - goto end; - } - - alert = LIST_NEXT(&q->email_alerts, typeof(alert), list); - LIST_DELETE(&alert->list); - t->expire = tick_add(now_ms, 0); - check->tcpcheck_rules = &alert->rules; - check->status = HCHK_STATUS_INI; - check->state |= CHK_ST_ENABLED; - } - - process_chk(t, context, state); - if (check->state & CHK_ST_INPROGRESS) - break; - - alert = container_of(check->tcpcheck_rules, typeof(*alert), rules); - email_alert_free(alert); - check->tcpcheck_rules = NULL; - check->server = NULL; - check->state &= ~CHK_ST_ENABLED; - } - end: - HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock); - return t; -} - /* Initializes mailer alerts for the proxy

using parameters. * * The function returns 1 in success case, otherwise, it returns 0 and err is @@ -108,73 +33,11 @@ static struct task *process_email_alert(struct task *t, void *context, unsigned */ int init_email_alert(struct mailers *mls, struct proxy *p, char **err) { - struct mailer *mailer; - struct email_alertq *queues; - const char *err_str; - int i = 0; - - if (!send_email_disabled) - ha_warning("Legacy mailers used by %s '%s' will not be supported anymore in version 3.3. You should use Lua to send email-alerts, see 'examples/lua/mailers.lua' file.\n", - proxy_type_str(p), p->id); - - if ((queues = calloc(mls->count, sizeof(*queues))) == NULL) { - memprintf(err, "out of memory while allocating mailer alerts queues"); - goto fail_no_queue; - } - - for (mailer = mls->mailer_list; mailer; i++, mailer = mailer->next) { - struct email_alertq *q = &queues[i]; - struct check *check = &q->check; - struct task *t; - - LIST_INIT(&q->email_alerts); - HA_SPIN_INIT(&q->lock); - check->obj_type = OBJ_TYPE_CHECK; - check->inter = mls->timeout.mail; - check->rise = DEF_AGENT_RISETIME; - check->proxy = p; - check->fall = DEF_AGENT_FALLTIME; - if ((err_str = init_check(check, PR_O2_TCPCHK_CHK))) { - memprintf(err, "%s", err_str); - goto error; - } - - check->xprt = mailer->xprt; - check->addr = mailer->addr; - check->port = get_host_port(&mailer->addr); - - if ((t = task_new_anywhere()) == NULL) { - memprintf(err, "out of memory while allocating mailer alerts task"); - goto error; - } - - check->task = t; - t->process = process_email_alert; - t->context = check; - - /* check this in one ms */ - t->expire = TICK_ETERNITY; - check->start = now_ns; - task_queue(t); - } - mls->users++; free(p->email_alert.mailers.name); p->email_alert.mailers.m = mls; p->email_alert.flags |= PR_EMAIL_ALERT_RESOLVED; - p->email_alert.queues = queues; return 0; - - error: - for (i = 0; i < mls->count; i++) { - struct email_alertq *q = &queues[i]; - struct check *check = &q->check; - - free_check(check); - } - free(queues); - fail_no_queue: - return 1; } void free_email_alert(struct proxy *p) @@ -185,159 +48,3 @@ void free_email_alert(struct proxy *p) ha_free(&p->email_alert.to); ha_free(&p->email_alert.myhostname); } - -static int enqueue_one_email_alert(struct proxy *p, struct server *s, - struct email_alertq *q, const char *msg) -{ - struct email_alert *alert; - struct tcpcheck_rule *tcpcheck; - struct check *check = &q->check; - - if ((alert = pool_alloc(pool_head_email_alert)) == NULL) - goto error; - LIST_INIT(&alert->list); - alert->rules.flags = TCPCHK_RULES_TCP_CHK; - alert->rules.list = calloc(1, sizeof(*alert->rules.list)); - if (!alert->rules.list) - goto error; - LIST_INIT(alert->rules.list); - LIST_INIT(&alert->rules.preset_vars); /* unused for email alerts */ - alert->srv = s; - - if ((tcpcheck = pool_zalloc(pool_head_tcpcheck_rule)) == NULL) - goto error; - tcpcheck->action = TCPCHK_ACT_CONNECT; - tcpcheck->comment = NULL; - - LIST_APPEND(alert->rules.list, &tcpcheck->list); - - if (!add_tcpcheck_expect_str(&alert->rules, "220 ")) - goto error; - - { - const char * const strs[4] = { "HELO ", p->email_alert.myhostname, "\r\n" }; - if (!add_tcpcheck_send_strs(&alert->rules, strs)) - goto error; - } - - if (!add_tcpcheck_expect_str(&alert->rules, "250 ")) - goto error; - - { - const char * const strs[4] = { "MAIL FROM:<", p->email_alert.from, ">\r\n" }; - if (!add_tcpcheck_send_strs(&alert->rules, strs)) - goto error; - } - - if (!add_tcpcheck_expect_str(&alert->rules, "250 ")) - goto error; - - { - const char * const strs[4] = { "RCPT TO:<", p->email_alert.to, ">\r\n" }; - if (!add_tcpcheck_send_strs(&alert->rules, strs)) - goto error; - } - - if (!add_tcpcheck_expect_str(&alert->rules, "250 ")) - goto error; - - { - const char * const strs[2] = { "DATA\r\n" }; - if (!add_tcpcheck_send_strs(&alert->rules, strs)) - goto error; - } - - if (!add_tcpcheck_expect_str(&alert->rules, "354 ")) - goto error; - - { - struct tm tm; - char datestr[48]; - const char * const strs[18] = { - "From: ", p->email_alert.from, "\r\n", - "To: ", p->email_alert.to, "\r\n", - "Date: ", datestr, "\r\n", - "Subject: [HAProxy Alert] ", msg, "\r\n", - "\r\n", - msg, "\r\n", - "\r\n", - ".\r\n", - NULL - }; - - get_localtime(date.tv_sec, &tm); - - if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %T %z (%Z)", &tm) == 0) { - goto error; - } - - if (!add_tcpcheck_send_strs(&alert->rules, strs)) - goto error; - } - - if (!add_tcpcheck_expect_str(&alert->rules, "250 ")) - goto error; - - { - const char * const strs[2] = { "QUIT\r\n" }; - if (!add_tcpcheck_send_strs(&alert->rules, strs)) - goto error; - } - - if (!add_tcpcheck_expect_str(&alert->rules, "221 ")) - goto error; - - HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock); - task_wakeup(check->task, TASK_WOKEN_MSG); - LIST_APPEND(&q->email_alerts, &alert->list); - HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock); - return 1; - -error: - email_alert_free(alert); - return 0; -} - -static void enqueue_email_alert(struct proxy *p, struct server *s, const char *msg) -{ - int i; - struct mailer *mailer; - - for (i = 0, mailer = p->email_alert.mailers.m->mailer_list; - i < p->email_alert.mailers.m->count; i++, mailer = mailer->next) { - if (!enqueue_one_email_alert(p, s, &p->email_alert.queues[i], msg)) { - ha_alert("Email alert [%s] could not be enqueued: out of memory\n", p->id); - return; - } - } - - return; -} - -/* - * Send email alert if configured. - */ -void send_email_alert(struct server *s, int level, const char *format, ...) -{ - va_list argp; - char buf[1024]; - int len; - struct proxy *p = s->proxy; - - if (send_email_disabled) - return; - - if (!p->email_alert.mailers.m || level > p->email_alert.level || format == NULL) - return; - - va_start(argp, format); - len = vsnprintf(buf, sizeof(buf), format, argp); - va_end(argp); - - if (len < 0 || len >= sizeof(buf)) { - ha_alert("Email alert [%s] could not format message\n", p->id); - return; - } - - enqueue_email_alert(p, s, buf); -} diff --git a/src/server.c b/src/server.c index 45b079e9d..294ba7e99 100644 --- a/src/server.c +++ b/src/server.c @@ -6592,8 +6592,6 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus log_level = srv_was_stopping ? LOG_NOTICE : LOG_ALERT; send_log(s->proxy, log_level, "%s.\n", tmptrash->area); - send_email_alert(s, log_level, "%s", - tmptrash->area); free_trash_chunk(tmptrash); } } @@ -6657,8 +6655,6 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus ha_warning("%s.\n", tmptrash->area); send_log(s->proxy, LOG_NOTICE, "%s.\n", tmptrash->area); - send_email_alert(s, LOG_NOTICE, "%s", - tmptrash->area); free_trash_chunk(tmptrash); } } @@ -6918,8 +6914,6 @@ static int _srv_update_status_adm(struct server *s, enum srv_adm_st_chg_cause ca ha_warning("%s.\n", tmptrash->area); send_log(s->proxy, LOG_NOTICE, "%s.\n", tmptrash->area); - send_email_alert(s, LOG_NOTICE, "%s", - tmptrash->area); } free_trash_chunk(tmptrash); } diff --git a/src/thread.c b/src/thread.c index 0bdb0f94d..8c0c5c294 100644 --- a/src/thread.c +++ b/src/thread.c @@ -421,7 +421,6 @@ const char *lock_label(enum lock_label label) case SPOE_APPLET_LOCK: return "SPOE_APPLET"; case DNS_LOCK: return "DNS"; case PID_LIST_LOCK: return "PID_LIST"; - case EMAIL_ALERTS_LOCK: return "EMAIL_ALERTS"; case PIPES_LOCK: return "PIPES"; case TLSKEYS_REF_LOCK: return "TLSKEYS_REF"; case AUTH_LOCK: return "AUTH";