Hi Poul-Henning & Fred, The two patches in attachment fix a bug in the haproxy CLI handling and add the support for the haproxy master CLI in VTest. Could you merge them? Thanks
You can also find in attachment a vtc file which use this new feature. Regards, -- William Lallemand
>From ee3feab9152dc18bc6ccf6eda38dd4ac7ff03b06 Mon Sep 17 00:00:00 2001 From: William Lallemand <wlallem...@haproxy.com> Date: Tue, 1 Oct 2019 17:20:31 +0200 Subject: [PATCH 1/2] BUG/MINOR: haproxy: a CLI command should be followed by a SHUT_WR haproxy_cli_recv() waits for a close, however it is not guaranteed by haproxy than the CLI will close after a response if a SHUT_WR was not sent. This patch fixes the issue by doing a SHUT_WR after each CLI send. --- src/vtc_haproxy.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vtc_haproxy.c b/src/vtc_haproxy.c index b24af08..7cb4584 100644 --- a/src/vtc_haproxy.c +++ b/src/vtc_haproxy.c @@ -191,6 +191,7 @@ cmd_haproxy_cli_send(CMD_ARGS) { struct vsb *vsb; struct haproxy_cli *hc; + int j; (void)cmd; (void)vl; @@ -225,6 +226,13 @@ cmd_haproxy_cli_send(CMD_ARGS) vtc_fatal(hc->vl, "CLI fd %d send error %s", hc->sock, strerror(errno)); + /* a CLI command must be followed by a SHUT_WR if we want HAProxy to + * close after the response */ + shutdown(hc->sock, SHUT_WR); + vtc_log(hc->vl, 3, "CLI shutting fd %d", hc->sock); + if (!VTCP_Check(j)) + vtc_fatal(hc->vl, "Shutdown failed: %s", strerror(errno)); + VSB_destroy(&vsb); } -- 2.21.0
>From bc151646cd7897d82c06a3214280d0a95a20087d Mon Sep 17 00:00:00 2001 From: William Lallemand <wlallem...@haproxy.com> Date: Tue, 1 Oct 2019 16:07:16 +0200 Subject: [PATCH 2/2] haproxy: handle master CLI in master worker mode This patch adds the support for the master CLI of the haproxy master worker mode. With the -W option, VTest will start haproxy with the -S option which runs the master CLI. The -mcli command can be used in the same way as the -cli one. --- src/vtc_haproxy.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/vtc_haproxy.c b/src/vtc_haproxy.c index 7cb4584..57a0b4f 100644 --- a/src/vtc_haproxy.c +++ b/src/vtc_haproxy.c @@ -87,6 +87,9 @@ struct haproxy { /* TCP socket CLI. */ struct haproxy_cli *cli; + /* master CLI */ + struct haproxy_cli *mcli; + char *workdir; struct vsb *msgs; char closed_sock[256]; /* Closed TCP socket */ @@ -483,6 +486,51 @@ haproxy_cli_new(struct haproxy *h) return (hc); } +/* creates a master CLI client (-mcli) */ +static struct haproxy_cli * +haproxy_mcli_new(struct haproxy *h) +{ + struct haproxy_cli *hc; + + ALLOC_OBJ(hc, HAPROXY_CLI_MAGIC); + AN(hc); + + hc->vl = h->vl; + hc->sock = -1; + bprintf(hc->connect, "${%s_mcli_sock}", h->name); + + hc->txbuf_sz = hc->rxbuf_sz = 2048 * 1024; + hc->txbuf = malloc(hc->txbuf_sz); + AN(hc->txbuf); + hc->rxbuf = malloc(hc->rxbuf_sz); + AN(hc->rxbuf); + + return (hc); +} + +/* Bind an address/port for the master CLI (-mcli) */ +static int +haproxy_create_mcli(struct haproxy *h) +{ + int sock; + const char *err; + char buf[128], addr[128], port[128]; + + sock = VTCP_listen_on("localhost:0", NULL, 100, &err); + if (err != NULL) + vtc_fatal(h->vl, + "Create listen socket failed: %s", err); + assert(sock > 0); + + VTCP_myname(sock, addr, sizeof addr, port, sizeof port); + bprintf(buf, "%s_mcli", h->name); + macro_def(h->vl, buf, "sock", "%s %s", addr, port); + macro_def(h->vl, buf, "addr", "%s", addr); + macro_def(h->vl, buf, "port", "%s", port); + + return sock; +} + static void haproxy_cli_delete(struct haproxy_cli *hc) { @@ -553,6 +601,9 @@ haproxy_new(const char *name) h->cli = haproxy_cli_new(h); AN(h->cli); + h->mcli = haproxy_mcli_new(h); + AN(h->mcli); + bprintf(buf, "rm -rf \"%s\" ; mkdir -p \"%s\"", h->workdir, h->workdir); AZ(system(buf)); @@ -586,6 +637,7 @@ haproxy_delete(struct haproxy *h) free(h->pid_fn); VSB_destroy(&h->args); haproxy_cli_delete(h->cli); + haproxy_cli_delete(h->mcli); /* XXX: MEMLEAK (?) */ FREE_OBJ(h); @@ -606,6 +658,7 @@ haproxy_thread(void *priv) return (NULL); } + /********************************************************************** * Start a HAProxy instance. */ @@ -633,8 +686,13 @@ haproxy_start(struct haproxy *h) else VSB_printf(vsb, " -d"); - if (h->opt_worker) + if (h->opt_worker) { + int sock; + + sock = haproxy_create_mcli(h); VSB_printf(vsb, " -W"); + VSB_printf(vsb, " -S \"fd@%d\"", sock); + } VSB_printf(vsb, " %s", VSB_data(h->args)); @@ -715,6 +773,9 @@ haproxy_wait(struct haproxy *h) if (h->cli->spec) haproxy_cli_run(h->cli); + if (h->mcli->spec) + haproxy_cli_run(h->mcli); + closefd(&h->fds[1]); sig = SIGINT; @@ -912,6 +973,10 @@ haproxy_write_conf(struct haproxy *h) * \-cli STRING * Specify the spec to be run by the command line interface (CLI). * + * \-mcli STRING + * Specify the spec to be run by the command line interface (CLI) + * of the Master process. + * * \-conf STRING * Specify the configuration to be loaded by this HAProxy instance. * @@ -1009,6 +1074,15 @@ cmd_haproxy(CMD_ARGS) av++; continue; } + + if (!strcmp(*av, "-mcli")) { + REPLACE(h->mcli->spec, av[1]); + if (h->tp) + haproxy_cli_run(h->mcli); + av++; + continue; + } + if (!strcmp(*av, "-conf")) { AN(av[1]); haproxy_store_conf(h, av[1], 0); -- 2.21.0
>From 9893d0b72b51ada29a87244793c83012da2b8c24 Mon Sep 17 00:00:00 2001 From: William Lallemand <wlallem...@haproxy.com> Date: Tue, 1 Oct 2019 17:53:58 +0200 Subject: [PATCH] REGTEST: mcli/mcli_show_info: launch a 'show info' on the master CLI This test launches a HAProxy process in master worker with 'nbproc 4'. It sends a "show info" to the process 3 and verify that the right process replied. This regtest depends on the support of the master CLI for VTest. --- reg-tests/mcli/mcli_show_info.vtc | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 reg-tests/mcli/mcli_show_info.vtc diff --git a/reg-tests/mcli/mcli_show_info.vtc b/reg-tests/mcli/mcli_show_info.vtc new file mode 100644 index 000000000..e92b78688 --- /dev/null +++ b/reg-tests/mcli/mcli_show_info.vtc @@ -0,0 +1,32 @@ +varnishtest "Show info of process 3" + +#REQUIRE_VERSION=1.9 + +feature ignore_unknown_macro + +# Do nothing. Is there only to create s1_* macros +server s1 { +} -start + +haproxy h1 -W -conf { + global + nbproc 4 + defaults + mode http + ${no-htx} option http-use-htx + timeout connect 1s + timeout client 1s + timeout server 1s + + frontend myfrontend + bind "fd@${my_fe}" + default_backend test + + backend test + server www1 ${s1_addr}:${s1_port} +} -start + +haproxy h1 -mcli { + send "@3 show info" + expect ~ ".*\nProcess_num: 3\n.*" +} -wait -- 2.21.0