nagios4/base/flapping.c

796 lines
27 KiB
C

/*****************************************************************************
*
* FLAPPING.C - State flap detection and handling routines for Nagios
*
* Copyright (c) 2001-2009 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 05-15-2009
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#include "../include/nagios.h"
#include "../include/broker.h"
extern int interval_length;
extern int enable_flap_detection;
extern double low_service_flap_threshold;
extern double high_service_flap_threshold;
extern double low_host_flap_threshold;
extern double high_host_flap_threshold;
extern host *host_list;
extern service *service_list;
extern unsigned long modified_host_process_attributes;
extern unsigned long modified_service_process_attributes;
/******************************************************************/
/******************** FLAP DETECTION FUNCTIONS ********************/
/******************************************************************/
/* detects service flapping */
void check_for_service_flapping(service *svc, int update, int allow_flapstart_notification) {
int update_history = TRUE;
int is_flapping = FALSE;
register int x = 0;
register int y = 0;
int last_state_history_value = STATE_OK;
double curved_changes = 0.0;
double curved_percent_change = 0.0;
double low_threshold = 0.0;
double high_threshold = 0.0;
double low_curve_value = 0.75;
double high_curve_value = 1.25;
/* large install tweaks skips all flap detection logic - including state change calculation */
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_service_flapping()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Checking service '%s' on host '%s' for flapping...\n", svc->description, svc->host_name);
/* if this is a soft service state and not a soft recovery, don't record this in the history */
/* only hard states and soft recoveries get recorded for flap detection */
if(svc->state_type == SOFT_STATE && svc->current_state != STATE_OK)
return;
/* what threshold values should we use (global or service-specific)? */
low_threshold = (svc->low_flap_threshold <= 0.0) ? low_service_flap_threshold : svc->low_flap_threshold;
high_threshold = (svc->high_flap_threshold <= 0.0) ? high_service_flap_threshold : svc->high_flap_threshold;
update_history = update;
/* should we update state history for this state? */
if(update_history == TRUE) {
if(svc->current_state == STATE_OK && svc->flap_detection_on_ok == FALSE)
update_history = FALSE;
if(svc->current_state == STATE_WARNING && svc->flap_detection_on_warning == FALSE)
update_history = FALSE;
if(svc->current_state == STATE_UNKNOWN && svc->flap_detection_on_unknown == FALSE)
update_history = FALSE;
if(svc->current_state == STATE_CRITICAL && svc->flap_detection_on_critical == FALSE)
update_history = FALSE;
}
/* record current service state */
if(update_history == TRUE) {
/* record the current state in the state history */
svc->state_history[svc->state_history_index] = svc->current_state;
/* increment state history index to next available slot */
svc->state_history_index++;
if(svc->state_history_index >= MAX_STATE_HISTORY_ENTRIES)
svc->state_history_index = 0;
}
/* calculate overall and curved percent state changes */
for(x = 0, y = svc->state_history_index; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if(x == 0) {
last_state_history_value = svc->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
continue;
}
if(last_state_history_value != svc->state_history[y])
curved_changes += (((double)(x - 1) * (high_curve_value - low_curve_value)) / ((double)(MAX_STATE_HISTORY_ENTRIES - 2))) + low_curve_value;
last_state_history_value = svc->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
}
/* calculate overall percent change in state */
curved_percent_change = (double)(((double)curved_changes * 100.0) / (double)(MAX_STATE_HISTORY_ENTRIES - 1));
svc->percent_state_change = curved_percent_change;
log_debug_info(DEBUGL_FLAPPING, 2, "LFT=%.2f, HFT=%.2f, CPC=%.2f, PSC=%.2f%%\n", low_threshold, high_threshold, curved_percent_change, curved_percent_change);
/* don't do anything if we don't have flap detection enabled on a program-wide basis */
if(enable_flap_detection == FALSE)
return;
/* don't do anything if we don't have flap detection enabled for this service */
if(svc->flap_detection_enabled == FALSE)
return;
/* are we flapping, undecided, or what?... */
/* we're undecided, so don't change the current flap state */
if(curved_percent_change > low_threshold && curved_percent_change < high_threshold)
return;
/* we're below the lower bound, so we're not flapping */
else if(curved_percent_change <= low_threshold)
is_flapping = FALSE;
/* else we're above the upper bound, so we are flapping */
else if(curved_percent_change >= high_threshold)
is_flapping = TRUE;
log_debug_info(DEBUGL_FLAPPING, 1, "Service %s flapping (%.2f%% state change).\n", (is_flapping == TRUE) ? "is" : "is not", curved_percent_change);
/* did the service just start flapping? */
if(is_flapping == TRUE && svc->is_flapping == FALSE)
set_service_flap(svc, curved_percent_change, high_threshold, low_threshold, allow_flapstart_notification);
/* did the service just stop flapping? */
else if(is_flapping == FALSE && svc->is_flapping == TRUE)
clear_service_flap(svc, curved_percent_change, high_threshold, low_threshold);
return;
}
/* detects host flapping */
void check_for_host_flapping(host *hst, int update, int actual_check, int allow_flapstart_notification) {
int update_history = TRUE;
int is_flapping = FALSE;
register int x = 0;
register int y = 0;
int last_state_history_value = HOST_UP;
unsigned long wait_threshold = 0L;
double curved_changes = 0.0;
double curved_percent_change = 0.0;
time_t current_time = 0L;
double low_threshold = 0.0;
double high_threshold = 0.0;
double low_curve_value = 0.75;
double high_curve_value = 1.25;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_host_flapping()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Checking host '%s' for flapping...\n", hst->name);
time(&current_time);
/* period to wait for updating archived state info if we have no state change */
if(hst->total_services == 0)
wait_threshold = hst->notification_interval * interval_length;
else
wait_threshold = (hst->total_service_check_interval * interval_length) / hst->total_services;
update_history = update;
/* should we update state history for this state? */
if(update_history == TRUE) {
if(hst->current_state == HOST_UP && hst->flap_detection_on_up == FALSE)
update_history = FALSE;
if(hst->current_state == HOST_DOWN && hst->flap_detection_on_down == FALSE)
update_history = FALSE;
if(hst->current_state == HOST_UNREACHABLE && hst->flap_detection_on_unreachable == FALSE)
update_history = FALSE;
}
/* if we didn't have an actual check, only update if we've waited long enough */
if(update_history == TRUE && actual_check == FALSE && (current_time - hst->last_state_history_update) < wait_threshold) {
update_history = FALSE;
}
/* what thresholds should we use (global or host-specific)? */
low_threshold = (hst->low_flap_threshold <= 0.0) ? low_host_flap_threshold : hst->low_flap_threshold;
high_threshold = (hst->high_flap_threshold <= 0.0) ? high_host_flap_threshold : hst->high_flap_threshold;
/* record current host state */
if(update_history == TRUE) {
/* update the last record time */
hst->last_state_history_update = current_time;
/* record the current state in the state history */
hst->state_history[hst->state_history_index] = hst->current_state;
/* increment state history index to next available slot */
hst->state_history_index++;
if(hst->state_history_index >= MAX_STATE_HISTORY_ENTRIES)
hst->state_history_index = 0;
}
/* calculate overall changes in state */
for(x = 0, y = hst->state_history_index; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if(x == 0) {
last_state_history_value = hst->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
continue;
}
if(last_state_history_value != hst->state_history[y])
curved_changes += (((double)(x - 1) * (high_curve_value - low_curve_value)) / ((double)(MAX_STATE_HISTORY_ENTRIES - 2))) + low_curve_value;
last_state_history_value = hst->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
}
/* calculate overall percent change in state */
curved_percent_change = (double)(((double)curved_changes * 100.0) / (double)(MAX_STATE_HISTORY_ENTRIES - 1));
hst->percent_state_change = curved_percent_change;
log_debug_info(DEBUGL_FLAPPING, 2, "LFT=%.2f, HFT=%.2f, CPC=%.2f, PSC=%.2f%%\n", low_threshold, high_threshold, curved_percent_change, curved_percent_change);
/* don't do anything if we don't have flap detection enabled on a program-wide basis */
if(enable_flap_detection == FALSE)
return;
/* don't do anything if we don't have flap detection enabled for this host */
if(hst->flap_detection_enabled == FALSE)
return;
/* are we flapping, undecided, or what?... */
/* we're undecided, so don't change the current flap state */
if(curved_percent_change > low_threshold && curved_percent_change < high_threshold)
return;
/* we're below the lower bound, so we're not flapping */
else if(curved_percent_change <= low_threshold)
is_flapping = FALSE;
/* else we're above the upper bound, so we are flapping */
else if(curved_percent_change >= high_threshold)
is_flapping = TRUE;
log_debug_info(DEBUGL_FLAPPING, 1, "Host %s flapping (%.2f%% state change).\n", (is_flapping == TRUE) ? "is" : "is not", curved_percent_change);
/* did the host just start flapping? */
if(is_flapping == TRUE && hst->is_flapping == FALSE)
set_host_flap(hst, curved_percent_change, high_threshold, low_threshold, allow_flapstart_notification);
/* did the host just stop flapping? */
else if(is_flapping == FALSE && hst->is_flapping == TRUE)
clear_host_flap(hst, curved_percent_change, high_threshold, low_threshold);
return;
}
/******************************************************************/
/********************* FLAP HANDLING FUNCTIONS ********************/
/******************************************************************/
/* handles a service that is flapping */
void set_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) {
char *temp_buffer = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "set_service_flap()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' started flapping!\n", svc->description, svc->host_name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_RUNTIME_WARNING, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STARTED; Service appears to have started flapping (%2.1f%% change >= %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, high_threshold);
/* add a non-persistent comment to the service */
asprintf(&temp_buffer, "Notifications for this service are being suppressed because it was detected as having been flapping between different states (%2.1f%% change >= %2.1f%% threshold). When the service state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold);
add_new_service_comment(FLAPPING_COMMENT, svc->host_name, svc->description, time(NULL), "(Nagios Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(svc->flapping_comment_id));
my_free(temp_buffer);
/* set the flapping indicator */
svc->is_flapping = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL);
#endif
/* see if we should check to send a recovery notification out when flapping stops */
if(svc->current_state != STATE_OK && svc->current_notification_number > 0)
svc->check_flapping_recovery_notification = TRUE;
else
svc->check_flapping_recovery_notification = FALSE;
/* send a notification */
if(allow_flapstart_notification == TRUE)
service_notification(svc, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE);
return;
}
/* handles a service that has stopped flapping */
void clear_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_service_flap()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' stopped flapping.\n", svc->description, svc->host_name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STOPPED; Service appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, low_threshold);
/* delete the comment we added earlier */
if(svc->flapping_comment_id != 0)
delete_service_comment(svc->flapping_comment_id);
svc->flapping_comment_id = 0;
/* clear the flapping indicator */
svc->is_flapping = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL);
#endif
/* send a notification */
service_notification(svc, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK)
service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
svc->check_flapping_recovery_notification = FALSE;
return;
}
/* handles a host that is flapping */
void set_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) {
char *temp_buffer = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "set_host_flap()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' started flapping!\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_RUNTIME_WARNING, FALSE, "HOST FLAPPING ALERT: %s;STARTED; Host appears to have started flapping (%2.1f%% change > %2.1f%% threshold)\n", hst->name, percent_change, high_threshold);
/* add a non-persistent comment to the host */
asprintf(&temp_buffer, "Notifications for this host are being suppressed because it was detected as having been flapping between different states (%2.1f%% change > %2.1f%% threshold). When the host state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold);
add_new_host_comment(FLAPPING_COMMENT, hst->name, time(NULL), "(Nagios Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(hst->flapping_comment_id));
my_free(temp_buffer);
/* set the flapping indicator */
hst->is_flapping = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold, NULL);
#endif
/* see if we should check to send a recovery notification out when flapping stops */
if(hst->current_state != HOST_UP && hst->current_notification_number > 0)
hst->check_flapping_recovery_notification = TRUE;
else
hst->check_flapping_recovery_notification = FALSE;
/* send a notification */
if(allow_flapstart_notification == TRUE)
host_notification(hst, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE);
return;
}
/* handles a host that has stopped flapping */
void clear_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_host_flap()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' stopped flapping.\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Host appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", hst->name, percent_change, low_threshold);
/* delete the comment we added earlier */
if(hst->flapping_comment_id != 0)
delete_host_comment(hst->flapping_comment_id);
hst->flapping_comment_id = 0;
/* clear the flapping indicator */
hst->is_flapping = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold, NULL);
#endif
/* send a notification */
host_notification(hst, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP)
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
hst->check_flapping_recovery_notification = FALSE;
return;
}
/******************************************************************/
/***************** FLAP DETECTION STATUS FUNCTIONS ****************/
/******************************************************************/
/* enables flap detection on a program wide basis */
void enable_flap_detection_routines(void) {
host *temp_host = NULL;
service *temp_service = NULL;
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_flap_detection_routines()\n");
/* bail out if we're already set */
if(enable_flap_detection == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set flap detection flag */
enable_flap_detection = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
/* check for flapping */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next)
check_for_host_flapping(temp_host, FALSE, FALSE, TRUE);
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next)
check_for_service_flapping(temp_service, FALSE, TRUE);
return;
}
/* disables flap detection on a program wide basis */
void disable_flap_detection_routines(void) {
host *temp_host = NULL;
service *temp_service = NULL;
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_flap_detection_routines()\n");
/* bail out if we're already set */
if(enable_flap_detection == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set flap detection flag */
enable_flap_detection = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
/* handle the details... */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next)
handle_host_flap_detection_disabled(temp_host);
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next)
handle_service_flap_detection_disabled(temp_service);
return;
}
/* enables flap detection for a specific host */
void enable_host_flap_detection(host *hst) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_host_flap_detection()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Enabling flap detection for host '%s'.\n", hst->name);
/* nothing to do... */
if(hst->flap_detection_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the flap detection enabled flag */
hst->flap_detection_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* check for flapping */
check_for_host_flapping(hst, FALSE, FALSE, TRUE);
/* update host status */
update_host_status(hst, FALSE);
return;
}
/* disables flap detection for a specific host */
void disable_host_flap_detection(host *hst) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_host_flap_detection()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Disabling flap detection for host '%s'.\n", hst->name);
/* nothing to do... */
if(hst->flap_detection_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the flap detection enabled flag */
hst->flap_detection_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* handle the details... */
handle_host_flap_detection_disabled(hst);
return;
}
/* handles the details for a host when flap detection is disabled (globally or per-host) */
void handle_host_flap_detection_disabled(host *hst) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_host_flap_detection_disabled()\n");
if(hst == NULL)
return;
/* if the host was flapping, remove the flapping indicator */
if(hst->is_flapping == TRUE) {
hst->is_flapping = FALSE;
/* delete the original comment we added earlier */
if(hst->flapping_comment_id != 0)
delete_host_comment(hst->flapping_comment_id);
hst->flapping_comment_id = 0;
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;DISABLED; Flap detection has been disabled\n", hst->name);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_DISABLED, HOST_FLAPPING, hst, hst->percent_state_change, 0.0, 0.0, NULL);
#endif
/* send a notification */
host_notification(hst, NOTIFICATION_FLAPPINGDISABLED, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP)
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
hst->check_flapping_recovery_notification = FALSE;
}
/* update host status */
update_host_status(hst, FALSE);
return;
}
/* enables flap detection for a specific service */
void enable_service_flap_detection(service *svc) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_service_flap_detection()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Enabling flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name);
/* nothing to do... */
if(svc->flap_detection_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the flap detection enabled flag */
svc->flap_detection_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* check for flapping */
check_for_service_flapping(svc, FALSE, TRUE);
/* update service status */
update_service_status(svc, FALSE);
return;
}
/* disables flap detection for a specific service */
void disable_service_flap_detection(service *svc) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_service_flap_detection()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Disabling flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name);
/* nothing to do... */
if(svc->flap_detection_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the flap detection enabled flag */
svc->flap_detection_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* handle the details... */
handle_service_flap_detection_disabled(svc);
return;
}
/* handles the details for a service when flap detection is disabled (globally or per-service) */
void handle_service_flap_detection_disabled(service *svc) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_service_flap_detection_disabled()\n");
if(svc == NULL)
return;
/* if the service was flapping, remove the flapping indicator */
if(svc->is_flapping == TRUE) {
svc->is_flapping = FALSE;
/* delete the original comment we added earlier */
if(svc->flapping_comment_id != 0)
delete_service_comment(svc->flapping_comment_id);
svc->flapping_comment_id = 0;
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;DISABLED; Flap detection has been disabled\n", svc->host_name, svc->description);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_DISABLED, SERVICE_FLAPPING, svc, svc->percent_state_change, 0.0, 0.0, NULL);
#endif
/* send a notification */
service_notification(svc, NOTIFICATION_FLAPPINGDISABLED, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK)
service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
svc->check_flapping_recovery_notification = FALSE;
}
/* update service status */
update_service_status(svc, FALSE);
return;
}