Skip to content

Instantly share code, notes, and snippets.

@arslanm
Last active October 24, 2017 13:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save arslanm/9d0b93c414b7645e9a74731ed37b91c0 to your computer and use it in GitHub Desktop.
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
$ 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\">"
"&nbsp;<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