MINOR: server: Add server_template_init() function to initialize servers from a templates.
This patch adds server_template_init() function used to initialize servers
from server templates. It is called just after having parsed a 'server-template'
line.
diff --git a/src/server.c b/src/server.c
index 9f07788..69c1ec3 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1650,14 +1650,73 @@
#endif
/*
+ * Allocate <srv> server dns resolution.
+ * May be safely called with a default server as <src> argument (without hostname).
+ */
+static void srv_alloc_dns_resolution(struct server *srv, const char *hostname)
+{
+ char *hostname_dn;
+ int hostname_dn_len;
+ struct dns_resolution *dst_dns_rslt;
+
+ if (!hostname)
+ return;
+
+ srv->hostname = strdup(hostname);
+ dst_dns_rslt = calloc(1, sizeof *dst_dns_rslt);
+ hostname_dn_len = dns_str_to_dn_label_len(hostname);
+ hostname_dn = calloc(hostname_dn_len + 1, sizeof(char));
+
+ if (!srv->hostname || !dst_dns_rslt || !hostname_dn)
+ goto err;
+
+ srv->resolution = dst_dns_rslt;
+ srv->resolution->hostname_dn = hostname_dn;
+ srv->resolution->hostname_dn_len = hostname_dn_len;
+
+ if (!dns_str_to_dn_label(srv->hostname,
+ srv->resolution->hostname_dn,
+ srv->resolution->hostname_dn_len + 1))
+ goto err;
+
+ srv->resolution->requester = srv;
+ srv->resolution->requester_cb = snr_resolution_cb;
+ srv->resolution->requester_error_cb = snr_resolution_error_cb;
+ srv->resolution->status = RSLV_STATUS_NONE;
+ srv->resolution->step = RSLV_STEP_NONE;
+ /* a first resolution has been done by the configuration parser */
+ srv->resolution->last_resolution = 0;
+
+ return;
+
+ err:
+ free(srv->hostname);
+ srv->hostname = NULL;
+ free(hostname_dn);
+ free(dst_dns_rslt);
+}
+
+/*
* Copy <src> server settings to <srv> server allocating
* everything needed.
+ * This function is not supposed to be called at any time, but only
+ * during server settings parsing or during server allocations from
+ * a server template, and just after having calloc()'ed a new server.
+ * So, <src> may only be a default server (when parsing server settings)
+ * or a server template (during server allocations from a server template).
+ * <srv_tmpl> distinguishes these two cases (must be 1 if <srv> is a template,
+ * 0 if not).
*/
-static void srv_settings_cpy(struct server *srv, struct server *src)
+static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmpl)
{
/* Connection source settings copy */
srv_conn_src_cpy(srv, src);
+ if (srv_tmpl) {
+ srv->addr = src->addr;
+ srv->svc_port = src->svc_port;
+ }
+
srv->pp_opts = src->pp_opts;
if (src->rdr_pfx != NULL) {
srv->rdr_pfx = strdup(src->rdr_pfx);
@@ -1999,6 +2058,75 @@
return 0;
}
+static inline void srv_set_id_from_prefix(struct server *srv, const char *prefix, int nb)
+{
+ chunk_printf(&trash, "%s%d", prefix, nb);
+ free(srv->id);
+ srv->id = strdup(trash.str);
+}
+
+/*
+ * Initialize as much as possible servers from <srv> server template.
+ * Note that a server template is a special server with
+ * a few different parameters than a server which has
+ * been parsed mostly the same way as a server.
+ * Returns the number of servers succesfully allocated,
+ * 'srv' template included.
+ */
+static int server_template_init(struct server *srv, struct proxy *px)
+{
+ int i;
+ struct server *newsrv;
+
+ for (i = srv->tmpl_info.nb_low + 1; i <= srv->tmpl_info.nb_high; i++) {
+ int check_init_state;
+ int agent_init_state;
+
+ newsrv = new_server(px);
+ if (!newsrv)
+ goto err;
+
+ srv_settings_cpy(newsrv, srv, 1);
+ srv_alloc_dns_resolution(newsrv, srv->hostname);
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ if (newsrv->sni_expr) {
+ newsrv->ssl_ctx.sni = srv_sni_sample_parse_expr(newsrv, px, NULL, 0, NULL);
+ if (!newsrv->ssl_ctx.sni)
+ goto err;
+ }
+#endif
+ /* Set this new server ID. */
+ srv_set_id_from_prefix(newsrv, srv->tmpl_info.prefix, i);
+
+ /* Initial checks states. */
+ check_init_state = CHK_ST_CONFIGURED | CHK_ST_ENABLED;
+ agent_init_state = CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
+
+ if (do_health_check_init(newsrv, px->options2 & PR_O2_CHK_ANY, check_init_state) ||
+ do_server_agent_check_init(newsrv, agent_init_state))
+ goto err;
+
+ /* Linked backwards first. This will be restablished after parsing. */
+ newsrv->next = px->srv;
+ px->srv = newsrv;
+ }
+ srv_set_id_from_prefix(srv, srv->tmpl_info.prefix, srv->tmpl_info.nb_low);
+
+ return i - srv->tmpl_info.nb_low;
+
+ err:
+ srv_set_id_from_prefix(srv, srv->tmpl_info.prefix, srv->tmpl_info.nb_low);
+ if (newsrv) {
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ release_sample_expr(newsrv->ssl_ctx.sni);
+#endif
+ free_check(&newsrv->agent);
+ free_check(&newsrv->check);
+ }
+ free(newsrv);
+ return i - srv->tmpl_info.nb_low;
+}
+
int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
{
struct server *newsrv = NULL;
@@ -2174,7 +2302,7 @@
}
/* Copy default server settings to new server settings. */
- srv_settings_cpy(newsrv, &curproxy->defsrv);
+ srv_settings_cpy(newsrv, &curproxy->defsrv, 0);
cur_arg++;
} else {
newsrv = &curproxy->defsrv;
@@ -2609,6 +2737,8 @@
err_code |= server_finalize_init(file, linenum, args, cur_arg, newsrv, curproxy);
if (err_code & ERR_FATAL)
goto out;
+ if (srv_tmpl)
+ server_template_init(newsrv, curproxy);
}
free(fqdn);
return 0;