MINOR: hlua: expose SERVER_STATE event
Exposing SERVER_STATE event in lua and updating the documentation.
diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst
index d470491..333c351 100644
--- a/doc/lua-api/index.rst
+++ b/doc/lua-api/index.rst
@@ -946,10 +946,14 @@
* **SERVER_DEL**: when a server is removed
* **SERVER_DOWN**: when a server state goes from UP to DOWN
* **SERVER_UP**: when a server state goes from DOWN to UP
+ * **SERVER_STATE**: when a server state changes
.. Note::
- You may also use **SERVER** in **event_types** to subscribe to all server
- events types at once.
+ Use **SERVER** in **event_types** to subscribe to all server events types
+ at once. Note that this should only be used for testing purposes since a
+ single event source could result in multiple events types being generated.
+ (e.g.: SERVER_STATE will always be generated for each SERVER_DOWN or
+ SERVER_UP)
The prototype of the Lua function used as argument is:
@@ -1522,6 +1526,111 @@
(Will never be set for SERVER_DEL event since the server does not exist
anymore)
+.. js:attribute:: ServerEvent.state
+
+ A :ref:`server_event_state_class`
+
+ .. Note::
+ Only available for SERVER_STATE event
+
+.. _server_event_checkres_class:
+
+ServerEventCheckRes class
+=========================
+
+.. js:class:: ServerEventCheckRes
+
+This class describes the result of a server's check.
+
+.. js:attribute:: ServerEventCheckRes.result
+
+ Effective check result.
+
+ Check result is a string and will be set to one of the following values:
+ - "FAILED": the check failed
+ - "PASSED": the check succeeded
+ - "CONDPASS": the check conditionally passed
+
+.. js:attribute:: ServerEventCheckRes.agent
+
+ Boolean set to true if the check is an agent check.
+ Else it is a health check.
+
+.. js:attribute:: ServerEventCheckRes.duration
+
+ Check's duration in milliseconds
+
+.. js:attribute:: ServerEventCheckRes.reason
+
+ Check's status. An array containing three fields:
+ - **short**: a string representing check status short name
+ - **desc**: a string representing check status description
+ - **code**: an integer, this extra information is provided for checks
+ that went through the data analysis stage (>= layer 5)
+
+.. js:attribute:: ServerEventCheckRes.health
+
+ An array containing values about check's health (integers):
+ - **cur**: current health counter:
+ - 0 to (**rise** - 1) = BAD
+ - **rise** to (**rise** + **fall** - 1) = GOOD
+ - **rise**: server will be considered as operational after **rise**
+ consecutive successful checks
+ - **fall**: server will be considered as dead after **fall** consecutive
+ unsuccessful checks
+
+.. _server_event_state_class:
+
+ServerEventState class
+======================
+
+.. js:class:: ServerEventState
+
+This class contains additional info related to **SERVER_STATE** event.
+
+.. js:attribute:: ServerEventState.admin
+
+ Boolean set to true if the server state change is due to an administrative
+ change. Else it is an operational change.
+
+.. js:attribute:: ServerEventState.check
+
+ A :ref:`server_event_checkres_class`, provided if the state change is
+ due to a server check (must be an operational change).
+
+.. js:attribute:: ServerEventState.cause
+
+ Printable state change cause. Might be empty.
+
+.. js:attribute:: ServerEventState.new_state
+
+ New server state due to operational or admin change.
+
+ It is a string that can be any of the following values:
+ - "STOPPED": The server is down
+ - "STOPPING": The server is up but soft-stopping
+ - "STARTING": The server is warming up
+ - "RUNNING": The server is fully up
+
+.. js:attribute:: ServerEventState.old_state
+
+ Previous server state prior to the operational or admin change.
+
+ Can be any value described in **new_state**, but they should differ.
+
+.. js:attribute:: ServerEventState.requeued
+
+ Number of connections that were requeued due to the server state change.
+
+ For a server going DOWN: it is the number of pending server connections
+ that are requeued to the backend (such connections will be redispatched
+ to any server that is suitable according to the configured load balancing
+ algorithm).
+
+ For a server doing UP: it is the number of pending connections on the
+ backend that may be redispatched to the server according to the load
+ balancing algorithm that is in use.
+
.. _concat_class:
Concat class
diff --git a/src/hlua.c b/src/hlua.c
index 973e277..34ad3c8 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -66,6 +66,7 @@
#include <haproxy/vars.h>
#include <haproxy/xref.h>
#include <haproxy/event_hdl.h>
+#include <haproxy/check.h>
/* Lua uses longjmp to perform yield or throwing errors. This
* macro is used only for identifying the function that can
@@ -9029,6 +9030,67 @@
}
}
+__LJMP static void hlua_event_hdl_cb_push_event_checkres(lua_State *L,
+ struct event_hdl_cb_data_server_checkres *check)
+{
+ lua_pushstring(L, "agent");
+ lua_pushboolean(L, check->agent);
+ lua_settable(L, -3);
+ lua_pushstring(L, "result");
+ switch (check->result) {
+ case CHK_RES_FAILED:
+ lua_pushstring(L, "FAILED");
+ break;
+ case CHK_RES_PASSED:
+ lua_pushstring(L, "PASSED");
+ break;
+ case CHK_RES_CONDPASS:
+ lua_pushstring(L, "CONDPASS");
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+ lua_settable(L, -3);
+
+ lua_pushstring(L, "duration");
+ lua_pushinteger(L, check->duration);
+ lua_settable(L, -3);
+
+ lua_pushstring(L, "reason");
+ lua_newtable(L);
+
+ lua_pushstring(L, "short");
+ lua_pushstring(L, get_check_status_info(check->reason.status));
+ lua_settable(L, -3);
+ lua_pushstring(L, "desc");
+ lua_pushstring(L, get_check_status_description(check->reason.status));
+ lua_settable(L, -3);
+ if (check->reason.status >= HCHK_STATUS_L57DATA) {
+ /* code only available when the check reached data analysis stage */
+ lua_pushstring(L, "code");
+ lua_pushinteger(L, check->reason.code);
+ lua_settable(L, -3);
+ }
+
+ lua_settable(L, -3); /* reason table */
+
+ lua_pushstring(L, "health");
+ lua_newtable(L);
+
+ lua_pushstring(L, "cur");
+ lua_pushinteger(L, check->health.cur);
+ lua_settable(L, -3);
+ lua_pushstring(L, "rise");
+ lua_pushinteger(L, check->health.rise);
+ lua_settable(L, -3);
+ lua_pushstring(L, "fall");
+ lua_pushinteger(L, check->health.fall);
+ lua_settable(L, -3);
+
+ lua_settable(L, -3); /* health table */
+}
+
/* This function pushes various arguments such as event type and event data to
* the lua function that will be called to consume the event.
*/
@@ -9072,6 +9134,73 @@
lua_pushinteger(hlua->T, e_server->safe.proxy_uuid);
lua_settable(hlua->T, -3);
+ /* special events, fetch additional info with explicit type casting */
+ if (event_hdl_sub_type_equal(EVENT_HDL_SUB_SERVER_STATE, event)) {
+ struct event_hdl_cb_data_server_state *state = data;
+ int it;
+
+ if (!lua_checkstack(hlua->T, 20))
+ WILL_LJMP(luaL_error(hlua->T, "Lua out of memory error."));
+
+ /* state subclass */
+ lua_pushstring(hlua->T, "state");
+ lua_newtable(hlua->T);
+
+ lua_pushstring(hlua->T, "admin");
+ lua_pushboolean(hlua->T, state->safe.type);
+ lua_settable(hlua->T, -3);
+
+ /* is it because of a check ? */
+ if (!state->safe.type &&
+ (state->safe.op_st_chg.cause == SRV_OP_STCHGC_HEALTH ||
+ state->safe.op_st_chg.cause == SRV_OP_STCHGC_AGENT)) {
+ /* yes, provide check result */
+ lua_pushstring(hlua->T, "check");
+ lua_newtable(hlua->T);
+ hlua_event_hdl_cb_push_event_checkres(hlua->T, &state->safe.op_st_chg.check);
+ lua_settable(hlua->T, -3); /* check table */
+ }
+
+ lua_pushstring(hlua->T, "cause");
+ if (state->safe.type)
+ lua_pushstring(hlua->T, srv_adm_st_chg_cause(state->safe.adm_st_chg.cause));
+ else
+ lua_pushstring(hlua->T, srv_op_st_chg_cause(state->safe.op_st_chg.cause));
+ lua_settable(hlua->T, -3);
+
+ /* old_state, new_state */
+ for (it = 0; it < 2; it++) {
+ enum srv_state srv_state = (!it) ? state->safe.old_state : state->safe.new_state;
+
+ lua_pushstring(hlua->T, (!it) ? "old_state" : "new_state");
+ switch (srv_state) {
+ case SRV_ST_STOPPED:
+ lua_pushstring(hlua->T, "STOPPED");
+ break;
+ case SRV_ST_STOPPING:
+ lua_pushstring(hlua->T, "STOPPING");
+ break;
+ case SRV_ST_STARTING:
+ lua_pushstring(hlua->T, "STARTING");
+ break;
+ case SRV_ST_RUNNING:
+ lua_pushstring(hlua->T, "RUNNING");
+ break;
+ default:
+ lua_pushnil(hlua->T);
+ break;
+ }
+ lua_settable(hlua->T, -3);
+ }
+
+ /* requeued */
+ lua_pushstring(hlua->T, "requeued");
+ lua_pushinteger(hlua->T, state->safe.requeued);
+ lua_settable(hlua->T, -3);
+
+ lua_settable(hlua->T, -3); /* state table */
+ }
+
/* attempt to provide reference server object
* (if it wasn't removed yet, SERVER_DEL will never succeed here)
*/