/* * Soft: Keepalived is a failover program for the LVS project * . It monitor & manipulate * a loadbalanced server pool using multi-layer checks. * * Part: Interface tracking framework. * * Author: Alexandre Cassen, * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Copyright (C) 2001-2017 Alexandre Cassen, */ #include "config.h" #include #include #include #include #include #include #include #include /* local include */ #include "vrrp_track.h" #include "vrrp_data.h" #include "vrrp.h" #include "vrrp_sync.h" #include "logger.h" #include "memory.h" #include "vrrp_scheduler.h" #include "scheduler.h" #include "parser.h" #include "utils.h" #include "vrrp_notify.h" #include "bitops.h" #include "track_file.h" #ifdef _WITH_CN_PROC_ #include "track_process.h" #endif /* Track interface dump */ static void dump_track_if(FILE *fp, const tracked_if_t *tip) { conf_write(fp, " %s weight %d%s", IF_NAME(tip->ifp), tip->weight, tip->weight_reverse ? " reverse" : ""); } void dump_track_if_list(FILE *fp, const list_head_t *l) { tracked_if_t *tip; list_for_each_entry(tip, l, e_list) dump_track_if(fp, tip); } void free_track_if(tracked_if_t *tip) { list_del_init(&tip->e_list); FREE(tip); } void free_track_if_list(list_head_t *l) { tracked_if_t *tip, *tip_tmp; list_for_each_entry_safe(tip, tip_tmp, l, e_list) free_track_if(tip); } void alloc_track_if(const char *name, list_head_t *l, const vector_t *strvec) { interface_t *ifp; tracked_if_t *tip; int weight = 0; const char *tracked = strvec_slot(strvec, 0); bool reverse = false; ifp = if_get_by_ifname(tracked, IF_CREATE_IF_DYNAMIC); if (!ifp) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) tracked interface %s doesn't exist" , name, tracked); return; } /* Check this vrrp isn't already tracking the i/f */ list_for_each_entry(tip, l, e_list) { if (tip->ifp == ifp) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_interface %s - ignoring" , name, tracked); return; } } if (vector_size(strvec) >= 2) { if (strcmp(strvec_slot(strvec, 1), "weight")) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_interface %s" " option %s - ignoring" , name, tracked, strvec_slot(strvec, 1)); return; } if (vector_size(strvec) == 2) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified" " for track_interface %s - ignoring" , name, tracked); return; } if (!read_int_strvec(strvec, 2, &weight, -254, 254, true)) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight %s for %s must be" " between [-253..253] inclusive. Ignoring..." , name, strvec_slot(strvec, 2), tracked); weight = 0; } else if (weight == -254 || weight == 254) { /* This check can be removed once users have migrated away from +/-254 */ report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for %s cannot be +/-254." " Setting to +/-253" , name, tracked); weight = weight == -254 ? -253 : 253; } if (vector_size(strvec) >= 4) { if (!strcmp(strvec_slot(strvec, 3), "reverse")) reverse = true; else report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_interace %s" " weight option %s - ignoring" , name, tracked, strvec_slot(strvec, 3)); } } tip = (tracked_if_t *) MALLOC(sizeof(tracked_if_t)); INIT_LIST_HEAD(&tip->e_list); tip->ifp = ifp; tip->weight = weight; tip->weight_reverse = reverse; list_add_tail(&tip->e_list, l); } vrrp_script_t * __attribute__ ((pure)) find_script_by_name(const char *name) { vrrp_script_t *scr; list_for_each_entry(scr, &vrrp_data->vrrp_script, e_list) { if (!strcmp(scr->sname, name)) return scr; } return NULL; } /* Track script dump */ static void dump_track_script(FILE *fp, const tracked_sc_t *tsc) { conf_write(fp, " %s weight %d%s", tsc->scr->sname, tsc->weight, tsc->weight_reverse ? " reverse" : ""); } void dump_track_script_list(FILE *fp, const list_head_t *l) { tracked_sc_t *tsc; list_for_each_entry(tsc, l, e_list) dump_track_script(fp, tsc); } void free_track_script(tracked_sc_t *tsc) { list_del_init(&tsc->e_list); FREE(tsc); } void free_track_script_list(list_head_t *l) { tracked_sc_t *tsc, *tsc_tmp; list_for_each_entry_safe(tsc, tsc_tmp, l, e_list) free_track_script(tsc); } void alloc_track_script(const char *name, list_head_t *l, const vector_t *strvec) { vrrp_script_t *vsc; tracked_sc_t *tsc; int weight; const char *tracked = strvec_slot(strvec, 0); tracked_sc_t *etsc; bool reverse; vsc = find_script_by_name(tracked); /* Ignoring if no script found */ if (!vsc) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) track script %s not found, ignoring..." , name, tracked); return; } /* Check this vrrp isn't already tracking the script */ list_for_each_entry(etsc, l, e_list) { if (etsc->scr == vsc) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_script %s - ignoring" , name, tracked); return; } } /* default weight */ weight = vsc->weight; reverse = vsc->weight_reverse; if (vector_size(strvec) >= 2) { if (strcmp(strvec_slot(strvec, 1), "weight")) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track script option %s - ignoring" , name, strvec_slot(strvec, 1)); return; } if (vector_size(strvec) == 2) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified for" " track script %s - ignoring" , name, tracked); return; } if (!read_int_strvec(strvec, 2, &weight, -254, 254, true)) { weight = vsc->weight; report_config_error(CONFIG_GENERAL_ERROR, "(%s) track script %s: weight must be" " between [-253..253] inclusive, ignoring..." , name, tracked); } else if (weight == -254 || weight == 254) { /* This check can be removed once users have migrated away from +/-254 */ report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for %s cannot be +/-254." " Setting to +/-253" , name, tracked); weight = weight == -254 ? -253 : 253; } if (vector_size(strvec) >= 4) { if (!strcmp(strvec_slot(strvec, 3), "reverse")) reverse = true; else if (!strcmp(strvec_slot(strvec, 3), "noreverse")) reverse = false; else report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_script %s" " weight option %s - ignoring" , name, tracked, strvec_slot(strvec, 3)); } } tsc = (tracked_sc_t *) MALLOC(sizeof(tracked_sc_t)); INIT_LIST_HEAD(&tsc->e_list); tsc->scr = vsc; tsc->weight = weight; tsc->weight_reverse = reverse; vsc->init_state = SCRIPT_INIT_STATE_INIT; list_add_tail(&tsc->e_list, l); } #ifdef _WITH_CN_PROC_ static vrrp_tracked_process_t * __attribute__ ((pure)) find_tracked_process_by_name(const char *name) { vrrp_tracked_process_t *process; list_for_each_entry(process, &vrrp_data->vrrp_track_processes, e_list) { if (!strcmp(process->pname, name)) return process; } return NULL; } /* Track process dump */ static void dump_track_process(FILE *fp, const tracked_process_t *tprocess) { conf_write(fp, " %s, weight %d%s", tprocess->process->pname , tprocess->weight, tprocess->weight_reverse ? " reverse" : ""); } void dump_track_process_list(FILE *fp, const list_head_t *l) { tracked_process_t *tprocess; list_for_each_entry(tprocess, l, e_list) dump_track_process(fp, tprocess); } void free_track_process_list(list_head_t *l) { tracked_process_t *tprocess, *tprocess_tmp; list_for_each_entry_safe(tprocess, tprocess_tmp, l, e_list) FREE(tprocess); } void alloc_track_process(const char *name, list_head_t *l, const vector_t *strvec) { vrrp_tracked_process_t *vsp; const char *tracked = strvec_slot(strvec, 0); tracked_process_t *tprocess; int weight; bool reverse; vsp = find_tracked_process_by_name(tracked); /* Ignoring if no process found */ if (!vsp) { if (proc_events_not_supported) report_config_error(CONFIG_GENERAL_ERROR, "(%s) track process not supported by kernel" , name); else report_config_error(CONFIG_GENERAL_ERROR, "(%s) track process %s not found, ignoring..." , name, tracked); return; } /* Check this vrrp isn't already tracking the process */ list_for_each_entry(tprocess, l, e_list) { if (tprocess->process == vsp) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_process %s - ignoring" , name, tracked); return; } } weight = vsp->weight; reverse = vsp->weight_reverse; if (vector_size(strvec) >= 2) { if (strcmp(strvec_slot(strvec, 1), "weight")) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track process option %s - ignoring" , name, strvec_slot(strvec, 1)); return; } if (vector_size(strvec) == 2) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified for" " track process %s - ignoring" , name, tracked); return; } if (!read_int_strvec(strvec, 2, &weight, -254, 254, true)) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for track process %s must be in " "[-254..254] inclusive. Ignoring..." , name, tracked); weight = vsp->weight; } if (vector_size(strvec) >= 4) { if (!strcmp(strvec_slot(strvec, 3), "reverse")) reverse = true; else if (!strcmp(strvec_slot(strvec, 3), "noreverse")) reverse = false; else report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_process %s weight" " option %s - ignoring" , name, tracked, strvec_slot(strvec, 3)); } } PMALLOC(tprocess); INIT_LIST_HEAD(&tprocess->e_list); tprocess->process = vsp; tprocess->weight = weight; tprocess->weight_reverse = reverse; list_add_tail(&tprocess->e_list, l); } #endif #ifdef _WITH_BFD_ /* VRRP Track bfd related */ vrrp_tracked_bfd_t * __attribute__ ((pure)) find_vrrp_tracked_bfd_by_name(const char *name) { vrrp_tracked_bfd_t *bfd; list_for_each_entry(bfd, &vrrp_data->vrrp_track_bfds, e_list) { if (!strcmp(bfd->bname, name)) return bfd; } return NULL; } void alloc_vrrp_tracked_bfd(const char *name, list_head_t *l) { vrrp_tracked_bfd_t *tbfd; if (strlen(name) >= BFD_INAME_MAX) { report_config_error(CONFIG_GENERAL_ERROR, "BFD name %s too long", name); skip_block(true); return; } list_for_each_entry(tbfd, l, e_list) { if (!strcmp(name, tbfd->bname)) { report_config_error(CONFIG_GENERAL_ERROR, "BFD %s already specified", name); skip_block(true); return; } } PMALLOC(tbfd); INIT_LIST_HEAD(&tbfd->e_list); strncpy(tbfd->bname, name, BFD_INAME_MAX-1); /* Not really need, but... */ tbfd->weight = 0; tbfd->weight_reverse = false; tbfd->bfd_up = false; INIT_LIST_HEAD(&tbfd->tracking_vrrp); list_add_tail(&tbfd->e_list, l); } /* Track bfd related */ static void dump_tracked_bfd(FILE *fp, const tracked_bfd_t *tbfd) { conf_write(fp, " %s: weight %d%s", tbfd->bfd->bname, tbfd->weight, tbfd->weight_reverse ? " reverse" : ""); } void dump_tracked_bfd_list(FILE *fp, const list_head_t *l) { tracked_bfd_t *tbfd; list_for_each_entry(tbfd, l, e_list) dump_tracked_bfd(fp, tbfd); } void free_track_bfd(tracked_bfd_t *tbfd) { list_del_init(&tbfd->e_list); FREE(tbfd); } void free_track_bfd_list(list_head_t *l) { tracked_bfd_t *tbfd, *tbfd_tmp; list_for_each_entry_safe(tbfd, tbfd_tmp, l, e_list) free_track_bfd(tbfd); } void alloc_track_bfd(const char *name, list_head_t *l, const vector_t *strvec) { vrrp_tracked_bfd_t *vtb; tracked_bfd_t *tbfd; const char *tracked = strvec_slot(strvec, 0); tracked_bfd_t *etbfd; int weight; bool reverse = false; vtb = find_vrrp_tracked_bfd_by_name(tracked); /* Ignoring if no bfd found */ if (!vtb) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) track bfd %s not found, ignoring..." , name, tracked); return; } /* Check this vrrp isn't already tracking the bfd */ list_for_each_entry(etbfd, l, e_list) { if (etbfd->bfd == vtb) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_bfd %s - ignoring" , name, tracked); return; } } weight = vtb->weight; reverse = vtb->weight_reverse; if (vector_size(strvec) >= 2) { if (strcmp(strvec_slot(strvec, 1), "weight")) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track bfd %s option %s - ignoring" , name, tracked, strvec_slot(strvec, 1)); return; } if (vector_size(strvec) == 2) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified" " for track bfd %s - ignoring" , name, tracked); return; } if (!read_int_strvec(strvec, 2, &weight, -253, 253, true)) { report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for track bfd %s must be in " "[-253..253] inclusive. Ignoring..." , name, tracked); weight = vtb->weight; } if (vector_size(strvec) >= 4) { if (!strcmp(strvec_slot(strvec, 3), "reverse")) reverse = true; else if (!strcmp(strvec_slot(strvec, 3), "noreverse")) reverse = false; else { report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track bfd %s weight" " option %s - ignoring" , name, tracked, strvec_slot(strvec, 3)); return; } } } PMALLOC(tbfd); INIT_LIST_HEAD(&tbfd->e_list); tbfd->bfd = vtb; tbfd->weight = weight; tbfd->weight_reverse = reverse; list_add_tail(&tbfd->e_list, l); } #endif void down_instance(vrrp_t *vrrp) { if (vrrp->num_script_if_fault++ == 0 || vrrp->state == VRRP_STATE_INIT) { vrrp->wantstate = VRRP_STATE_FAULT; if (vrrp->state == VRRP_STATE_MAST) vrrp_state_leave_master(vrrp, true); else vrrp_state_leave_fault(vrrp); if (vrrp->sync && vrrp->sync->num_member_fault++ == 0) vrrp_sync_fault(vrrp); } } /* Set effective priorty, issue message on changes */ void vrrp_set_effective_priority(vrrp_t *vrrp) { uint8_t new_prio; uint32_t old_down_timer; /* Don't change priority if address owner */ if (vrrp->base_priority == VRRP_PRIO_OWNER) return; if (vrrp->total_priority < 1) new_prio = 1; else if (vrrp->total_priority >= VRRP_PRIO_OWNER) new_prio = VRRP_PRIO_OWNER - 1; else new_prio = (uint8_t)vrrp->total_priority; if (vrrp->effective_priority == new_prio) return; log_message(LOG_INFO, "(%s) Changing effective priority from %d to %d", vrrp->iname, vrrp->effective_priority, new_prio); vrrp->effective_priority = new_prio; old_down_timer = vrrp->ms_down_timer; vrrp->ms_down_timer = 3 * vrrp->master_adver_int + VRRP_TIMER_SKEW(vrrp); if (vrrp->state == VRRP_STATE_BACK) { if (old_down_timer < vrrp->ms_down_timer) vrrp->sands = timer_add_long(vrrp->sands, vrrp->ms_down_timer - old_down_timer); else vrrp->sands = timer_sub_long(vrrp->sands, old_down_timer - vrrp->ms_down_timer); vrrp_thread_requeue_read(vrrp); } if (vrrp->notify_priority_changes) send_instance_priority_notifies(vrrp); } static void process_script_update_priority(int weight, int multiplier, vrrp_script_t *vscript, bool script_ok, vrrp_t *vrrp) { bool instance_left_init = false; if (!weight) { if (vscript->init_state == SCRIPT_INIT_STATE_INIT) { /* We need to adjust the number of scripts in init state */ if (!--vrrp->num_script_init) { instance_left_init = true; if (vrrp->sync) vrrp->sync->num_member_init--; } } if (script_ok != (multiplier == 1)) { /* The instance needs to go down */ down_instance(vrrp); } else if (!vrrp->num_script_init && (!vrrp->sync || !vrrp->sync->num_member_init)) { /* The instance can come up */ try_up_instance(vrrp, instance_left_init); // Set want_state = BACKUP/MASTER, and check i/fs and sync groups } return; } if (vscript->init_state == SCRIPT_INIT_STATE_INIT) { /* If the script hasn't previously exited, we need to only adjust the priority if the state the script is now in causes an adjustment to the priority */ if (script_ok) { if (weight > 0) vrrp->total_priority += weight * multiplier; } else { if (weight < 0) vrrp->total_priority += weight * multiplier; } } else { if (script_ok) vrrp->total_priority += abs(weight) * multiplier; else vrrp->total_priority -= abs(weight) * multiplier; } vrrp_set_effective_priority(vrrp); } void update_script_priorities(vrrp_script_t *vscript, bool script_ok) { tracking_obj_t* top; vrrp_t *vrrp; /* First process the vrrp instances tracking the script */ list_for_each_entry(top, &vscript->tracking_vrrp, e_list) { vrrp = top->obj.vrrp; process_script_update_priority(top->weight, top->weight_multiplier, vscript, script_ok, vrrp); } } static void initialise_track_script_state(tracked_sc_t *tsc, vrrp_t *vrrp) { if (!tsc->weight) { if (tsc->scr->init_state == SCRIPT_INIT_STATE_INIT) vrrp->num_script_init++; else if (tsc->scr->init_state == SCRIPT_INIT_STATE_FAILED || (tsc->scr->result >= 0 && tsc->scr->result < tsc->scr->rise)) { /* The script is in fault state */ vrrp->num_script_if_fault++; log_message(LOG_INFO, "(%s): entering FAULT state due to script %s", vrrp->iname, tsc->scr->sname); vrrp->state = VRRP_STATE_FAULT; } return; } /* Don't change effective priority if address owner */ if (vrrp->base_priority == VRRP_PRIO_OWNER) return; if (tsc->scr->init_state != SCRIPT_INIT_STATE_INIT) { if (tsc->scr->result >= tsc->scr->rise) { if (tsc->weight > 0) vrrp->total_priority += tsc->weight; } else { if (tsc->weight < 0) vrrp->total_priority += tsc->weight; } } } #ifdef _WITH_BFD_ static void initialise_track_bfd_state(tracked_bfd_t *tbfd, vrrp_t *vrrp) { int multiplier = tbfd->weight_reverse ? -1 : 1; if (tbfd->weight) { if (tbfd->bfd->bfd_up) { if (tbfd->weight > 0) vrrp->total_priority += tbfd->weight * multiplier; } else { if (tbfd->weight < 0) vrrp->total_priority += tbfd->weight * multiplier; else if (!tbfd->weight) { vrrp->num_script_if_fault++; vrrp->state = VRRP_STATE_FAULT; } } } else if (tbfd->bfd->bfd_up == tbfd->weight_reverse) { vrrp->num_script_if_fault++; vrrp->state = VRRP_STATE_FAULT; } } #endif static void initialise_interface_tracking_priorities(void) { tracking_obj_t *top; vrrp_t *vrrp; interface_t *ifp; list_head_t *ifq; ifq = get_interface_queue(); list_for_each_entry(ifp, ifq, e_list) { list_for_each_entry(top, &ifp->tracking_vrrp, e_list) { vrrp = top->obj.vrrp; if (top->weight == VRRP_NOT_TRACK_IF) continue; if (!top->weight) { if (IF_FLAGS_UP(ifp) != (top->weight_multiplier == 1)) { /* The instance is down */ log_message(LOG_INFO, "(%s): entering FAULT state (interface %s down)", vrrp->iname, ifp->ifname); vrrp->state = VRRP_STATE_FAULT; vrrp->num_script_if_fault++; } } else if (IF_FLAGS_UP(ifp)) { if (top->weight > 0) vrrp->total_priority += top->weight * top->weight_multiplier; } else { if (top->weight < 0) vrrp->total_priority += top->weight * top->weight_multiplier; } } } } static void initialise_vrrp_file_tracking_priorities(void) { tracked_file_t *tfile; tracking_obj_t *top; vrrp_t *vrrp; int status; list_for_each_entry(tfile, &vrrp_data->vrrp_track_files, e_list) { list_for_each_entry(top, &tfile->tracking_obj, e_list) { vrrp = top->obj.vrrp; status = !top->weight ? (!!tfile->last_status == (top->weight_multiplier == 1) ? -254 : 0 ) : tfile->last_status * top->weight * top->weight_multiplier; if (status <= -254) { /* The instance is down */ log_message(LOG_INFO, "(%s): entering FAULT state (tracked file %s has status %i)", vrrp->iname, tfile->fname, status); vrrp->state = VRRP_STATE_FAULT; vrrp->num_script_if_fault++; } else vrrp->total_priority += (status > 253 ? 253 : status); } } } #ifdef _WITH_CN_PROC_ static void initialise_process_tracking_priorities(void) { vrrp_tracked_process_t *tprocess; tracking_obj_t *top; vrrp_t *vrrp; list_for_each_entry(tprocess, &vrrp_data->vrrp_track_processes, e_list) { tprocess->have_quorum = (tprocess->num_cur_proc >= tprocess->quorum && tprocess->num_cur_proc <= tprocess->quorum_max); list_for_each_entry(top, &tprocess->tracking_vrrp, e_list) { vrrp = top->obj.vrrp; if (!top->weight) { if (tprocess->have_quorum != (top->weight_multiplier == 1)) { /* The instance is down */ log_message(LOG_INFO, "(%s) entering FAULT state (tracked process %s" " quorum not achieved)" , vrrp->iname, tprocess->pname); vrrp->state = VRRP_STATE_FAULT; vrrp->num_script_if_fault++; } } else if (tprocess->have_quorum) { if (top->weight > 0) vrrp->total_priority += top->weight * top->weight_multiplier; } else { if (top->weight < 0) vrrp->total_priority += top->weight * top->weight_multiplier; } } } } #endif static void initialise_vrrp_tracking_priorities(vrrp_t *vrrp) { tracked_sc_t *tsc; #ifdef _WITH_BFD_ tracked_bfd_t *tbfd; #endif /* If no src address has been specified, and the interface doesn't have * an appropriate address, put the interface into fault state */ if (vrrp->saddr.ss_family == AF_UNSPEC) { /* The instance is down */ log_message(LOG_INFO, "(%s) entering FAULT state (no IPv%d address for interface)" , vrrp->iname, vrrp->family == AF_INET ? 4 : 6); vrrp->state = VRRP_STATE_FAULT; vrrp->num_script_if_fault++; } /* Initialise the vrrp instance's tracked scripts */ list_for_each_entry(tsc, &vrrp->track_script, e_list) initialise_track_script_state(tsc, vrrp); #ifdef _WITH_BFD_ /* Initialise the vrrp instance's tracked scripts */ list_for_each_entry(tbfd, &vrrp->track_bfd, e_list) initialise_track_bfd_state(tbfd, vrrp); #endif /* If have a sync group, initialise it's tracked scripts and bfds */ if (vrrp->sync) { list_for_each_entry(tsc, &vrrp->sync->track_script, e_list) initialise_track_script_state(tsc, vrrp); } vrrp_set_effective_priority(vrrp); } void initialise_tracking_priorities(void) { vrrp_t *vrrp; /* Check for instance down due to an interface */ initialise_interface_tracking_priorities(); initialise_vrrp_file_tracking_priorities(); #ifdef _WITH_CN_PROC_ initialise_process_tracking_priorities(); #endif /* Now check for tracking scripts, files, bfd etc. */ list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list) { /* Set effective priority and fault state */ initialise_vrrp_tracking_priorities(vrrp); if (vrrp->sync) { if (vrrp->state == VRRP_STATE_FAULT) { if (vrrp->sync->state != VRRP_STATE_FAULT) { vrrp->sync->state = VRRP_STATE_FAULT; log_message(LOG_INFO, "VRRP_Group(%s): Syncing %s to FAULT state" , vrrp->sync->gname, vrrp->iname); } vrrp->sync->num_member_fault++; } if (vrrp->num_script_init) { /* Update init count on sync group if needed */ vrrp->sync->num_member_init++; if (vrrp->sync->state != VRRP_STATE_FAULT) vrrp->sync->state = VRRP_STATE_INIT; } } } } #ifdef _WITH_CN_PROC_ void process_update_track_process_status(vrrp_tracked_process_t *tprocess, bool now_up) { tracking_obj_t *top; vrrp_t *vrrp; log_message(LOG_INFO, "Quorum %s for tracked process %s", now_up ? "gained" : "lost", tprocess->pname); list_for_each_entry(top, &tprocess->tracking_vrrp, e_list) { vrrp = top->obj.vrrp; if (!top->weight) { if (now_up == (top->weight_multiplier == 1)) try_up_instance(vrrp, false); else down_instance(vrrp); } else if (vrrp->base_priority != VRRP_PRIO_OWNER) { if ((top->weight > 0) == now_up) vrrp->total_priority += top->weight * top->weight_multiplier; else vrrp->total_priority -= top->weight * top->weight_multiplier; vrrp_set_effective_priority(vrrp); } } } #endif