]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: check/spoe: Use SPOP multiplexer to perform SPOP health-checks
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 4 Jul 2024 12:30:23 +0000 (14:30 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 12 Jul 2024 13:27:04 +0000 (15:27 +0200)
The SPOP health-checks are now performed using the SPOP multiplexer. This
will be fixed later, but for now, it is considered as a L4 health-check and
no specific status code is reported. It means the corresponding vtest script
is marked as broken for now.

Functionnaly speaking, the same is performed. A connection is opened, a
HELLO frame is sent to the agent and we wait for the HELLO frame from the
agent in reply. But only L4OK, L4KO or L4TOUT will be reported.

The related issue is #2502.

include/haproxy/check.h
reg-tests/checks/spop-check.vtc
src/flt_spoe.c
src/tcpcheck.c

index c90d3e77fc19da077b89812d6c1639f2e611c787..842d7f7dda71925930e22446de40ae14ca837607 100644 (file)
@@ -89,10 +89,6 @@ int init_srv_check(struct server *srv);
 int init_srv_agent_check(struct server *srv);
 int start_check_task(struct check *check, int mininter, int nbcheck, int srvpos);
 
-/* Declared here, but the definitions are in flt_spoe.c */
-int spoe_prepare_healthcheck_request(char **req, int *len);
-int spoe_handle_healthcheck_response(char *frame, size_t size, char *err, int errlen);
-
 int set_srv_agent_send(struct server *srv, const char *send);
 
 /* set agent addr and appropriate flag */
index 202476cc71f590b07e730457fd4a4d426f2e0b11..7cd71c78f7e0facfdfd70f366661a12abee63cbe 100644 (file)
@@ -2,6 +2,8 @@ varnishtest "Health-checks: SPOP health-check"
 #REGTEST_TYPE=slow
 feature ignore_unknown_macro
 
+#REGTEST_TYPE=broken
+
 # This scripts tests health-checks for SPOE agent, enabled using
 # "option spop-check" line. A intermediate listener is used to validate
 # the request because it is impossible with VTEST to read and match raw
index edc3169b00f1e6beef557948828b7fa8f96a6d6e..a873dccf55813848664ea7c3b14b0579be275138 100644 (file)
@@ -970,80 +970,6 @@ spoe_handle_agentack_frame(struct appctx *appctx, char *frame, size_t size)
        return (p - frame);
 }
 
-/* This function is used in cfgparse.c and declared in proto/checks.h. It
- * prepare the request to send to agents during a healthcheck. It returns 0 on
- * success and -1 if an error occurred. */
-int
-spoe_prepare_healthcheck_request(char **req, int *len)
-{
-       struct appctx      appctx;
-       struct spoe_appctx spoe_appctx;
-       char  *frame, *end, buf[SPOP_MAX_FRAME_SIZE+4];
-       size_t sz;
-       int    ret;
-
-       memset(&appctx, 0, sizeof(appctx));
-       memset(&spoe_appctx, 0, sizeof(spoe_appctx));
-       memset(buf, 0, sizeof(buf));
-
-       appctx.svcctx = &spoe_appctx;
-       SPOE_APPCTX(&appctx)->max_frame_size = SPOP_MAX_FRAME_SIZE;
-
-       frame = buf+4; /* Reserved the 4 first bytes for the frame size */
-       end   = frame + SPOP_MAX_FRAME_SIZE;
-
-       ret = spoe_prepare_hahello_frame(&appctx, frame, SPOP_MAX_FRAME_SIZE);
-       if (ret <= 0)
-               return -1;
-       frame += ret;
-
-       /* Add "healthcheck" K/V item */
-       sz = SLEN(HEALTHCHECK_KEY);
-       if (spoe_encode_buffer(HEALTHCHECK_KEY, sz, &frame, end) == -1)
-               return -1;
-       *frame++ = (SPOP_DATA_T_BOOL | SPOP_DATA_FL_TRUE);
-
-       *len = frame - buf;
-       sz   = htonl(*len - 4);
-       memcpy(buf, (char *)&sz, 4);
-
-       if ((*req = malloc(*len)) == NULL)
-               return -1;
-       memcpy(*req, buf, *len);
-       return 0;
-}
-
-/* This function is used in checks.c and declared in proto/checks.h. It decode
- * the response received from an agent during a healthcheck. It returns 0 on
- * success and -1 if an error occurred. */
-int
-spoe_handle_healthcheck_response(char *frame, size_t size, char *err, int errlen)
-{
-       struct appctx      appctx;
-       struct spoe_appctx spoe_appctx;
-
-       memset(&appctx, 0, sizeof(appctx));
-       memset(&spoe_appctx, 0, sizeof(spoe_appctx));
-
-       appctx.svcctx = &spoe_appctx;
-       SPOE_APPCTX(&appctx)->max_frame_size = SPOP_MAX_FRAME_SIZE;
-
-       if (*frame == SPOP_FRM_T_AGENT_DISCON) {
-               spoe_handle_agentdiscon_frame(&appctx, frame, size);
-               goto error;
-       }
-       if (spoe_handle_agenthello_frame(&appctx, frame, size) <= 0)
-               goto error;
-
-       return 0;
-
-  error:
-       if (SPOE_APPCTX(&appctx)->status_code >= SPOP_ERR_ENTRIES)
-               SPOE_APPCTX(&appctx)->status_code = SPOP_ERR_UNKNOWN;
-       strncpy(err, spoe_frm_err_reasons[SPOE_APPCTX(&appctx)->status_code], errlen);
-       return -1;
-}
-
 /* Send a SPOE frame to an agent. It returns -1 when an error occurred, 0 when
  * the frame can be ignored, 1 to retry later, and the frame length on
  * success. */
index e820fdc2e82df65b060c7d3e065138595142e7de..ccfc797625c420618dde8faa8a4e5359f8ca54bc 100644 (file)
@@ -759,55 +759,6 @@ enum tcpcheck_eval_ret tcpcheck_ldap_expect_bindrsp(struct check *check, struct
        goto out;
 }
 
-/* Custom tcp-check expect function to parse and validate the SPOP hello agent
- * frame. Returns TCPCHK_EVAL_WAIT to wait for more data, TCPCHK_EVAL_CONTINUE
- * to evaluate the next rule or TCPCHK_EVAL_STOP if an error occurred.
- */
-enum tcpcheck_eval_ret tcpcheck_spop_expect_agenthello(struct check *check, struct tcpcheck_rule *rule, int last_read)
-{
-       enum tcpcheck_eval_ret ret = TCPCHK_EVAL_CONTINUE;
-       enum healthcheck_status status;
-       struct buffer *msg = NULL;
-       struct ist desc = IST_NULL;
-       unsigned int framesz;
-
-       TRACE_ENTER(CHK_EV_TCPCHK_EXP, check);
-
-       memcpy(&framesz, b_head(&check->bi), 4);
-       framesz = ntohl(framesz);
-
-       if (!last_read && b_data(&check->bi) < (4+framesz))
-               goto wait_more_data;
-
-       memset(b_orig(&trash), 0, b_size(&trash));
-       if (spoe_handle_healthcheck_response(b_peek(&check->bi, 4), framesz, b_orig(&trash), HCHK_DESC_LEN) == -1) {
-               status = HCHK_STATUS_L7RSP;
-               desc = ist2(b_orig(&trash), strlen(b_orig(&trash)));
-               goto error;
-       }
-
-       status = ((rule->expect.ok_status != HCHK_STATUS_UNKNOWN) ? rule->expect.ok_status : HCHK_STATUS_L7OKD);
-       set_server_check_status(check, status, "SPOA server is ok");
-
-  out:
-       free_trash_chunk(msg);
-       TRACE_LEAVE(CHK_EV_TCPCHK_EXP, check, 0, 0, (size_t[]){ret});
-       return ret;
-
-  error:
-       ret = TCPCHK_EVAL_STOP;
-       msg = alloc_trash_chunk();
-       if (msg)
-               tcpcheck_expect_onerror_message(msg, check, rule, 0, desc);
-       set_server_check_status(check, status, (msg ? b_head(msg) : NULL));
-       goto out;
-
-  wait_more_data:
-       TRACE_DEVEL("waiting for more data", CHK_EV_TCPCHK_EXP, check);
-       ret = TCPCHK_EVAL_WAIT;
-       goto out;
-}
-
 /* Custom tcp-check expect function to parse and validate the agent-check
  * reply. Returns TCPCHK_EVAL_WAIT to wait for more data, TCPCHK_EVAL_CONTINUE
  * to evaluate the next rule or TCPCHK_EVAL_STOP if an error occurred.
@@ -1239,9 +1190,7 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec
                else if ((connect->options & TCPCHK_OPT_DEFAULT_CONNECT) && check->mux_proto)
                        mux_ops = check->mux_proto->mux;
                else {
-                       int mode = ((check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK) == TCPCHK_RULES_HTTP_CHK
-                                   ? PROTO_MODE_HTTP
-                                   : PROTO_MODE_TCP);
+                       int mode = tcpchk_rules_type_to_proto_mode(check->tcpcheck_rules->flags);
 
                        mux_ops = conn_get_best_mux(conn, IST_NULL, PROTO_SIDE_BE, mode);
                }
@@ -4842,10 +4791,7 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
 {
        struct tcpcheck_ruleset *rs = NULL;
        struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
-       struct tcpcheck_rule *chk;
-       char *spop_req = NULL;
-       char *errmsg = NULL;
-       int spop_len = 0, err_code = 0;
+       int err_code = 0;
 
        if (warnifnotcap(curpx, PR_CAP_BE, file, line, args[cur_arg+1], NULL))
                err_code |= ERR_WARN;
@@ -4860,7 +4806,6 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
        rules->list  = NULL;
        rules->flags = 0;
 
-
        rs = find_tcpcheck_ruleset("*spop-check");
        if (rs)
                goto ruleset_found;
@@ -4871,41 +4816,12 @@ int proxy_parse_spop_check_opt(char **args, int cur_arg, struct proxy *curpx, co
                goto error;
        }
 
-       if (spoe_prepare_healthcheck_request(&spop_req, &spop_len) == -1) {
-               ha_alert("parsing [%s:%d] : out of memory.\n", file, line);
-               goto error;
-       }
-       chunk_reset(&trash);
-       dump_binary(&trash, spop_req, spop_len);
-       trash.area[trash.data] = '\0';
-
-       chk = parse_tcpcheck_send((char *[]){"tcp-check", "send-binary", b_head(&trash), ""},
-                                 1, curpx, &rs->rules, file, line, &errmsg);
-       if (!chk) {
-               ha_alert("parsing [%s:%d] : %s\n", file, line, errmsg);
-               goto error;
-       }
-       chk->index = 0;
-       LIST_APPEND(&rs->rules, &chk->list);
-
-       chk = parse_tcpcheck_expect((char *[]){"tcp-check", "expect", "custom", "min-recv", "4", ""},
-                                   1, curpx, &rs->rules, TCPCHK_RULES_SPOP_CHK, file, line, &errmsg);
-       if (!chk) {
-               ha_alert("parsing [%s:%d] : %s\n", file, line, errmsg);
-               goto error;
-       }
-       chk->expect.custom = tcpcheck_spop_expect_agenthello;
-       chk->index = 1;
-       LIST_APPEND(&rs->rules, &chk->list);
-
   ruleset_found:
        rules->list = &rs->rules;
        rules->flags &= ~(TCPCHK_RULES_PROTO_CHK|TCPCHK_RULES_UNUSED_RS);
        rules->flags |= TCPCHK_RULES_SPOP_CHK;
 
   out:
-       free(spop_req);
-       free(errmsg);
        return err_code;
 
   error: