Hi,

It turned out you couldn't properly create backends dynamically, or at
least remove them. Please find attached a patch set that fixes that,
and adds a "director" capability to the debug vmod with an initial
test case. This is still incomplete, and I want to push this further. For
example I've created a Backend_added log record, but nothing for
deletion.

Before I do anything else, I'll wait for feedback :)

Cheers,
Dridi

PS. today I'm doing training and the customer is blocking IRC

On Thu, Mar 19, 2015 at 12:26 AM, Dridi Boukelmoune <[email protected]> wrote:
> Hi,
>
> As discussed briefly during the last VDD in Hamburg, phk said that
> everything should be in place to allow dynamic backend allocations
> (ie. outside of pure VCL).
>
> I looked quickly at the code right after the VDD with fgs, and at the
> time there was a couple backend-related commits that had just showed
> up. But I came to the conclusion that you could only add/remove a
> backend and a tcp pool in vcl_init and vcl_fini.
>
> Those operations can only be triggered by the CLI thread right now, so
> it's not possible to programmatically add a backend at any arbitrary
> time and still benefit from the existing facilities (stats, probes,
> connection pools, etc).
>
> I haven't made any progress since then, so I'm asking first what the
> comment was about. I think I misunderstood what it was supposed to
> mean at the time.
>
> Also please find attached a tiny patch removing leftovers I found after the
> VDD.
>
> Regards,
> Dridi
From 291a80a90ce8eed2eedcdca3b3ba5a7a118400be Mon Sep 17 00:00:00 2001
From: Dridi Boukelmoune <[email protected]>
Date: Mon, 13 Apr 2015 09:31:09 +0200
Subject: [PATCH 1/3] Remove unsused context from VRT backend functions

---
 bin/varnishd/cache/cache_backend.c | 6 ++----
 include/vrt.h                      | 4 ++--
 lib/libvcc/vcc_backend.c           | 4 ++--
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index a02a7d8..3ec17d7 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -319,14 +319,13 @@ VRT_init_vbe(VRT_CTX, struct director **dp, const struct vrt_backend *vrt)
 }
 
 void
-VRT_event_vbe(VRT_CTX, enum vcl_event_e ev, const struct director *d,
+VRT_event_vbe(enum vcl_event_e ev, const struct director *d,
     const struct vrt_backend *vrt)
 {
 	struct backend *be;
 
 	ASSERT_CLI();
 	(void)ev;
-	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
 	CHECK_OBJ_NOTNULL(vrt, VRT_BACKEND_MAGIC);
 	assert(d->priv2 == vrt);
@@ -351,13 +350,12 @@ VRT_event_vbe(VRT_CTX, enum vcl_event_e ev, const struct director *d,
 }
 
 void
-VRT_fini_vbe(VRT_CTX, struct director **dp, const struct vrt_backend *vrt)
+VRT_fini_vbe(struct director **dp, const struct vrt_backend *vrt)
 {
 	struct director *d;
 	struct backend *be;
 
 	ASSERT_CLI();
-	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	AN(dp);
 	AN(*dp);
 	CHECK_OBJ_NOTNULL(vrt, VRT_BACKEND_MAGIC);
diff --git a/include/vrt.h b/include/vrt.h
index e034f91..b5442d8 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -234,10 +234,10 @@ void VRT_synth_page(VRT_CTX, const char *, ...);
 /* Backend related */
 void VRT_init_vbe(VRT_CTX, struct director **, const struct vrt_backend *);
 #ifdef VCL_RET_MAX
-void VRT_event_vbe(VRT_CTX, enum vcl_event_e, const struct director *,
+void VRT_event_vbe(enum vcl_event_e, const struct director *,
     const struct vrt_backend *);
 #endif
-void VRT_fini_vbe(VRT_CTX, struct director **, const struct vrt_backend *);
+void VRT_fini_vbe(struct director **, const struct vrt_backend *);
 
 /* Suckaddr related */
 int VRT_VSA_GetPtr(const struct suckaddr *sua, const unsigned char ** dst);
diff --git a/lib/libvcc/vcc_backend.c b/lib/libvcc/vcc_backend.c
index b937404..d475dc6 100644
--- a/lib/libvcc/vcc_backend.c
+++ b/lib/libvcc/vcc_backend.c
@@ -418,10 +418,10 @@ vcc_ParseHostDef(struct vcc *tl, const struct token *t_be)
 	    "\tVRT_init_vbe(ctx, &VGCDIR(%s), &vgc_dir_priv_%s);",
 	    vgcname, vgcname);
 	VSB_printf(ifp->fin,
-	    "\tVRT_fini_vbe(ctx, &VGCDIR(%s), &vgc_dir_priv_%s);",
+	    "\tVRT_fini_vbe(&VGCDIR(%s), &vgc_dir_priv_%s);",
 	    vgcname, vgcname);
 	VSB_printf(ifp->event,
-	    "\tVRT_event_vbe(ctx, ev, VGCDIR(%s), &vgc_dir_priv_%s);",
+	    "\tVRT_event_vbe(ev, VGCDIR(%s), &vgc_dir_priv_%s);",
 	    vgcname, vgcname);
 	tl->ndirector++;
 }
-- 
2.1.0

From a81e99559417bd9f3cc86fbe5cfd99c1a78943cc Mon Sep 17 00:00:00 2001
From: Dridi Boukelmoune <[email protected]>
Date: Mon, 13 Apr 2015 09:31:53 +0200
Subject: [PATCH 2/3] Add a new Backend_added log event

---
 bin/varnishd/cache/cache_backend_cfg.c |  3 +++
 include/tbl/vsl_tags.h                 | 10 ++++++++++
 2 files changed, 13 insertions(+)

diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c
index 08b58d3..8058b6c 100644
--- a/bin/varnishd/cache/cache_backend_cfg.c
+++ b/bin/varnishd/cache/cache_backend_cfg.c
@@ -120,6 +120,9 @@ VBE_AddBackend(const char *vcl, const struct vrt_backend *vb)
 
 	VTAILQ_INSERT_TAIL(&backends, b, list);
 	VSC_C_main->n_backend++;
+
+	VSL(SLT_Backend_added, 0, "%s %s", b->vcl_name, b->display_name);
+
 	return (b);
 }
 
diff --git a/include/tbl/vsl_tags.h b/include/tbl/vsl_tags.h
index ecb2683..e5aaa22 100644
--- a/include/tbl/vsl_tags.h
+++ b/include/tbl/vsl_tags.h
@@ -373,6 +373,16 @@ SLTM(Backend_health, 0, "Backend health check",
 	"\n"
 )
 
+SLTM(Backend_added, 0, "Backend added",
+	"Logged when a backend is created.\n\n"
+	"The format is::\n\n"
+	"\t%s %s\n"
+	"\t|  |\n"
+	"\t|  +- Backend display name\n"
+	"\t+---- VCL name\n"
+	"\n"
+)
+
 SLTM(VCL_Log, 0, "Log statement from VCL",
 	"User generated log messages insert from VCL through std.log()"
 )
-- 
2.1.0

From ca0a47eb4da3d46889f7a1ecf6ee0d167f361bd0 Mon Sep 17 00:00:00 2001
From: Dridi Boukelmoune <[email protected]>
Date: Mon, 13 Apr 2015 09:34:12 +0200
Subject: [PATCH 3/3] Add a single-backend director to the debug vmod

And test dynamic backend creation.
---
 bin/varnishtest/tests/d00007.vtc   |  37 ++++++++++++
 lib/libvmod_debug/Makefile.am      |   3 +-
 lib/libvmod_debug/vmod.vcc         |   8 +++
 lib/libvmod_debug/vmod_debug_dyn.c | 116 +++++++++++++++++++++++++++++++++++++
 4 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 bin/varnishtest/tests/d00007.vtc
 create mode 100644 lib/libvmod_debug/vmod_debug_dyn.c

diff --git a/bin/varnishtest/tests/d00007.vtc b/bin/varnishtest/tests/d00007.vtc
new file mode 100644
index 0000000..4695514
--- /dev/null
+++ b/bin/varnishtest/tests/d00007.vtc
@@ -0,0 +1,37 @@
+varnishtest "Test dynamic backends"
+
+server s1 {
+	rxreq
+	txresp
+} -start
+
+varnish v1 -vcl {
+	import ${vmod_debug};
+
+	backend dummy {
+		.host = "${bad_ip}";
+	}
+
+	sub vcl_init {
+		new s1 = debug.dyn("${s1_addr}", "${s1_port}");
+	}
+
+	sub vcl_recv {
+		set req.backend_hint = s1.backend();
+	}
+} -start
+
+logexpect l1 -v v1 -g raw -d {
+        expect * 0 Backend_added "dummy vcl1.dummy"
+        expect * 0 Backend_added "s1 vcl1.s1"
+} -start
+
+varnish v1 -expect MAIN.n_backend == 2
+
+logexpect l1 -wait
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 200
+} -run
diff --git a/lib/libvmod_debug/Makefile.am b/lib/libvmod_debug/Makefile.am
index d189102..c9e05f5 100644
--- a/lib/libvmod_debug/Makefile.am
+++ b/lib/libvmod_debug/Makefile.am
@@ -17,6 +17,7 @@ libvmod_debug_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version
 
 libvmod_debug_la_SOURCES = \
 	vmod_debug.c \
+	vmod_debug_dyn.c \
 	vmod_debug_obj.c
 
 nodist_libvmod_debug_la_SOURCES = \
@@ -24,7 +25,7 @@ nodist_libvmod_debug_la_SOURCES = \
 	vcc_if.h
 
 # BUILT_SOURCES is only a hack and dependency tracking does not help for the first build
-vmod_debug.lo vmod_debug_obj.lo: vcc_if.h
+vmod_debug.lo vmod_debug_dyn.lo vmod_debug_obj.lo: vcc_if.h
 
 vcc_if.c vcc_if.h vmod_debug.rst vmod_debug.man.rst: $(vmodtool) $(vmod_srcdir)/vmod.vcc
 	@PYTHON@ $(vmodtool) $(vmodtoolargs) $(vmod_srcdir)/vmod.vcc
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index 434ee78..dedddff 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -101,3 +101,11 @@ $Function INT vre_limit()
 $Function VOID register_exp_callback(PRIV_VCL)
 
 Register the vmod to receive expiry callbacks
+
+$Object dyn(STRING addr, STRING port)
+
+Dynamically create a single-backend director
+
+$Method BACKEND .backend()
+
+Return the dynamic backend.
diff --git a/lib/libvmod_debug/vmod_debug_dyn.c b/lib/libvmod_debug/vmod_debug_dyn.c
new file mode 100644
index 0000000..342ca5e
--- /dev/null
+++ b/lib/libvmod_debug/vmod_debug_dyn.c
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 2015 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "cache/cache.h"
+#include "cache/cache_backend.h"
+
+#include "vcl.h"
+#include "vrt.h"
+#include "vsa.h"
+#include "vss.h"
+#include "vcc_if.h"
+
+struct vmod_debug_dyn {
+	unsigned		magic;
+#define VMOD_DEBUG_DYN_MAGIC	0x9b77ccbd
+	struct suckaddr         *addr;
+	char			*port;
+	struct director		*dir;
+	struct vrt_backend	vrt;
+};
+
+static int __match_proto__(vss_resolved_f)
+vmod_dyn_cb(void *priv, const struct suckaddr *sa)
+{
+	struct vmod_debug_dyn *o;
+
+	CAST_OBJ_NOTNULL(o, priv, VMOD_DEBUG_DYN_MAGIC);
+	AN(o->addr = VSA_Clone(sa));
+	o->vrt.ipv4_suckaddr = o->addr;
+	return 1;
+}
+
+VCL_VOID
+vmod_dyn__init(VRT_CTX, struct vmod_debug_dyn **op,
+    const char *vcl_name, VCL_STRING addr, VCL_STRING port)
+{
+	struct vmod_debug_dyn *o;
+	const char *err;
+
+	ASSERT_CLI();
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	AN(op);
+	AZ(*op);
+	AN(addr);
+	AN(port);
+
+	ALLOC_OBJ(o, VMOD_DEBUG_DYN_MAGIC);
+	AN(o);
+	o->port = strdup(port);
+	o->vrt.magic = VRT_BACKEND_MAGIC;
+	o->vrt.vcl_name = vcl_name;
+	o->vrt.ipv4_addr = addr;
+	o->vrt.port = o->port;
+	assert(VSS_resolver(addr, port, vmod_dyn_cb, o, &err) == 1);
+
+	VRT_init_vbe(ctx, &o->dir, &o->vrt);
+	if (o->dir)
+		*op = o;
+
+	VRT_event_vbe(VCL_EVENT_WARM, o->dir, &o->vrt);
+}
+
+VCL_VOID
+vmod_dyn__fini(struct vmod_debug_dyn **op)
+{
+	struct vmod_debug_dyn *o;
+
+	AN(op);
+	CAST_OBJ_NOTNULL(o, *op, VMOD_DEBUG_DYN_MAGIC);
+	CHECK_OBJ_NOTNULL(&o->vrt, VRT_BACKEND_MAGIC);
+	AN(o->dir);
+	VRT_fini_vbe(&o->dir, &o->vrt);
+	AZ(o->dir);
+	free(o->addr);
+	free(o->port);
+	FREE_OBJ(o);
+	*op = NULL;
+}
+
+VCL_BACKEND __match_proto__()
+vmod_dyn_backend(VRT_CTX, struct vmod_debug_dyn *op)
+{
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	CHECK_OBJ_NOTNULL(op, VMOD_DEBUG_DYN_MAGIC);
+	AN(op->dir);
+	return op->dir;
+}
-- 
2.1.0

_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to