MEDIUM: Add external check
Add an external check which makes use of an external process to
check the status of a server.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 762978a..6a331d1 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -856,6 +856,9 @@
}
global.gid = atol(args[1]);
}
+ else if (!strcmp(args[0], "external-check")) {
+ global.external_check = 1;
+ }
/* user/group name handling */
else if (!strcmp(args[0], "user")) {
struct passwd *ha_user;
@@ -2102,6 +2105,11 @@
curproxy->conf.used_listener_id = EB_ROOT;
curproxy->conf.used_server_id = EB_ROOT;
+ if (defproxy.check_path)
+ curproxy->check_path = strdup(defproxy.check_path);
+ if (defproxy.check_command)
+ curproxy->check_command = strdup(defproxy.check_command);
+
goto out;
}
else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
@@ -2110,6 +2118,8 @@
* config parsing to free all default values.
*/
free(defproxy.check_req);
+ free(defproxy.check_command);
+ free(defproxy.check_path);
free(defproxy.cookie_name);
free(defproxy.rdp_cookie_name);
free(defproxy.cookie_domain);
@@ -2617,6 +2627,41 @@
err_code |= ERR_ALERT | ERR_FATAL;
}
}/* end else if (!strcmp(args[0], "cookie")) */
+ else if (!strcmp(args[0], "external-check")) {
+ if (*(args[1]) == 0) {
+ Alert("parsing [%s:%d] : missing argument after '%s'.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (!strcmp(args[1], "command")) {
+ if (*(args[1]) == 0) {
+ Alert("parsing [%s:%d] : missing argument after '%s'.\n",
+ file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ free(curproxy->check_command);
+ curproxy->check_command = strdup(args[2]);
+ }
+ else if (!strcmp(args[1], "path")) {
+ if (*(args[1]) == 0) {
+ Alert("parsing [%s:%d] : missing argument after '%s'.\n",
+ file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ free(curproxy->check_path);
+ curproxy->check_path = strdup(args[2]);
+ }
+ else {
+ Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
+ file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }/* end else if (!strcmp(args[0], "external-check")) */
else if (!strcmp(args[0], "persist")) { /* persist */
if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : missing persist method.\n",
@@ -4024,6 +4069,13 @@
curproxy->options2 &= ~PR_O2_CHK_ANY;
curproxy->options2 |= PR_O2_TCPCHK_CHK;
}
+ else if (!strcmp(args[1], "external-check")) {
+ /* excute an external command to check servers' health */
+ free(curproxy->check_req);
+ curproxy->check_req = NULL;
+ curproxy->options2 &= ~PR_O2_CHK_ANY;
+ curproxy->options2 |= PR_O2_EXT_CHK;
+ }
else if (!strcmp(args[1], "forwardfor")) {
int cur_arg;
@@ -6081,6 +6133,48 @@
}
}
+ if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
+ if (!global.external_check) {
+ Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
+ curproxy->id, "option external-check");
+ cfgerr++;
+ }
+ if (!curproxy->check_command) {
+ Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
+ curproxy->id, "option external-check");
+ cfgerr++;
+ }
+ }
+
+ if (curproxy->check_command) {
+ int clear = 0;
+ if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
+ Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
+ "external-check command", proxy_type_str(curproxy), curproxy->id);
+ err_code |= ERR_WARN;
+ clear = 1;
+ }
+ if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
+ Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
+ curproxy->id, "external-check command");
+ cfgerr++;
+ }
+ if (clear) {
+ free(curproxy->check_command);
+ curproxy->check_command = NULL;
+ }
+ }
+
+ if (curproxy->check_path) {
+ if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
+ Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
+ "external-check path", proxy_type_str(curproxy), curproxy->id);
+ err_code |= ERR_WARN;
+ free(curproxy->check_path);
+ curproxy->check_path = NULL;
+ }
+ }
+
/* if a default backend was specified, let's find it */
if (curproxy->defbe.name) {
struct proxy *target;