/* Remove a realserver IPVS rule */ static int clear_service_rs(virtual_server_t * vs, list l) { element e; real_server_t *rs; long weight_sum; long down_threshold = vs->quorum - vs->hysteresis; for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); if (ISALIVE(rs)) { log_message(LOG_INFO, "Removing service %s from VS %s" , FMT_RS(rs) , FMT_VS(vs)); if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, rs)) return 0; UNSET_ALIVE(rs); if (!vs->omega) continue; /* In Omega mode we call VS and RS down notifiers * all the way down the exit, as necessary. */ if (rs->notify_down) { log_message(LOG_INFO, "Executing [%s] for service %s in VS %s" , rs->notify_down , FMT_RS(rs) , FMT_VS(vs)); notify_exec(rs->notify_down); } #ifdef _WITH_SNMP_ check_snmp_rs_trap(rs, vs); #endif /* Sooner or later VS will lose the quorum (if any). However, * we don't push in a sorry server then, hence the regression * is intended. */ weight_sum = weigh_live_realservers(vs); if (vs->quorum_state == UP && ( !weight_sum || weight_sum < down_threshold) ) { vs->quorum_state = DOWN; if (vs->quorum_down) { log_message(LOG_INFO, "Executing [%s] for VS %s" , vs->quorum_down , FMT_VS(vs)); notify_exec(vs->quorum_down); } #ifdef _WITH_SNMP_ check_snmp_quorum_trap(vs); #endif } } } return 1; }
/* set quorum state depending on current weight of real servers */ static void update_quorum_state(virtual_server_t * vs) { long weight_sum = weigh_live_realservers(vs); long up_threshold = vs->quorum + vs->hysteresis; long down_threshold = vs->quorum - vs->hysteresis; /* If we have just gained quorum, it's time to consider notify_up. */ if (vs->quorum_state == DOWN && weight_sum >= up_threshold) { vs->quorum_state = UP; log_message(LOG_INFO, "Gained quorum %lu+%lu=%li <= %li for VS %s" , vs->quorum , vs->hysteresis , up_threshold , weight_sum , FMT_VS(vs)); if (vs->s_svr && ISALIVE(vs->s_svr)) { log_message(LOG_INFO, "%s sorry server %s from VS %s" , (vs->s_svr->inhibit ? "Disabling" : "Removing") , FMT_RS(vs->s_svr) , FMT_VS(vs)); ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr); vs->s_svr->alive = 0; /* Adding back alive real servers */ perform_quorum_state(vs, 1); } if (vs->quorum_up) { log_message(LOG_INFO, "Executing [%s] for VS %s" , vs->quorum_up , FMT_VS(vs)); notify_exec(vs->quorum_up); } #ifdef _WITH_SNMP_CHECKER_ check_snmp_quorum_trap(vs); #endif return; } /* If we have just lost quorum for the VS, we need to consider * VS notify_down and sorry_server cases */ if (vs->quorum_state == UP && (!weight_sum || weight_sum < down_threshold) ) { vs->quorum_state = DOWN; log_message(LOG_INFO, "Lost quorum %lu-%lu=%li > %li for VS %s" , vs->quorum , vs->hysteresis , down_threshold , weight_sum , FMT_VS(vs)); if (vs->quorum_down) { log_message(LOG_INFO, "Executing [%s] for VS %s" , vs->quorum_down , FMT_VS(vs)); notify_exec(vs->quorum_down); } if (vs->s_svr) { log_message(LOG_INFO, "%s sorry server %s to VS %s" , (vs->s_svr->inhibit ? "Enabling" : "Adding") , FMT_RS(vs->s_svr) , FMT_VS(vs)); /* the sorry server is now up in the pool, we flag it alive */ ipvs_cmd(LVS_CMD_ADD_DEST, vs, vs->s_svr); vs->s_svr->alive = 1; /* Remove remaining alive real servers */ perform_quorum_state(vs, 0); } #ifdef _WITH_SNMP_CHECKER_ check_snmp_quorum_trap(vs); #endif return; } }