This patch introduces mworker_cli_proxy_new_listener() which allows the creation of new listeners for the CLI proxy.
Using this function it is possible to create new listeners from the program arguments with -Sa <unix_socket>. It is allowed to create multiple listeners with several -Sa. --- include/proto/cli.h | 1 + src/cli.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/haproxy.c | 32 +++++++++++++++++ 3 files changed, 131 insertions(+) diff --git a/include/proto/cli.h b/include/proto/cli.h index 6d6ca35ff..467a86ea7 100644 --- a/include/proto/cli.h +++ b/include/proto/cli.h @@ -29,6 +29,7 @@ void cli_register_kw(struct cli_kw_list *kw_list); int cli_has_level(struct appctx *appctx, int level); int mworker_cli_proxy_create(); +int mworker_cli_proxy_new_listener(char *line); int mworker_cli_sockpair_new(struct mworker_proc *mworker_proc, int proc); #endif /* _PROTO_CLI_H */ diff --git a/src/cli.c b/src/cli.c index 161d1ebb0..8a4fbc52c 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1651,6 +1651,104 @@ int mworker_cli_proxy_create() return 0; } +/* + * Create a new listener for the master CLI proxy + */ +int mworker_cli_proxy_new_listener(char *line) +{ + struct bind_conf *bind_conf; + struct listener *l; + char *err = NULL; + char *args[MAX_LINE_ARGS + 1]; + int arg; + int cur_arg; + + arg = 0; + args[0] = line; + + /* args is a bind configuration with spaces replaced by commas */ + while (*line && arg < MAX_LINE_ARGS) { + + if (*line == ',') { + *line++ = '\0'; + while (*line == ',') + line++; + args[++arg] = line; + } + line++; + } + + args[++arg] = "\0"; + + bind_conf = bind_conf_alloc(mworker_proxy, "master-socket", 0, "", xprt_get(XPRT_RAW)); + + bind_conf->level &= ~ACCESS_LVL_MASK; + bind_conf->level |= ACCESS_LVL_ADMIN; + + if (!str2listener(args[0], mworker_proxy, bind_conf, "master-socket", 0, &err)) { + ha_alert("Cannot create the listener of the master CLI\n"); + return -1; + } + + cur_arg = 1; + + while (*args[cur_arg]) { + static int bind_dumped; + struct bind_kw *kw; + + kw = bind_find_kw(args[cur_arg]); + if (kw) { + if (!kw->parse) { + memprintf(&err, "'%s %s' : '%s' option is not implemented in this version (check build options).", + args[0], args[1], args[cur_arg]); + goto err; + } + + if (kw->parse(args, cur_arg, global.stats_fe, bind_conf, &err) != 0) { + if (err) + memprintf(&err, "'%s %s' : '%s'", args[0], args[1], err); + else + memprintf(&err, "'%s %s' : error encountered while processing '%s'", + args[0], args[1], args[cur_arg]); + goto err; + } + + cur_arg += 1 + kw->skip; + continue; + } + + if (!bind_dumped) { + bind_dump_kws(&err); + indent_msg(&err, 4); + bind_dumped = 1; + } + + memprintf(&err, "'%s %s' : unknown keyword '%s'.%s%s", + args[0], args[1], args[cur_arg], + err ? " Registered keywords :" : "", err ? err : ""); + goto err; + } + + + list_for_each_entry(l, &bind_conf->listeners, by_bind) { + l->maxconn = 10; + l->backlog = 10; + l->accept = session_accept_fd; + l->default_target = mworker_proxy->default_target; + /* don't make the peers subject to global limits and don't close it in the master */ + l->options |= (LI_O_UNLIMITED|LI_O_MWORKER); /* we are keeping this FD in the master */ + l->nice = -64; /* we want to boost priority for local stats */ + global.maxsock += l->maxconn; + } + + return 0; + +err: + ha_alert("%s\n", err); + return -1; + +} + /* * Create a new CLI socket using a socketpair for a worker process * <mworker_proc> is the process structure, and <proc> is the process number diff --git a/src/haproxy.c b/src/haproxy.c index 5affcd208..4e6d24303 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -224,6 +224,8 @@ static void *run_thread_poll_loop(void *data); /* bitfield of a few warnings to emit just once (WARN_*) */ unsigned int warned = 0; +/* master CLI configuration (-S flag) */ +struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf); /* These are strings to be reported in the output of "haproxy -vv". They may * either be constants (in which case must_free must be zero) or dynamically @@ -452,6 +454,7 @@ static void usage(char *name) " -dV disables SSL verify on servers side\n" " -sf/-st [pid ]* finishes/terminates old pids.\n" " -x <unix_socket> get listening sockets from a unix socket\n" + " -S <unix_socket>[,<bind options>...] new stats socket for the master\n" "\n", name, DEFAULT_MAXCONN, cfg_maxpconn); exit(1); @@ -1563,6 +1566,22 @@ static void init(int argc, char **argv) argv++; argc--; } + else if (*flag == 'S') { + struct wordlist *c; + + if (argc <= 1 || argv[1][0] == '-') { + ha_alert("Socket and optional bind parameters expected with the -S flag\n"); + usage(progname); + } + if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) { + ha_alert("Cannot allocate memory\n"); + exit(EXIT_FAILURE); + } + LIST_ADD(&mworker_cli_conf, &c->list); + + argv++; + argc--; + } else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) { /* list of pids to finish ('f') or terminate ('t') */ @@ -1701,6 +1720,7 @@ static void init(int argc, char **argv) if (global.mode & MODE_MWORKER) { int proc; + struct wordlist *it, *c; for (proc = 0; proc < global.nbproc; proc++) { struct mworker_proc *tmproc; @@ -1727,6 +1747,18 @@ static void init(int argc, char **argv) ha_alert("Can't create the master's CLI.\n"); exit(EXIT_FAILURE); } + + list_for_each_entry_safe(c, it, &mworker_cli_conf, list) { + + if (mworker_cli_proxy_new_listener(c->s) < 0) { + ha_alert("Can't create the master's CLI.\n"); + exit(EXIT_FAILURE); + } + LIST_DEL(&c->list); + free(c->s); + free(c); + } + } pattern_finalize_config(); -- 2.16.4