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

Reply via email to