From 9ede66b06d3b8dbf1c5c0d58bee42793b6bdac8d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Cyril=20Bont=C3=A9?= Date: Tue, 2 Dec 2014 21:21:36 +0100 Subject: [PATCH] MEDIUM: checks: provide environment variables to the external checks The external command accepted 4 arguments, some with the value "NOT_USED" when not applicable. In order to make the exernal command more generic, this patch also provides the values in environment variables. This allows to provide more information. Currently, the supported environment variables are : PATH, as previously provided. HAPROXY_PROXY_NAME, the backend name HAPROXY_PROXY_ID, the backend id HAPROXY_PROXY_ADDR, the first bind address if available (or empty) HAPROXY_PROXY_PORT, the first bind port if available (or empty) HAPROXY_SERVER_NAME, the server name HAPROXY_SERVER_ID, the server id HAPROXY_SERVER_ADDR, the server address HAPROXY_SERVER_PORT, the server port if available (or empty) HAPROXY_SERVER_MAXCONN, the server max connections HAPROXY_SERVER_CURCONN, the current number of connections on the server --- src/checks.c | 98 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/src/checks.c b/src/checks.c index bb8b719ebe..03ddb26c44 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1568,6 +1568,52 @@ static int init_pid_list(void) { return 0; } +#define EXTCHECK_ARG_MAX 5 +#define EXTCHECK_ENV_ROOM 16 + +#define EXTCHECK_ADD_ENV(check, envname, value, idx) { if (external_check_add_env(check, envname, value, idx)) goto err; } + +/* + * helper function to allocate enough space for new environment variables used + * by external checks. + */ +static int external_check_add_env(struct check *check, const char *envname, const char *value, int *idx) +{ + int len, ret; + + if (*idx % EXTCHECK_ENV_ROOM == 0) { + /* Allocate enough space to store new environment variables */ + char **tmp = realloc(check->envp, (EXTCHECK_ENV_ROOM * ((*idx / EXTCHECK_ENV_ROOM) + 1) + 1) * sizeof(check->envp)); + if (tmp == NULL) { + Alert("Failed to allocate memory for new environment variables. Aborting\n"); + return 1; + } else { + check->envp = tmp; + } + } + /* Instead of sending NOT_USED, sending an empty value is preferable */ + if (strcmp(value, "NOT_USED") == 0) { + value = ""; + } + len = strlen(envname) + strlen(value) + 1; + check->envp[*idx] = malloc(len + 1); + check->envp[*idx + 1] = NULL; + if (!check->envp[*idx]) { + Alert("Failed to allocate memory for the environment variable '%s'. Aborting.\n", envname); + return 1; + } + ret = snprintf(check->envp[*idx], len + 1, "%s=%s", envname, value); + if (ret < 0) { + Alert("Failed to store the environment variable '%s'. Reason : %s. Aborting.\n", envname, strerror(errno)); + return 1; + } + else if (ret != len) { + Alert("Environment variable '%s' was truncated. Aborting.\n", envname); + return 1; + } + (*idx)++; + return 0; +} static int prepare_external_check(struct check *check) { @@ -1575,10 +1621,9 @@ static int prepare_external_check(struct check *check) struct proxy *px = s->proxy; struct listener *listener = NULL, *l; int i; - const char *err_fmt = "Starting [%s:%s] check: out of memory.\n"; + int envidx = 0; const char *path = px->check_path ? px->check_path : DEF_CHECK_PATH; - char host[46]; - char serv[6]; + char buf[256]; list_for_each_entry(l, &px->conf.listeners, by_fe) /* Use the first INET, INET6 or UNIX listener */ @@ -1590,18 +1635,9 @@ static int prepare_external_check(struct check *check) } check->curpid = NULL; + check->envp = NULL; - check->envp = calloc(2, sizeof(check->argv)); - if (!check->envp) - goto err; - check->envp[0] = malloc(strlen("PATH=") + strlen(path) + 1); - if (!check->envp[0]) - goto err; - strcpy(check->envp[0], "PATH="); - strcpy(check->envp[0] + strlen(check->envp[0]), path); - check->envp[1] = NULL; - - check->argv = calloc(6, sizeof(check->argv)); + check->argv = calloc(EXTCHECK_ARG_MAX + 1, sizeof(check->argv)); if (!check->argv) goto err; @@ -1613,10 +1649,10 @@ static int prepare_external_check(struct check *check) } else if (listener->addr.ss_family == AF_INET || listener->addr.ss_family == AF_INET6) { - addr_to_str(&listener->addr, host, sizeof(host)); - check->argv[1] = strdup(host); - port_to_str(&listener->addr, serv, sizeof(serv)); - check->argv[2] = strdup(serv); + addr_to_str(&listener->addr, buf, sizeof(buf)); + check->argv[1] = strdup(buf); + port_to_str(&listener->addr, buf, sizeof(buf)); + check->argv[2] = strdup(buf); } else if (listener->addr.ss_family == AF_UNIX) { const struct sockaddr_un *un; @@ -1629,19 +1665,34 @@ static int prepare_external_check(struct check *check) goto err; } - addr_to_str(&s->addr, host, sizeof(host)); - check->argv[3] = strdup(host); - port_to_str(&s->addr, serv, sizeof(serv)); - check->argv[4] = strdup(serv); + addr_to_str(&s->addr, buf, sizeof(buf)); + check->argv[3] = strdup(buf); + port_to_str(&s->addr, buf, sizeof(buf)); + check->argv[4] = strdup(buf); for (i = 0; i < 5; i++) if (!check->argv[i]) goto err; + EXTCHECK_ADD_ENV(check, "PATH", path, &envidx); + /* Add proxy environment variables */ + EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_NAME", px->id, &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_ID", ultoa_r(px->uuid, buf, sizeof(buf)), &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_ADDR", check->argv[1], &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_PORT", check->argv[2], &envidx); + /* Add server environment variables */ + EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_NAME", s->id, &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_ID", ultoa_r(s->puid, buf, sizeof(buf)), &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_ADDR", check->argv[3], &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_PORT", check->argv[4], &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_MAXCONN", ultoa_r(s->maxconn, buf, sizeof(buf)), &envidx); + EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_CURCONN", ultoa_r(s->cur_sess, buf, sizeof(buf)), &envidx); + return 1; err: if (check->envp) { - free(check->envp[1]); + for (i = 0; i < envidx; i++) + free(check->envp[i]); free(check->envp); check->envp = NULL; } @@ -1652,7 +1703,6 @@ err: free(check->argv); check->argv = NULL; } - Alert(err_fmt, px->id, s->id); return 0; } -- 2.39.5