Last active
October 24, 2017 13:25
-
-
Save arslanm/9d0b93c414b7645e9a74731ed37b91c0 to your computer and use it in GitHub Desktop.
HAProxy patch against 1.6.6 to control the backup flag of a server using state file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ wget http://www.haproxy.org/download/1.6/src/haproxy-1.6.6.tar.gz | |
$ tar xf haproxy-1.6.6.tar.gz | |
$ cd haproxy-1.6.6 | |
$ cat below_patch | patch -p1 | |
$ make USE_PCRE=1 DEBUG="" ARCH=$(uname -m) TARGET=linux26 | |
$ make install | |
/etc/haproxy/haproxy.cfg: | |
global | |
... | |
stats socket /etc/haproxy/haproxy.sock level admin | |
server-state-file /etc/haproxy/haproxy.state | |
... | |
# put myserver in mybackend into backup mode | |
$ echo "set server mybackend/myserver state backup" | socat unix-connect:/etc/haproxy/haproxy.sock stdio | |
# or make it active again | |
$ echo "set server mybackend/myserver state active" | socat unix-connect:/etc/haproxy/haproxy.sock stdio | |
# save haproxy state | |
$ echo "show servers state" | socat unix-connect:/etc/haproxy/haproxy.sock stdio > /etc/haproxy/haproxy.state | |
# -----------------------------------------------------------------------------------------------------------------# | |
diff -urN a/doc/management.txt b/doc/management.txt | |
--- a/doc/management.txt 2016-06-26 17:41:01.000000000 +0000 | |
+++ b/doc/management.txt 2016-06-29 20:27:36.000000000 +0000 | |
@@ -1586,6 +1586,7 @@ | |
configuration. | |
srv_f_forced_id: Flag to know if the server's ID is forced by | |
configuration. | |
+ srv_is_backup: Flag to know if the server's in backup mode | |
show sess | |
Dump all known sessions. Avoid doing this on slow connections as this can | |
diff -urN a/include/types/server.h b/include/types/server.h | |
--- a/include/types/server.h 2016-06-26 17:41:01.000000000 +0000 | |
+++ b/include/types/server.h 2016-06-29 20:27:36.000000000 +0000 | |
@@ -86,7 +86,7 @@ | |
#define SRV_STATE_FILE_VERSION 1 | |
#define SRV_STATE_FILE_VERSION_MIN 1 | |
#define SRV_STATE_FILE_VERSION_MAX 1 | |
-#define SRV_STATE_FILE_FIELD_NAMES "be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight srv_iweight srv_time_since_last_change srv_check_status srv_check_result srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id" | |
+#define SRV_STATE_FILE_FIELD_NAMES "be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight srv_iweight srv_time_since_last_change srv_check_status srv_check_result srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id srv_is_backup" | |
#define SRV_STATE_FILE_MAX_FIELDS 18 | |
#define SRV_STATE_FILE_NB_FIELDS_VERSION_1 18 | |
#define SRV_STATE_LINE_MAXLEN 512 | |
diff -urN a/src/dumpstats.c b/src/dumpstats.c | |
--- a/src/dumpstats.c 2016-06-26 17:41:01.000000000 +0000 | |
+++ b/src/dumpstats.c 2016-06-29 21:24:05.964819008 +0000 | |
@@ -117,6 +117,10 @@ | |
ST_ADM_ACTION_ARUNN, | |
ST_ADM_ACTION_ADOWN, | |
+ /* backup/active states */ | |
+ ST_ADM_ACTION_BACKUP, | |
+ ST_ADM_ACTION_ACTIVE, | |
+ | |
/* set admin state */ | |
ST_ADM_ACTION_READY, | |
ST_ADM_ACTION_DRAIN, | |
@@ -1529,6 +1533,20 @@ | |
srv_adm_set_drain(sv); | |
else if (strcmp(args[4], "maint") == 0) | |
srv_adm_set_maint(sv); | |
+ else if (strcmp(args[4], "backup") == 0) { | |
+ if (!(sv->flags & SRV_F_BACKUP)) { | |
+ sv->flags |= SRV_F_BACKUP; | |
+ sv->proxy->srv_act --; | |
+ sv->proxy->srv_bck ++; | |
+ } | |
+ } | |
+ else if (strcmp(args[4], "active") == 0) { | |
+ if (sv->flags & SRV_F_BACKUP) { | |
+ sv->flags &= ~SRV_F_BACKUP; | |
+ sv->proxy->srv_act ++; | |
+ sv->proxy->srv_bck --; | |
+ } | |
+ } | |
else { | |
appctx->ctx.cli.msg = "'set server <srv> state' expects 'ready', 'drain' and 'maint'.\n"; | |
appctx->st0 = STAT_CLI_PRINT; | |
@@ -2749,6 +2767,7 @@ | |
char srv_addr[INET6_ADDRSTRLEN + 1]; | |
time_t srv_time_since_last_change; | |
int bk_f_forced_id, srv_f_forced_id; | |
+ int srv_is_backup; | |
/* we don't want to report any state if the backend is not enabled on this process */ | |
@@ -2764,6 +2783,7 @@ | |
srv_time_since_last_change = 0; | |
bk_f_forced_id = 0; | |
srv_f_forced_id = 0; | |
+ srv_is_backup = 0; | |
switch (srv->addr.ss_family) { | |
case AF_INET: | |
@@ -2778,19 +2798,20 @@ | |
srv_time_since_last_change = now.tv_sec - srv->last_change; | |
bk_f_forced_id = appctx->ctx.server_state.px->options & PR_O_FORCED_ID ? 1 : 0; | |
srv_f_forced_id = srv->flags & SRV_F_FORCED_ID ? 1 : 0; | |
+ srv_is_backup = srv->flags & SRV_F_BACKUP ? 1 : 0; | |
chunk_appendf(buf, | |
"%d %s " | |
"%d %s %s " | |
"%d %d %d %d %ld " | |
"%d %d %d %d %d " | |
- "%d %d" | |
+ "%d %d %d" | |
"\n", | |
appctx->ctx.server_state.px->uuid, appctx->ctx.server_state.px->id, | |
srv->puid, srv->id, srv_addr, | |
srv->state, srv->admin, srv->uweight, srv->iweight, (long int)srv_time_since_last_change, | |
srv->check.status, srv->check.result, srv->check.health, srv->check.state, srv->agent.state, | |
- bk_f_forced_id, srv_f_forced_id); | |
+ bk_f_forced_id, srv_f_forced_id, srv_is_backup); | |
if (bi_putchk(si_ic(si), &trash) == -1) { | |
si_applet_cant_put(si); | |
return 0; | |
@@ -4081,19 +4102,31 @@ | |
"Choose the action to perform on the checked servers : " | |
"<select name=action>" | |
"<option value=\"\"></option>" | |
- "<option value=\"ready\">Set state to READY</option>" | |
- "<option value=\"drain\">Set state to DRAIN</option>" | |
- "<option value=\"maint\">Set state to MAINT</option>" | |
- "<option value=\"dhlth\">Health: disable checks</option>" | |
- "<option value=\"ehlth\">Health: enable checks</option>" | |
- "<option value=\"hrunn\">Health: force UP</option>" | |
- "<option value=\"hnolb\">Health: force NOLB</option>" | |
- "<option value=\"hdown\">Health: force DOWN</option>" | |
- "<option value=\"dagent\">Agent: disable checks</option>" | |
- "<option value=\"eagent\">Agent: enable checks</option>" | |
- "<option value=\"arunn\">Agent: force UP</option>" | |
- "<option value=\"adown\">Agent: force DOWN</option>" | |
+ "<optgroup label=\"OP states\">" | |
+ "<option value=\"ready\">Set OP state to READY</option>" | |
+ "<option value=\"drain\">Set OP state to DRAIN</option>" | |
+ "<option value=\"maint\">Set OP state to MAINT</option>" | |
+ "</optgroup>" | |
+ "<optgroup label=\"BACKUP states\">" | |
+ "<option value=\"backup\">Set BACKUP state to ON</option>" | |
+ "<option value=\"active\">Set BACKUP state to OFF</option>" | |
+ "</optgroup>" | |
+ "<optgroup label=\"HEALTH actions\">" | |
+ "<option value=\"dhlth\">HEALTH: disable checks</option>" | |
+ "<option value=\"ehlth\">HEALTH: enable checks</option>" | |
+ "<option value=\"hrunn\">HEALTH: force UP</option>" | |
+ "<option value=\"hnolb\">HEALTH: force NOLB</option>" | |
+ "<option value=\"hdown\">HEALTH: force DOWN</option>" | |
+ "</optgroup>" | |
+ "<optgroup label=\"AGENT actions\">" | |
+ "<option value=\"dagent\">AGENT: disable checks</option>" | |
+ "<option value=\"eagent\">AGENT: enable checks</option>" | |
+ "<option value=\"arunn\">AGENT: force UP</option>" | |
+ "<option value=\"adown\">AGENT: force DOWN</option>" | |
+ "</optgroup>" | |
+ "<optgroup label=\"OTHER actions\">" | |
"<option value=\"shutdown\">Kill Sessions</option>" | |
+ "</optgroup>" | |
"</select>" | |
"<input type=\"hidden\" name=\"b\" value=\"#%d\">" | |
" <input type=\"submit\" value=\"Apply\">" | |
@@ -4891,6 +4924,12 @@ | |
else if (strcmp(value, "maint") == 0) { | |
action = ST_ADM_ACTION_MAINT; | |
} | |
+ else if (strcmp(value, "backup") == 0) { | |
+ action = ST_ADM_ACTION_BACKUP; | |
+ } | |
+ else if (strcmp(value, "active") == 0) { | |
+ action = ST_ADM_ACTION_ACTIVE; | |
+ } | |
else if (strcmp(value, "shutdown") == 0) { | |
action = ST_ADM_ACTION_SHUTDOWN; | |
} | |
@@ -5064,6 +5103,24 @@ | |
altered_servers++; | |
total_servers++; | |
break; | |
+ case ST_ADM_ACTION_BACKUP: | |
+ if (!(sv->flags & SRV_F_BACKUP)) { | |
+ sv->flags |= SRV_F_BACKUP; | |
+ px->srv_act --; | |
+ px->srv_bck ++; | |
+ altered_servers ++; | |
+ total_servers ++; | |
+ } | |
+ break; | |
+ case ST_ADM_ACTION_ACTIVE: | |
+ if (sv->flags & SRV_F_BACKUP) { | |
+ sv->flags &= ~SRV_F_BACKUP; | |
+ px->srv_act ++; | |
+ px->srv_bck --; | |
+ altered_servers ++; | |
+ total_servers ++; | |
+ } | |
+ break; | |
case ST_ADM_ACTION_SHUTDOWN: | |
if (px->state != PR_STSTOPPED) { | |
struct stream *sess, *sess_bck; | |
diff -urN a/src/server.c b/src/server.c | |
--- a/src/server.c 2016-06-26 17:41:01.000000000 +0000 | |
+++ b/src/server.c 2016-06-29 20:29:40.000000000 +0000 | |
@@ -1918,6 +1918,7 @@ | |
int srv_check_state, srv_agent_state; | |
int bk_f_forced_id; | |
int srv_f_forced_id; | |
+ int srv_is_backup; | |
msg = get_trash_chunk(); | |
switch (version) { | |
@@ -1937,6 +1938,7 @@ | |
* srv_agent_state: params[10] | |
* bk_f_forced_id: params[11] | |
* srv_f_forced_id: params[12] | |
+ * srv_is_backup: params[13] | |
*/ | |
/* validating srv_op_state */ | |
@@ -2045,6 +2047,13 @@ | |
if (p == params[12] || errno == EINVAL || errno == ERANGE || !((srv_f_forced_id == 0) || (srv_f_forced_id == 1))) | |
chunk_appendf(msg, ", invalid srv_f_forced_id value '%s'", params[12]); | |
+ /* validating srv_is_backup */ | |
+ p = NULL; | |
+ errno = 0; | |
+ srv_is_backup = strtol(params[13], &p, 10); | |
+ if (p == params[13] || errno == EINVAL || errno == ERANGE || !((srv_is_backup == 0) || (srv_is_backup == 1))) | |
+ chunk_appendf(msg, ", invalid srv_is_backup value '%s'", params[13]); | |
+ | |
/* don't apply anything if one error has been detected */ | |
if (msg->len) | |
@@ -2077,6 +2086,20 @@ | |
* state is different from new configuration state | |
*/ | |
/* configuration has changed */ | |
+ if (srv_is_backup) { | |
+ if (!(srv->flags & SRV_F_BACKUP)) { | |
+ srv->flags |= SRV_F_BACKUP; | |
+ srv->proxy->srv_act --; | |
+ srv->proxy->srv_bck ++; | |
+ } | |
+ } | |
+ else { | |
+ if (srv->flags & SRV_F_BACKUP) { | |
+ srv->flags &= ~SRV_F_BACKUP; | |
+ srv->proxy->srv_act ++; | |
+ srv->proxy->srv_bck --; | |
+ } | |
+ } | |
if ((srv_admin_state & SRV_ADMF_CMAINT) != (srv->admin & SRV_ADMF_CMAINT)) { | |
if (srv->admin & SRV_ADMF_CMAINT) | |
srv_adm_set_maint(srv); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment