if (!srv->eweight)
return 0;
- if (state & (SRV_STF_GOINGDOWN | SRV_STF_MAINTAIN))
+ if (srv->admin & SRV_ADMF_MAINT)
+ return 0;
+ if (state & SRV_STF_GOINGDOWN)
return 0;
if (!(state & SRV_STF_RUNNING))
return 0;
if (!srv->prev_eweight)
return 0;
- if (state & (SRV_STF_GOINGDOWN | SRV_STF_MAINTAIN))
+ if (srv->prev_admin & SRV_ADMF_MAINT)
+ return 0;
+ if (state & SRV_STF_GOINGDOWN)
return 0;
if (!(state & SRV_STF_RUNNING))
return 0;
static inline void srv_lb_commit_status(struct server *srv)
{
srv->prev_state = srv->state;
+ srv->prev_admin = srv->admin;
srv->prev_eweight = srv->eweight;
}
static inline int srv_lb_status_changed(const struct server *srv)
{
return (srv->state != srv->prev_state ||
+ srv->admin != srv->prev_admin ||
srv->eweight != srv->prev_eweight);
}
SRV_STF_RUNNING = 0x1, /* the server is UP */
SRV_STF_GOINGDOWN = 0x2, /* the server is going down (eg: 404) */
SRV_STF_WARMINGUP = 0x4, /* the server is warming up after a failure */
- SRV_STF_MAINTAIN = 0x8, /* the server is in maintenance mode */
+};
+
+/* Maintenance mode : each server may be in maintenance by itself or may inherit
+ * this status from another server it tracks. Let's store these origins here as
+ * flags. If no maintenance origin is specified, the server is not in maintenance.
+ */
+enum srv_admin {
+ SRV_ADMF_FMAINT = 0x1, /* the server was explicitly forced into maintenance */
+ SRV_ADMF_IMAINT = 0x2, /* the server has inherited the maintenance status from a tracked server */
+ SRV_ADMF_MAINT = 0x3, /* mask to check if any maintenance flag is present */
};
/* server flags */
struct server {
enum obj_type obj_type; /* object type == OBJ_TYPE_SERVER */
enum srv_state state, prev_state; /* server state among SRV_STF_* */
+ enum srv_admin admin, prev_admin; /* server maintenance status : SRV_ADMF_* */
unsigned char flags; /* server flags (SRV_F_*) */
struct server *next;
int cklen; /* the len of the cookie, to speed up checks */
smp->flags = SMP_F_VOL_TEST;
smp->type = SMP_T_BOOL;
- if (!(srv->state & SRV_STF_MAINTAIN) &&
+ if (!(srv->admin & SRV_ADMF_MAINT) &&
(!(srv->check.state & CHK_ST_CONFIGURED) || (srv->state & SRV_STF_RUNNING)))
smp->data.uint = 1;
else
}
/* if the other server is forced disabled, we have to do the same here */
- if (srv->state & SRV_STF_MAINTAIN) {
+ if (srv->admin & SRV_ADMF_MAINT) {
newsrv->state &= ~SRV_STF_RUNNING;
newsrv->check.health = 0;
newsrv->agent.health = 0;
struct server *srv;
int xferred;
- if (s->state & SRV_STF_MAINTAIN) {
+ if (s->admin & SRV_ADMF_MAINT) {
check->health = check->rise;
}
chunk_reset(&trash);
- if (s->state & SRV_STF_MAINTAIN) {
+ if (s->admin & SRV_ADMF_MAINT) {
chunk_appendf(&trash,
"%sServer %s/%s is DOWN for maintenance", s->flags & SRV_F_BACKUP ? "Backup " : "",
s->proxy->id, s->id);
s->counters.down_trans++;
for (srv = s->trackers; srv; srv = srv->tracknext)
- if (!(srv->state & SRV_STF_MAINTAIN))
+ if (!(srv->admin & SRV_ADMF_MAINT))
/* Only notify tracking servers that are not already in maintenance. */
set_server_down(&srv->check);
}
struct server *s = check->server;
struct server *srv;
int xferred;
- enum srv_state old_state = s->state;
+ enum srv_admin old_admin = s->admin;
- if (s->state & SRV_STF_MAINTAIN) {
+ if (s->admin & SRV_ADMF_MAINT) {
check->health = check->rise;
}
s->last_change = now.tv_sec;
s->state |= SRV_STF_RUNNING;
- s->state &= ~SRV_STF_MAINTAIN;
+ s->admin &= ~SRV_ADMF_FMAINT;
s->check.state &= ~CHK_ST_PAUSED;
if (s->slowstart > 0) {
chunk_reset(&trash);
- if (old_state & SRV_STF_MAINTAIN) {
+ if (old_admin) {
chunk_appendf(&trash,
"%sServer %s/%s is UP (leaving maintenance)", s->flags & SRV_F_BACKUP ? "Backup " : "",
s->proxy->id, s->id);
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
for (srv = s->trackers; srv; srv = srv->tracknext)
- if (!(srv->state & SRV_STF_MAINTAIN))
+ if (!(srv->admin & SRV_ADMF_MAINT))
/* Only notify tracking servers if they're not in maintenance. */
set_server_up(&srv->check);
}
/* by default, plan on stopping the task */
t->expire = TICK_ETERNITY;
- if ((s->state & (SRV_STF_RUNNING|SRV_STF_WARMINGUP|SRV_STF_MAINTAIN)) != (SRV_STF_RUNNING|SRV_STF_WARMINGUP))
+ if ((s->admin & SRV_ADMF_MAINT) ||
+ (s->state & (SRV_STF_RUNNING|SRV_STF_WARMINGUP)) != (SRV_STF_RUNNING|SRV_STF_WARMINGUP))
return t;
server_recalc_eweight(s);
set_server_disabled(check);
}
- if (!(s->state & SRV_STF_MAINTAIN) &&
+ if (!(s->admin & SRV_ADMF_MAINT) &&
check->health < check->rise + check->fall - 1) {
check->health++; /* was bad, stays for a while */
set_server_up(check);
if (!sv)
return 1;
- if (sv->state & SRV_STF_MAINTAIN) {
+ if (sv->admin & SRV_ADMF_MAINT) {
/* The server is really in maintenance, we can change the server state */
if (sv->track) {
/* If this server tracks the status of another one,
set_server_up(&sv->check);
sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
} else {
- sv->state &= ~SRV_STF_MAINTAIN;
+ sv->admin &= ~SRV_ADMF_FMAINT;
sv->check.state &= ~CHK_ST_PAUSED;
set_server_down(&sv->check);
}
if (!sv)
return 1;
- if (! (sv->state & SRV_STF_MAINTAIN)) {
+ if (!(sv->admin & SRV_ADMF_MAINT)) {
/* Not already in maintenance, we can change the server state */
- sv->state |= SRV_STF_MAINTAIN;
+ sv->admin |= SRV_ADMF_FMAINT;
sv->check.state |= CHK_ST_PAUSED;
set_server_down(&sv->check);
}
"<i>no check</i>"
};
- if ((sv->state & SRV_STF_MAINTAIN) || (ref->state & SRV_STF_MAINTAIN))
+ if ((sv->admin | ref->admin) & SRV_ADMF_MAINT)
chunk_appendf(&trash, "<tr class=\"maintain\">");
else
chunk_appendf(&trash,
/* status, lest check */
chunk_appendf(&trash, "<td class=ac>");
- if (sv->state & SRV_STF_MAINTAIN) {
+ if (sv->admin & SRV_ADMF_MAINT) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - sv->last_change, 1));
chunk_appendf(&trash, "MAINT");
}
- else if (ref != sv && ref->state & SRV_STF_MAINTAIN) {
+ else if (ref != sv && (ref->admin & SRV_ADMF_MAINT)) {
chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1));
chunk_appendf(&trash, "MAINT(via)");
}
ref->counters.down_trans, human_time(srv_downtime(sv), 1));
}
else if (sv != ref) {
- if (sv->state & SRV_STF_MAINTAIN)
+ if (sv->admin & SRV_ADMF_MAINT)
chunk_appendf(&trash, "<td class=ac colspan=3></td>");
else
chunk_appendf(&trash,
sv->counters.retries, sv->counters.redispatches);
/* status */
- if (sv->state & SRV_STF_MAINTAIN)
+ if (sv->admin & SRV_ADMF_MAINT)
chunk_appendf(&trash, "MAINT,");
- else if (ref != sv && ref->state & SRV_STF_MAINTAIN)
+ else if (ref != sv && (ref->admin & SRV_ADMF_MAINT))
chunk_appendf(&trash, "MAINT(via),");
else
chunk_appendf(&trash,
else
sv_state = 0; /* DOWN */
- if (((sv_state == 0) || (sv->state & SRV_STF_MAINTAIN)) && (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
+ if (((sv_state == 0) || (sv->admin & SRV_ADMF_MAINT)) && (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
/* do not report servers which are DOWN */
appctx->ctx.stats.sv = sv->next;
continue;
else if ((sv = findserver(px, value)) != NULL) {
switch (action) {
case ST_ADM_ACTION_DISABLE:
- if ((px->state != PR_STSTOPPED) && !(sv->state & SRV_STF_MAINTAIN)) {
+ if ((px->state != PR_STSTOPPED) && !(sv->admin & SRV_ADMF_MAINT)) {
/* Not already in maintenance, we can change the server state */
- sv->state |= SRV_STF_MAINTAIN;
+ sv->admin |= SRV_ADMF_FMAINT;
sv->check.state |= CHK_ST_PAUSED;
set_server_down(&sv->check);
altered_servers++;
}
break;
case ST_ADM_ACTION_ENABLE:
- if ((px->state != PR_STSTOPPED) && (sv->state & SRV_STF_MAINTAIN)) {
+ if ((px->state != PR_STSTOPPED) && (sv->admin & SRV_ADMF_MAINT)) {
/* Already in maintenance, we can change the server state.
* If this server tracks the status of another one,
* we must restore the good status.
sv->check.health = sv->check.rise; /* up, but will fall down at first failure */
}
else {
- sv->state &= ~SRV_STF_MAINTAIN;
+ sv->admin &= ~SRV_ADMF_FMAINT;
sv->check.state &= ~CHK_ST_PAUSED;
set_server_down(&sv->check);
}
do_check = 0;
do_agent = 0;
newsrv->flags = 0;
+ newsrv->admin = 0;
newsrv->state = SRV_STF_RUNNING; /* early server setup */
newsrv->last_change = now.tv_sec;
newsrv->id = strdup(args[1]);
cur_arg += 1;
}
else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
- newsrv->state |= SRV_STF_MAINTAIN;
+ newsrv->admin |= SRV_ADMF_FMAINT;
newsrv->state &= ~SRV_STF_RUNNING;
newsrv->check.state |= CHK_ST_PAUSED;
newsrv->check.health = 0;