MINOR: server: prepare parsing for dynamic servers
Prepare the server parsing API to support dynamic servers.
- define a new parsing flag to be used for dynamic servers
- each keyword contains a new field dynamic_ok to indicate if it can be
used for a dynamic server. For now, no keyword are supported.
- do not copy settings from the default server for a new dynamic server.
- a dynamic server is created in a maintenance mode and requires an
explicit 'enable server' command.
- a new server flag named SRV_F_DYNAMIC is created. This flag is set for
all servers created at runtime. It might be useful later, for example
to know if a server can be purged.
diff --git a/src/server.c b/src/server.c
index 3c26243..ec9e6e6 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1626,48 +1626,48 @@
* Note: -1 as ->skip value means that the number of arguments are variable.
*/
static struct srv_kw_list srv_kws = { "ALL", { }, {
- { "backup", srv_parse_backup, 0, 1 }, /* Flag as backup server */
- { "cookie", srv_parse_cookie, 1, 1 }, /* Assign a cookie to the server */
- { "disabled", srv_parse_disabled, 0, 1 }, /* Start the server in 'disabled' state */
- { "enabled", srv_parse_enabled, 0, 1 }, /* Start the server in 'enabled' state */
- { "error-limit", srv_parse_error_limit, 1, 1 }, /* Configure the consecutive count of check failures to consider a server on error */
- { "id", srv_parse_id, 1, 0 }, /* set id# of server */
- { "init-addr", srv_parse_init_addr, 1, 1 }, /* */
- { "log-proto", srv_parse_log_proto, 1, 1 }, /* Set the protocol for event messages, only relevant in a ring section */
- { "maxconn", srv_parse_maxconn, 1, 1 }, /* Set the max number of concurrent connection */
- { "maxqueue", srv_parse_maxqueue, 1, 1 }, /* Set the max number of connection to put in queue */
- { "max-reuse", srv_parse_max_reuse, 1, 1 }, /* Set the max number of requests on a connection, -1 means unlimited */
- { "minconn", srv_parse_minconn, 1, 1 }, /* Enable a dynamic maxconn limit */
- { "namespace", srv_parse_namespace, 1, 1 }, /* Namespace the server socket belongs to (if supported) */
- { "no-backup", srv_parse_no_backup, 0, 1 }, /* Flag as non-backup server */
- { "no-send-proxy", srv_parse_no_send_proxy, 0, 1 }, /* Disable use of PROXY V1 protocol */
- { "no-send-proxy-v2", srv_parse_no_send_proxy_v2, 0, 1 }, /* Disable use of PROXY V2 protocol */
- { "no-tfo", srv_parse_no_tfo, 0, 1 }, /* Disable use of TCP Fast Open */
- { "non-stick", srv_parse_non_stick, 0, 1 }, /* Disable stick-table persistence */
- { "observe", srv_parse_observe, 1, 1 }, /* Enables health adjusting based on observing communication with the server */
- { "on-error", srv_parse_on_error, 1, 1 }, /* Configure the action on check failure */
- { "on-marked-down", srv_parse_on_marked_down, 1, 1 }, /* Configure the action when a server is marked down */
- { "on-marked-up", srv_parse_on_marked_up, 1, 1 }, /* Configure the action when a server is marked up */
- { "pool-low-conn", srv_parse_pool_low_conn, 1, 1 }, /* Set the min number of orphan idle connecbefore being allowed to pick from other threads */
- { "pool-max-conn", srv_parse_pool_max_conn, 1, 1 }, /* Set the max number of orphan idle connections, -1 means unlimited */
- { "pool-purge-delay", srv_parse_pool_purge_delay, 1, 1 }, /* Set the time before we destroy orphan idle connections, defaults to 1s */
- { "proto", srv_parse_proto, 1, 1 }, /* Set the proto to use for all outgoing connections */
- { "proxy-v2-options", srv_parse_proxy_v2_options, 1, 1 }, /* options for send-proxy-v2 */
- { "redir", srv_parse_redir, 1, 1 }, /* Enable redirection mode */
- { "resolve-net", srv_parse_resolve_net, 1, 1 }, /* Set the prefered network range for name resolution */
- { "resolve-opts", srv_parse_resolve_opts, 1, 1 }, /* Set options for name resolution */
- { "resolve-prefer", srv_parse_resolve_prefer, 1, 1 }, /* Set the prefered family for name resolution */
- { "resolvers", srv_parse_resolvers, 1, 1 }, /* Configure the resolver to use for name resolution */
- { "send-proxy", srv_parse_send_proxy, 0, 1 }, /* Enforce use of PROXY V1 protocol */
- { "send-proxy-v2", srv_parse_send_proxy_v2, 0, 1 }, /* Enforce use of PROXY V2 protocol */
- { "slowstart", srv_parse_slowstart, 1, 1 }, /* Set the warm-up timer for a previously failed server */
- { "source", srv_parse_source, -1, 1 }, /* Set the source address to be used to connect to the server */
- { "stick", srv_parse_stick, 0, 1 }, /* Enable stick-table persistence */
- { "tfo", srv_parse_tfo, 0, 1 }, /* enable TCP Fast Open of server */
- { "track", srv_parse_track, 1, 1 }, /* Set the current state of the server, tracking another one */
- { "socks4", srv_parse_socks4, 1, 1 }, /* Set the socks4 proxy of the server*/
- { "usesrc", srv_parse_usesrc, 0, 1 }, /* safe-guard against usesrc without preceding <source> keyword */
- { "weight", srv_parse_weight, 1, 1 }, /* Set the load-balancing weight */
+ { "backup", srv_parse_backup, 0, 1, 0 }, /* Flag as backup server */
+ { "cookie", srv_parse_cookie, 1, 1, 0 }, /* Assign a cookie to the server */
+ { "disabled", srv_parse_disabled, 0, 1, 0 }, /* Start the server in 'disabled' state */
+ { "enabled", srv_parse_enabled, 0, 1, 0 }, /* Start the server in 'enabled' state */
+ { "error-limit", srv_parse_error_limit, 1, 1, 0 }, /* Configure the consecutive count of check failures to consider a server on error */
+ { "id", srv_parse_id, 1, 0, 0 }, /* set id# of server */
+ { "init-addr", srv_parse_init_addr, 1, 1, 0 }, /* */
+ { "log-proto", srv_parse_log_proto, 1, 1, 0 }, /* Set the protocol for event messages, only relevant in a ring section */
+ { "maxconn", srv_parse_maxconn, 1, 1, 0 }, /* Set the max number of concurrent connection */
+ { "maxqueue", srv_parse_maxqueue, 1, 1, 0 }, /* Set the max number of connection to put in queue */
+ { "max-reuse", srv_parse_max_reuse, 1, 1, 0 }, /* Set the max number of requests on a connection, -1 means unlimited */
+ { "minconn", srv_parse_minconn, 1, 1, 0 }, /* Enable a dynamic maxconn limit */
+ { "namespace", srv_parse_namespace, 1, 1, 0 }, /* Namespace the server socket belongs to (if supported) */
+ { "no-backup", srv_parse_no_backup, 0, 1, 0 }, /* Flag as non-backup server */
+ { "no-send-proxy", srv_parse_no_send_proxy, 0, 1, 0 }, /* Disable use of PROXY V1 protocol */
+ { "no-send-proxy-v2", srv_parse_no_send_proxy_v2, 0, 1, 0 }, /* Disable use of PROXY V2 protocol */
+ { "no-tfo", srv_parse_no_tfo, 0, 1, 0 }, /* Disable use of TCP Fast Open */
+ { "non-stick", srv_parse_non_stick, 0, 1, 0 }, /* Disable stick-table persistence */
+ { "observe", srv_parse_observe, 1, 1, 0 }, /* Enables health adjusting based on observing communication with the server */
+ { "on-error", srv_parse_on_error, 1, 1, 0 }, /* Configure the action on check failure */
+ { "on-marked-down", srv_parse_on_marked_down, 1, 1, 0 }, /* Configure the action when a server is marked down */
+ { "on-marked-up", srv_parse_on_marked_up, 1, 1, 0 }, /* Configure the action when a server is marked up */
+ { "pool-low-conn", srv_parse_pool_low_conn, 1, 1, 0 }, /* Set the min number of orphan idle connecbefore being allowed to pick from other threads */
+ { "pool-max-conn", srv_parse_pool_max_conn, 1, 1, 0 }, /* Set the max number of orphan idle connections, -1 means unlimited */
+ { "pool-purge-delay", srv_parse_pool_purge_delay, 1, 1, 0 }, /* Set the time before we destroy orphan idle connections, defaults to 1s */
+ { "proto", srv_parse_proto, 1, 1, 0 }, /* Set the proto to use for all outgoing connections */
+ { "proxy-v2-options", srv_parse_proxy_v2_options, 1, 1, 0 }, /* options for send-proxy-v2 */
+ { "redir", srv_parse_redir, 1, 1, 0 }, /* Enable redirection mode */
+ { "resolve-net", srv_parse_resolve_net, 1, 1, 0 }, /* Set the prefered network range for name resolution */
+ { "resolve-opts", srv_parse_resolve_opts, 1, 1, 0 }, /* Set options for name resolution */
+ { "resolve-prefer", srv_parse_resolve_prefer, 1, 1, 0 }, /* Set the prefered family for name resolution */
+ { "resolvers", srv_parse_resolvers, 1, 1, 0 }, /* Configure the resolver to use for name resolution */
+ { "send-proxy", srv_parse_send_proxy, 0, 1, 0 }, /* Enforce use of PROXY V1 protocol */
+ { "send-proxy-v2", srv_parse_send_proxy_v2, 0, 1, 0 }, /* Enforce use of PROXY V2 protocol */
+ { "slowstart", srv_parse_slowstart, 1, 1, 0 }, /* Set the warm-up timer for a previously failed server */
+ { "source", srv_parse_source, -1, 1, 0 }, /* Set the source address to be used to connect to the server */
+ { "stick", srv_parse_stick, 0, 1, 0 }, /* Enable stick-table persistence */
+ { "tfo", srv_parse_tfo, 0, 1, 0 }, /* enable TCP Fast Open of server */
+ { "track", srv_parse_track, 1, 1, 0 }, /* Set the current state of the server, tracking another one */
+ { "socks4", srv_parse_socks4, 1, 1, 0 }, /* Set the socks4 proxy of the server*/
+ { "usesrc", srv_parse_usesrc, 0, 1, 0 }, /* safe-guard against usesrc without preceding <source> keyword */
+ { "weight", srv_parse_weight, 1, 1, 0 }, /* Set the load-balancing weight */
{ NULL, NULL, 0 },
}};
@@ -2212,8 +2212,12 @@
srv = NULL;
}
-/* This function is first intented to be used through parse_server to
- * initialize a new server on startup.
+/*
+ * Parse as much as possible such a range string argument: low[-high]
+ * Set <nb_low> and <nb_high> values so that they may be reused by this loop
+ * for(int i = nb_low; i <= nb_high; i++)... with nb_low >= 1.
+ * Fails if 'low' < 0 or 'high' is present and not higher than 'low'.
+ * Returns 0 if succeeded, -1 if not.
*/
static int _srv_parse_tmpl_range(struct server *srv, const char *arg,
int *nb_low, int *nb_high)
@@ -2399,6 +2403,9 @@
newsrv->tmpl_info.nb_high = tmpl_range_high;
}
+ if (parse_flags & SRV_PARSE_DYNAMIC)
+ newsrv->flags |= SRV_F_DYNAMIC;
+
/* Note: for a server template, its id is its prefix.
* This is a temporary id which will be used for server allocations to come
* after parsing.
@@ -2466,8 +2473,18 @@
(*cur_arg)++;
skip_addr:
- /* Copy default server settings to new server settings. */
- srv_settings_cpy(newsrv, &curproxy->defsrv, 0);
+ if (!(parse_flags & SRV_PARSE_DYNAMIC)) {
+ /* Copy default server settings to new server */
+ srv_settings_cpy(newsrv, &curproxy->defsrv, 0);
+ } else {
+ /* Initialize dynamic server weight to 1 */
+ newsrv->uweight = newsrv->iweight = 1;
+
+ /* A dynamic server is disabled on startup */
+ newsrv->next_admin = SRV_ADMF_FMAINT;
+ newsrv->next_state = SRV_ST_STOPPED;
+ server_recalc_eweight(newsrv, 0);
+ }
HA_SPIN_INIT(&newsrv->lock);
}
else {
@@ -2529,6 +2546,12 @@
err_code = ERR_ALERT;
goto out;
}
+ else if ((parse_flags & SRV_PARSE_DYNAMIC) && !kw->dynamic_ok) {
+ memprintf(errmsg, "'%s' option is not accepted for dynamic server",
+ args[*cur_arg]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
err_code = kw->parse(args, cur_arg, curproxy, srv, errmsg);
@@ -2569,7 +2592,7 @@
*/
static int _srv_parse_finalize(char **args, int cur_arg,
struct server *srv, struct proxy *px,
- char **errmsg)
+ int parse_flags, char **errmsg)
{
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
int ret;
@@ -2591,10 +2614,16 @@
return ret;
#endif
- if (srv->flags & SRV_F_BACKUP)
- px->srv_bck++;
- else
- px->srv_act++;
+ /* A dynamic server is disabled on startup. It must not be counted as
+ * an active backend entry.
+ */
+ if (!(parse_flags & SRV_PARSE_DYNAMIC)) {
+ if (srv->flags & SRV_F_BACKUP)
+ px->srv_bck++;
+ else
+ px->srv_act++;
+ }
+
srv_lb_commit_status(srv);
return 0;
@@ -2660,7 +2689,7 @@
}
if (!(parse_flags & SRV_PARSE_DEFAULT_SERVER)) {
- err_code |= _srv_parse_finalize(args, cur_arg, newsrv, curproxy, &errmsg);
+ err_code |= _srv_parse_finalize(args, cur_arg, newsrv, curproxy, parse_flags, &errmsg);
if (err_code) {
display_parser_err(file, linenum, args, cur_arg, err_code, &errmsg);
free(errmsg);