/* Set a realserver IPVS rules */ static int init_service_rs(virtual_server * vs) { element e; real_server *rs; for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); /* In alpha mode, be pessimistic (or realistic?) and don't * add real servers into the VS pool. They will get there * later upon healthchecks recovery (if ever). */ if (vs->alpha) { UNSET_ALIVE(rs); continue; } if (!ISALIVE(rs)) { if (!ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs)) return 0; else SET_ALIVE(rs); } else if (vs->vsgname) { UNSET_ALIVE(rs); if (!ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs)) return 0; SET_ALIVE(rs); } } return 1; }
/* Set a virtualserver IPVS rules */ static int init_service_vs(virtual_server_t * vs) { /* Init the VS root */ if (!ISALIVE(vs) || vs->vsgname) { if (!ipvs_cmd(LVS_CMD_ADD, vs, NULL)) return 0; else SET_ALIVE(vs); } /* Processing real server queue */ if (!init_service_rs(vs)) return 0; if (vs->reloaded) { if (vs->vsgname) /* add reloaded dests into new vsg entries */ sync_service_vsg(vs); /* we may have got/lost quorum due to quorum setting changed */ update_quorum_state(vs); } return 1; }
/* Store new weight in real_server struct and then update kernel. */ void update_svr_wgt(int weight, virtual_server_t * vs, real_server_t * rs , int update_quorum) { if (weight != rs->weight) { log_message(LOG_INFO, "Changing weight from %d to %d for %s service %s of VS %s" , rs->weight , weight , ISALIVE(rs) ? "active" : "inactive" , FMT_RS(rs) , FMT_VS(vs)); rs->weight = weight; /* * Have weight change take effect now only if rs is in * the pool and alive and the quorum is met (or if * there is no sorry server). If not, it will take * effect later when it becomes alive. */ if (rs->set && ISALIVE(rs) && (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr))) ipvs_cmd(LVS_CMD_EDIT_DEST, vs, rs); if (update_quorum) update_quorum_state(vs); } }
/* Set a realserver IPVS rules */ static int init_service_rs(virtual_server_t * vs) { element e; real_server_t *rs; for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); /* Do not re-add failed RS instantly on reload */ if (rs->reloaded) { /* force re-adding of the rs into vs_group: * we may have new vsg entries */ if (vs->vsgname) UNSET_ALIVE(rs); continue; } /* In alpha mode, be pessimistic (or realistic?) and don't * add real servers into the VS pool. They will get there * later upon healthchecks recovery (if ever). */ if (vs->alpha) { UNSET_ALIVE(rs); continue; } if (!ISALIVE(rs)) { if (!ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs)) return 0; SET_ALIVE(rs); } } return 1; }
/* Set a virtualserver IPVS rules */ static int init_service_vs(virtual_server_t * vs) { /* Init the VS root */ if (!ISALIVE(vs) || vs->vsgname) { if (!ipvs_cmd(LVS_CMD_ADD, check_data->vs_group, vs, NULL)) return 0; else SET_ALIVE(vs); } /* Processing real server queue */ if (!LIST_ISEMPTY(vs->rs)) { if (vs->alpha && ! vs->reloaded) vs->quorum_state = DOWN; if (!init_service_rs(vs)) return 0; } /* if the service was reloaded, we may have got/lost quorum due to quorum setting changed */ if (vs->reloaded) update_quorum_state(vs); return 1; }
/* Set a realserver IPVS rules */ static int init_service_rs(virtual_server_t * vs) { element e; real_server_t *rs; if (LIST_ISEMPTY(vs->rs)) { log_message(LOG_WARNING, "VS [%s] has no configured RS! Skipping RS activation." , FMT_VS(vs)); return 1; } for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); if (rs->reloaded) { if (rs->iweight != rs->pweight) update_svr_wgt(rs->iweight, vs, rs, 0); /* Do not re-add failed RS instantly on reload */ continue; } /* In alpha mode, be pessimistic (or realistic?) and don't * add real servers into the VS pool. They will get there * later upon healthchecks recovery (if ever). */ if (!vs->alpha && !ISALIVE(rs)) { ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs); SET_ALIVE(rs); } } return 1; }
/* Store new weight in real_server struct and then update kernel. */ void update_svr_wgt(int weight, virtual_server * vs, real_server * rs) { char rsip[INET6_ADDRSTRLEN]; if (weight != rs->weight) { log_message(LOG_INFO, "Changing weight from %d to %d for %s service [%s]:%d of VS [%s]:%d" , rs->weight , weight , ISALIVE(rs) ? "active" : "inactive" , inet_sockaddrtos2(&rs->addr, rsip) , ntohs(inet_sockaddrport(&rs->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); rs->weight = weight; /* * Have weight change take effect now only if rs is in * the pool and alive and the quorum is met (or if * there is no sorry server). If not, it will take * effect later when it becomes alive. */ if (rs->set && ISALIVE(rs) && (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr))) ipvs_cmd(LVS_CMD_EDIT_DEST, check_data->vs_group, vs, rs); update_quorum_state(vs); } }
/* 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; }
/* Remove a realserver IPVS rule */ static int clear_service_rs(list vs_group, virtual_server * vs, list l) { element e; real_server *rs; char rsip[16], vsip[16]; for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); if (ISALIVE(rs)) { if (!ipvs_cmd(LVS_CMD_DEL_DEST , vs_group , 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:%d]" " in VS [%s:%d]" , rs->notify_down , inet_ntoa2(SVR_IP(rs), rsip) , ntohs(SVR_PORT(rs)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); notify_exec(rs->notify_down); } /* 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. */ if (vs->quorum_state == UP && vs->quorum_down && weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) { vs->quorum_state = DOWN; log_message(LOG_INFO, "Executing [%s] for VS [%s:%d]" , vs->quorum_down , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); notify_exec(vs->quorum_down); } } #ifdef _KRNL_2_2_ /* if we have a /32 mask, we create one nat rules per * realserver. */ if (vs->nat_mask == HOST_NETMASK) if (!ipfw_cmd(IP_FW_CMD_DEL, vs, rs)) return 0; #endif } return 1; }
/* Remove a virtualserver IPVS rule */ static int clear_service_vs(virtual_server_t * vs) { /* Processing real server queue */ if (!LIST_ISEMPTY(vs->rs)) { if (vs->s_svr) { if (ISALIVE(vs->s_svr)) ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr); } else if (!clear_service_rs(vs, vs->rs)) return 0; /* The above will handle Omega case for VS as well. */ } ipvs_cmd(LVS_CMD_DEL, vs, NULL); UNSET_ALIVE(vs); return 1; }
/* Set a realserver IPVS rules */ static int init_service_rs(virtual_server * vs) { element e; real_server *rs; for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); /* In alpha mode, be pessimistic (or realistic?) and don't * add real servers into the VS pool. They will get there * later upon healthchecks recovery (if ever). */ if (vs->alpha) { UNSET_ALIVE(rs); continue; } if (!ISALIVE(rs)) { if (!ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs)) return 0; else SET_ALIVE(rs); } else if (vs->vsgname) { UNSET_ALIVE(rs); if (!ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs)) return 0; SET_ALIVE(rs); } #ifdef _KRNL_2_2_ /* if we have a /32 mask, we create one nat rules per * realserver. */ if (vs->nat_mask == HOST_NETMASK) if (!ipfw_cmd(IP_FW_CMD_ADD, vs, rs)) return 0; #endif } return 1; }
/* Remove a realserver IPVS rule */ static int clear_service_rs(list vs_group, virtual_server * vs, list l) { element e; real_server *rs; char rsip[INET6_ADDRSTRLEN]; for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); if (ISALIVE(rs)) { if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs_group, 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]:%d in VS [%s]:%d" , rs->notify_down , inet_sockaddrtos2(&rs->addr, rsip) , ntohs(inet_sockaddrport(&rs->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); notify_exec(rs->notify_down); } /* 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. */ if (vs->quorum_state == UP && vs->quorum_down && weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) { vs->quorum_state = DOWN; log_message(LOG_INFO, "Executing [%s] for VS [%s]:%d" , vs->quorum_down , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); notify_exec(vs->quorum_down); } } } return 1; }
/* Set a virtualserver IPVS rules */ static int init_service_vs(virtual_server * vs) { /* Init the VS root */ if (!ISALIVE(vs) || vs->vsgname) { if (!ipvs_cmd(LVS_CMD_ADD, check_data->vs_group, vs, NULL)) return 0; else SET_ALIVE(vs); } /* Processing real server queue */ if (!LIST_ISEMPTY(vs->rs)) { if (vs->alpha) vs->quorum_state = DOWN; if (!init_service_rs(vs)) return 0; } return 1; }
/* add or remove _alive_ real servers from a virtual server */ static void perform_quorum_state(virtual_server_t *vs, int add) { element e; real_server_t *rs; if (LIST_ISEMPTY(vs->rs)) return; log_message(LOG_INFO, "%s the pool for VS %s" , add?"Adding alive servers to":"Removing alive servers from" , FMT_VS(vs)); for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); if (!ISALIVE(rs)) /* We only handle alive servers */ continue; if (add) rs->alive = 0; ipvs_cmd(add?LVS_CMD_ADD_DEST:LVS_CMD_DEL_DEST, vs, rs); rs->alive = 1; } }
/* add or remove _alive_ real servers from a virtual server */ void perform_quorum_state(virtual_server *vs, int add) { element e; real_server *rs; if (LIST_ISEMPTY(vs->rs)) return; log_message(LOG_INFO, "%s the pool for VS [%s]:%d" , add?"Adding alive servers to":"Removing alive servers from" , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); if (!ISALIVE(rs)) /* We only handle alive servers */ continue; if (add) rs->alive = 0; ipvs_cmd(add?LVS_CMD_ADD_DEST:LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs); rs->alive = 1; } }
/* Store new weight in real_server struct and then update kernel. */ void update_svr_wgt(int weight, virtual_server * vs, real_server * rs) { char rsip[16], vsip[16]; if (weight != rs->weight) { log_message(LOG_INFO, "Changing weight from %d to %d for %s service [%s:%d]" " of VS [%s:%d]" , rs->weight , weight , ISALIVE(rs) ? "active" : "inactive" , inet_ntoa2(SVR_IP(rs), rsip) , ntohs(SVR_PORT(rs)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); rs->weight = weight; /* * Have weight change take effect now only if rs is alive. * If not, it will take effect later when it becomes alive. */ if (ISALIVE(rs)) ipvs_cmd(LVS_CMD_EDIT_DEST, check_data->vs_group, vs, rs); } }
/* Set a realserver IPVS rules */ static int init_service_rs(virtual_server_t * vs) { element e; real_server_t *rs; for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) { rs = ELEMENT_DATA(e); /* Do not re-add failed RS instantly on reload */ if (rs->reloaded) continue; /* In alpha mode, be pessimistic (or realistic?) and don't * add real servers into the VS pool. They will get there * later upon healthchecks recovery (if ever). */ if (!vs->alpha && !ISALIVE(rs)) { if (!ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs)) return 0; SET_ALIVE(rs); } } return 1; }
/* manipulate add/remove rs according to alive state */ void perform_svr_state(int alive, virtual_server * vs, real_server * rs) { char rsip[INET6_ADDRSTRLEN]; /* * | ISALIVE(rs) | alive | context * | 0 | 0 | first check failed under alpha mode, unreachable here * | 0 | 1 | RS went up, add it to the pool * | 1 | 0 | RS went down, remove it from the pool * | 1 | 1 | first check succeeded w/o alpha mode, unreachable here */ if (!ISALIVE(rs) && alive) { log_message(LOG_INFO, "%s service [%s]:%d to VS [%s]:%d" , (rs->inhibit) ? "Enabling" : "Adding" , inet_sockaddrtos2(&rs->addr, rsip) , ntohs(inet_sockaddrport(&rs->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); /* Add only if we have quorum or no sorry server */ if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) { ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs); } rs->alive = alive; if (rs->notify_up) { log_message(LOG_INFO, "Executing [%s] for service [%s]:%d in VS [%s]:%d" , rs->notify_up , inet_sockaddrtos2(&rs->addr, rsip) , ntohs(inet_sockaddrport(&rs->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); notify_exec(rs->notify_up); } /* We may have gained quorum */ update_quorum_state(vs); } if (ISALIVE(rs) && !alive) { log_message(LOG_INFO, "%s service [%s]:%d from VS [%s]:%d" , (rs->inhibit) ? "Disabling" : "Removing" , inet_sockaddrtos2(&rs->addr, rsip) , ntohs(inet_sockaddrport(&rs->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); /* server is down, it is removed from the LVS realserver pool * Remove only if we have quorum or no sorry server */ if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) { ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs); } rs->alive = alive; if (rs->notify_down) { log_message(LOG_INFO, "Executing [%s] for service [%s]:%d in VS [%s]:%d" , rs->notify_down , inet_sockaddrtos2(&rs->addr, rsip) , ntohs(inet_sockaddrport(&rs->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); notify_exec(rs->notify_down); } /* We may have lost quorum */ update_quorum_state(vs); } }
/* manipulate add/remove rs according to alive state */ static int perform_svr_state(int alive, virtual_server_t * vs, real_server_t * rs) { /* * | ISALIVE(rs) | alive | context * | 0 | 0 | first check failed under alpha mode, unreachable here * | 0 | 1 | RS went up, add it to the pool * | 1 | 0 | RS went down, remove it from the pool * | 1 | 1 | first check succeeded w/o alpha mode, unreachable here */ if (!ISALIVE(rs) && alive) { log_message(LOG_INFO, "%s service %s to VS %s" , (rs->inhibit) ? "Enabling" : "Adding" , FMT_RS(rs) , FMT_VS(vs)); /* Add only if we have quorum or no sorry server */ if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) { if (ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs)) return -1; } rs->alive = alive; if (rs->notify_up) { log_message(LOG_INFO, "Executing [%s] for service %s in VS %s" , rs->notify_up , FMT_RS(rs) , FMT_VS(vs)); notify_exec(rs->notify_up); } #ifdef _WITH_SNMP_CHECKER_ check_snmp_rs_trap(rs, vs); #endif /* We may have gained quorum */ update_quorum_state(vs); } if (ISALIVE(rs) && !alive) { log_message(LOG_INFO, "%s service %s from VS %s" , (rs->inhibit) ? "Disabling" : "Removing" , FMT_RS(rs) , FMT_VS(vs)); /* server is down, it is removed from the LVS realserver pool * Remove only if we have quorum or no sorry server */ if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) { if (ipvs_cmd(LVS_CMD_DEL_DEST, vs, rs)) return -1; } rs->alive = alive; 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_CHECKER_ check_snmp_rs_trap(rs, vs); #endif /* We may have lost quorum */ update_quorum_state(vs); } return 0; }
/* 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; } }
/* manipulate add/remove rs according to alive state */ void perform_svr_state(int alive, virtual_server * vs, real_server * rs) { char rsip[16], vsip[16]; /* * | ISALIVE(rs) | alive | context * | 0 | 0 | first check failed under alpha mode, unreachable here * | 0 | 1 | RS went up, add it to the pool * | 1 | 0 | RS went down, remove it from the pool * | 1 | 1 | first check succeeded w/o alpha mode, unreachable here */ if (!ISALIVE(rs) && alive) { /* adding a server to the vs pool, if sorry server is flagged alive, * we remove it from the vs pool. */ if (vs->s_svr) { if (ISALIVE(vs->s_svr) && (vs->quorum_state == UP || (weigh_live_realservers(vs) + rs->weight >= vs->quorum + vs->hysteresis))) { log_message(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]", inet_ntoa2(SVR_IP(vs->s_svr), rsip) , ntohs(SVR_PORT(vs->s_svr)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); ipvs_cmd(LVS_CMD_DEL_DEST , check_data->vs_group , vs , vs->s_svr); vs->s_svr->alive = 0; #ifdef _KRNL_2_2_ ipfw_cmd(IP_FW_CMD_DEL, vs, vs->s_svr); #endif } } log_message(LOG_INFO, "%s service [%s:%d] to VS [%s:%d]", (rs->inhibit) ? "Enabling" : "Adding" , inet_ntoa2(SVR_IP(rs), rsip) , ntohs(SVR_PORT(rs)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs); rs->alive = alive; if (rs->notify_up) { log_message(LOG_INFO, "Executing [%s] for service [%s:%d]" " in VS [%s:%d]" , rs->notify_up , inet_ntoa2(SVR_IP(rs), rsip) , ntohs(SVR_PORT(rs)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); notify_exec(rs->notify_up); } /* If we have just gained quorum, it's time to consider notify_up. */ if (vs->quorum_state == DOWN && weigh_live_realservers(vs) >= vs->quorum + vs->hysteresis) { vs->quorum_state = UP; log_message(LOG_INFO, "Gained quorum %lu+%lu=%lu <= %u for VS [%s:%d]" , vs->quorum , vs->hysteresis , vs->quorum + vs->hysteresis , weigh_live_realservers(vs) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); if (vs->quorum_up) { log_message(LOG_INFO, "Executing [%s] for VS [%s:%d]" , vs->quorum_up , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); notify_exec(vs->quorum_up); } } #ifdef _KRNL_2_2_ if (vs->nat_mask == HOST_NETMASK) ipfw_cmd(IP_FW_CMD_ADD, vs, rs); #endif return; } if (ISALIVE(rs) && !alive) { log_message(LOG_INFO, "%s service [%s:%d] from VS [%s:%d]", (rs->inhibit) ? "Disabling" : "Removing" , inet_ntoa2(SVR_IP(rs), rsip) , ntohs(SVR_PORT(rs)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); /* server is down, it is removed from the LVS realserver pool */ ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs); rs->alive = alive; if (rs->notify_down) { log_message(LOG_INFO, "Executing [%s] for service [%s:%d]" " in VS [%s:%d]" , rs->notify_down , inet_ntoa2(SVR_IP(rs), rsip) , ntohs(SVR_PORT(rs)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); notify_exec(rs->notify_down); } #ifdef _KRNL_2_2_ if (vs->nat_mask == HOST_NETMASK) ipfw_cmd(IP_FW_CMD_DEL, vs, rs); #endif /* 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 && weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) { vs->quorum_state = DOWN; log_message(LOG_INFO, "Lost quorum %lu-%lu=%lu > %u for VS [%s:%d]" , vs->quorum , vs->hysteresis , vs->quorum - vs->hysteresis , weigh_live_realservers(vs) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); if (vs->quorum_down) { log_message(LOG_INFO, "Executing [%s] for VS [%s:%d]" , vs->quorum_down , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); notify_exec(vs->quorum_down); } if (vs->s_svr) { log_message(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]", inet_ntoa2(SVR_IP(vs->s_svr), rsip) , ntohs(SVR_PORT(vs->s_svr)) , (vs->vsgname) ? vs->vsgname : inet_ntoa2(SVR_IP(vs), vsip) , ntohs(SVR_PORT(vs))); /* the sorry server is now up in the pool, we flag it alive */ ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, vs->s_svr); vs->s_svr->alive = 1; #ifdef _KRNL_2_2_ ipfw_cmd(IP_FW_CMD_ADD, vs, vs->s_svr); #endif } } } }
/* set quorum state depending on current weight of real servers */ void update_quorum_state(virtual_server * vs) { char rsip[INET6_ADDRSTRLEN]; /* If we have just gained quorum, it's time to consider notify_up. */ if (vs->quorum_state == DOWN && weigh_live_realservers(vs) >= vs->quorum + vs->hysteresis) { vs->quorum_state = UP; log_message(LOG_INFO, "Gained quorum %lu+%lu=%lu <= %u for VS [%s]:%d" , vs->quorum , vs->hysteresis , vs->quorum + vs->hysteresis , weigh_live_realservers(vs) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); if (vs->s_svr && ISALIVE(vs->s_svr)) { log_message(LOG_INFO, "Removing sorry server [%s]:%d from VS [%s]:%d" , inet_sockaddrtos2(&vs->s_svr->addr, rsip) , ntohs(inet_sockaddrport(&vs->s_svr->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, 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]:%d" , vs->quorum_up , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); notify_exec(vs->quorum_up); } 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 && weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) { vs->quorum_state = DOWN; log_message(LOG_INFO, "Lost quorum %lu-%lu=%lu > %u for VS [%s]:%d" , vs->quorum , vs->hysteresis , vs->quorum - vs->hysteresis , weigh_live_realservers(vs) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); if (vs->quorum_down) { log_message(LOG_INFO, "Executing [%s] for VS [%s]:%d" , vs->quorum_down , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); notify_exec(vs->quorum_down); } if (vs->s_svr) { log_message(LOG_INFO, "Adding sorry server [%s]:%d to VS [%s]:%d" , inet_sockaddrtos2(&vs->s_svr->addr, rsip) , ntohs(inet_sockaddrport(&vs->s_svr->addr)) , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr) , ntohs(inet_sockaddrport(&vs->addr))); /* the sorry server is now up in the pool, we flag it alive */ ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, vs->s_svr); vs->s_svr->alive = 1; /* Remove remaining alive real servers */ perform_quorum_state(vs, 0); } return; } }