Hi all,

this one is more to open the discussion than to be applied as is.
But if it's ok to everyone, let's apply it ;-)

It is also to revive this work, because it's something I started maybe 2 monthes ago but I couldn't find time to rework on it until now...

Once it's OK, I'll work on the documentation.

Le 30/11/2014 23:51, Cyril Bonté a écrit :
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 | 86 +++++++++++++++++++++++++++++++++++++++++++-----------------
  1 file changed, 62 insertions(+), 24 deletions(-)

diff --git a/src/checks.c b/src/checks.c
index bb8b719..966af47 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -1568,6 +1568,40 @@ 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)
+{
+       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 = "";
+       }
+       check->envp[*idx] = malloc(strlen(envname) + strlen(value) + 2);
+       if (!check->envp[*idx]) {
+               Alert("Failed to allocate memory for the environment variable '%s'. 
Aborting.\n", envname);
+               return 1;
+       }
+       sprintf(check->envp[*idx], "%s=%s", envname, value);
+       check->envp[++*idx] = NULL;
+       return 0;
+}

  static int prepare_external_check(struct check *check)
  {
@@ -1575,10 +1609,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 +1623,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 +1637,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 +1653,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 +1691,6 @@ err:
                free(check->argv);
                check->argv = NULL;
        }
-       Alert(err_fmt, px->id, s->id);
        return 0;
  }




--
Cyril Bonté

Reply via email to