/* 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 on a program wide basis */ void enable_flap_detection_routines(void) { unsigned int i; 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 (i = 0; i < num_objects.hosts; i++) check_for_host_flapping(host_ary[i], FALSE, FALSE, TRUE); for (i = 0; i < num_objects.services; i++) check_for_service_flapping(service_ary[i], FALSE, TRUE); }
/* disables flap detection on a program wide basis */ void disable_flap_detection_routines(void) { unsigned int i; unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED; /* 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; broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes); /* update program status */ update_program_status(FALSE); /* handle the details... */ for (i = 0; i < num_objects.hosts; i++) handle_host_flap_detection_disabled(host_ary[i]); for (i = 0; i < num_objects.services; i++) handle_service_flap_detection_disabled(service_ary[i]); return; }
/* this is the main event handler loop */ static void event_execution_loop(void) { while (!sigshutdown && !sigrestart) { if (sigrotate == TRUE) { sigrotate = FALSE; rotate_log_file(time(NULL)); update_program_status(FALSE); } if (event_poll()) break; } }
/* rotates the main log file */ int rotate_log_file(time_t rotation_time) { char *temp_buffer = NULL; char method_string[16] = ""; char *log_archive = NULL; struct tm *t, tm_s; int rename_result = 0; int stat_result = -1; struct stat log_file_stat; struct stat archive_stat; int archive_stat_result; if(log_rotation_method == LOG_ROTATION_NONE) { return OK; } else if(log_rotation_method == LOG_ROTATION_HOURLY) strcpy(method_string, "HOURLY"); else if(log_rotation_method == LOG_ROTATION_DAILY) strcpy(method_string, "DAILY"); else if(log_rotation_method == LOG_ROTATION_WEEKLY) strcpy(method_string, "WEEKLY"); else if(log_rotation_method == LOG_ROTATION_MONTHLY) strcpy(method_string, "MONTHLY"); else return ERROR; /* update the last log rotation time and status log */ last_log_rotation = time(NULL); update_program_status(FALSE); t = localtime_r(&rotation_time, &tm_s); stat_result = stat(log_file, &log_file_stat); close_log_file(); /* get the archived filename to use */ asprintf(&log_archive, "%s%snagios-%02d-%02d-%d-%02d.log", log_archive_path, (log_archive_path[strlen(log_archive_path) - 1] == '/') ? "" : "/", t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour); /* HACK: If the archive exists, don't overwrite it. This is a hack because the real problem is that some log rotations are executed early and as a result the next log rotatation is scheduled for the same time as the one that ran early */ archive_stat_result = stat(log_archive, &archive_stat); if((0 == archive_stat_result) || ((-1 == archive_stat_result) && (ENOENT != errno))) { return OK; } /* rotate the log file */ rename_result = my_rename(log_file, log_archive); log_fp = open_log_file(); if (log_fp == NULL) return ERROR; if(rename_result) { my_free(log_archive); return ERROR; } /* record the log rotation after it has been done... */ asprintf(&temp_buffer, "LOG ROTATION: %s\n", method_string); write_to_all_logs_with_timestamp(temp_buffer, NSLOG_PROCESS_INFO, &rotation_time); my_free(temp_buffer); /* record log file version format */ write_log_file_info(&rotation_time); if(stat_result == 0) { chmod(log_file, log_file_stat.st_mode); chown(log_file, log_file_stat.st_uid, log_file_stat.st_gid); } /* log current host and service state if activated */ if(log_current_states==TRUE) { log_host_states(CURRENT_STATES, &rotation_time); log_service_states(CURRENT_STATES, &rotation_time); } /* free memory */ my_free(log_archive); return OK; }
/* attempts to compensate for a change in the system time */ void compensate_for_system_time_change(unsigned long last_time, unsigned long current_time) { unsigned long time_difference = 0L; service *temp_service = NULL; host *temp_host = NULL; int days = 0; int hours = 0; int minutes = 0; int seconds = 0; int delta = 0; log_debug_info(DEBUGL_FUNCTIONS, 0, "compensate_for_system_time_change() start\n"); /* * if current_time < last_time, delta will be negative so we can * still use addition to all effected timestamps */ delta = current_time - last_time; /* we moved back in time... */ if (last_time > current_time) { time_difference = last_time - current_time; get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds); log_debug_info(DEBUGL_EVENTS, 0, "Detected a backwards time change of %dd %dh %dm %ds.\n", days, hours, minutes, seconds); } /* we moved into the future... */ else { time_difference = current_time - last_time; get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds); log_debug_info(DEBUGL_EVENTS, 0, "Detected a forwards time change of %dd %dh %dm %ds.\n", days, hours, minutes, seconds); } /* log the time change */ logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_WARNING, TRUE, "Warning: A system time change of %d seconds (%dd %dh %dm %ds %s in time) has been detected. Compensating...\n", delta, days, hours, minutes, seconds, (last_time > current_time) ? "backwards" : "forwards"); adjust_squeue_for_time_change(&nagios_squeue, delta); /* adjust service timestamps */ for (temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_notification); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_check); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->next_check); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_state_change); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_hard_state_change); /* recalculate next re-notification time */ temp_service->next_notification = get_next_service_notification_time(temp_service, temp_service->last_notification); /* update the status data */ update_service_status(temp_service, FALSE); } /* adjust host timestamps */ for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_notification); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_check); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->next_check); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_state_change); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_hard_state_change); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_state_history_update); /* recalculate next re-notification time */ temp_host->next_notification = get_next_host_notification_time(temp_host, temp_host->last_notification); /* update the status data */ update_host_status(temp_host, FALSE); } /* adjust program timestamps */ adjust_timestamp_for_time_change(last_time, current_time, time_difference, &program_start); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &event_start); /* update the status data */ update_program_status(FALSE); return; }
/* this is the main event handler loop */ int event_execution_loop(void) { timed_event *temp_event, *last_event = NULL; time_t last_time = 0L; time_t current_time = 0L; time_t last_status_update = 0L; int poll_time_ms; log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() start\n"); time(&last_time); while (1) { struct timeval now; const struct timeval *event_runtime; int inputs; /* super-priority (hardcoded) events come first */ /* see if we should exit or restart (a signal was encountered) */ if (sigshutdown == TRUE || sigrestart == TRUE) break; /* get the current time */ time(¤t_time); if (sigrotate == TRUE) { rotate_log_file(current_time); update_program_status(FALSE); } /* hey, wait a second... we traveled back in time! */ if (current_time < last_time) compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time); /* else if the time advanced over the specified threshold, try and compensate... */ else if ((current_time - last_time) >= time_change_threshold) compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time); /* get next scheduled event */ current_event = temp_event = (timed_event *)squeue_peek(nagios_squeue); /* if we don't have any events to handle, exit */ if (!temp_event) { log_debug_info(DEBUGL_EVENTS, 0, "There aren't any events that need to be handled! Exiting...\n"); break; } /* keep track of the last time */ last_time = current_time; /* update status information occassionally - NagVis watches the NDOUtils DB to see if Nagios is alive */ if ((unsigned long)(current_time - last_status_update) > 5) { last_status_update = current_time; update_program_status(FALSE); } event_runtime = squeue_event_runtime(temp_event->sq_event); if (temp_event != last_event) { log_debug_info(DEBUGL_EVENTS, 1, "** Event Check Loop\n"); log_debug_info(DEBUGL_EVENTS, 1, "Next Event Time: %s", ctime(&temp_event->run_time)); log_debug_info(DEBUGL_EVENTS, 1, "Current/Max Service Checks: %d/%d (%.3lf%% saturation)\n", currently_running_service_checks, max_parallel_service_checks, ((float)currently_running_service_checks / (float)max_parallel_service_checks) * 100); } last_event = temp_event; gettimeofday(&now, NULL); poll_time_ms = tv_delta_msec(&now, event_runtime); if (poll_time_ms < 0) poll_time_ms = 0; else if (poll_time_ms >= 1500) poll_time_ms = 1500; log_debug_info(DEBUGL_SCHEDULING, 2, "## Polling %dms; sockets=%d; events=%u; iobs=%p\n", poll_time_ms, iobroker_get_num_fds(nagios_iobs), squeue_size(nagios_squeue), nagios_iobs); inputs = iobroker_poll(nagios_iobs, poll_time_ms); if (inputs < 0 && errno != EINTR) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Polling for input on %p failed: %s", nagios_iobs, iobroker_strerror(inputs)); break; } log_debug_info(DEBUGL_IPC, 2, "## %d descriptors had input\n", inputs); /* * if the event we peaked was removed from the queue from * one of the I/O operations, we must take care not to * try to run at, as we're (almost) sure to access free'd * or invalid memory if we do. */ if (!current_event) { log_debug_info(DEBUGL_EVENTS, 0, "Event was cancelled by iobroker input\n"); continue; } gettimeofday(&now, NULL); if (tv_delta_msec(&now, event_runtime) >= 0) continue; /* move on if we shouldn't run this event */ if (should_run_event(temp_event) == FALSE) continue; /* handle the event */ handle_timed_event(temp_event); /* * we must remove the entry we've peeked, or * we'll keep getting the same one over and over. * This also maintains sync with broker modules. */ remove_event(nagios_squeue, temp_event); /* reschedule the event if necessary */ if (temp_event->recurring == TRUE) reschedule_event(nagios_squeue, temp_event); /* else free memory associated with the event */ else my_free(temp_event); } log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() end\n"); return OK; }
/* rotates the main log file */ int rotate_log_file(time_t rotation_time){ char *temp_buffer=NULL; char method_string[16]=""; char *log_archive=NULL; struct tm *t; int rename_result=0; int stat_result=-1; struct stat log_file_stat; if(log_rotation_method==LOG_ROTATION_NONE){ return OK; } else if(log_rotation_method==LOG_ROTATION_HOURLY) strcpy(method_string,"HOURLY"); else if(log_rotation_method==LOG_ROTATION_DAILY) strcpy(method_string,"DAILY"); else if(log_rotation_method==LOG_ROTATION_WEEKLY) strcpy(method_string,"WEEKLY"); else if(log_rotation_method==LOG_ROTATION_MONTHLY) strcpy(method_string,"MONTHLY"); else return ERROR; /* update the last log rotation time and status log */ last_log_rotation=time(NULL); update_program_status(FALSE); t=localtime(&rotation_time); stat_result = stat(log_file, &log_file_stat); /* get the archived filename to use */ asprintf(&log_archive,"%s%snagios-%02d-%02d-%d-%02d.log",log_archive_path,(log_archive_path[strlen(log_archive_path)-1]=='/')?"":"/",t->tm_mon+1,t->tm_mday,t->tm_year+1900,t->tm_hour); /* rotate the log file */ rename_result=my_rename(log_file,log_archive); if(rename_result){ my_free(log_archive); return ERROR; } #ifdef USE_EVENT_BROKER /* REMOVED - log rotation events are already handled by NEBTYPE_TIMEDEVENT_EXECUTE... */ /* send data to the event broker */ /* broker_log_data(NEBTYPE_LOG_ROTATION,NEBFLAG_NONE,NEBATTR_NONE,log_archive,log_rotation_method,0,NULL); */ #endif /* record the log rotation after it has been done... */ asprintf(&temp_buffer,"LOG ROTATION: %s\n",method_string); write_to_all_logs_with_timestamp(temp_buffer,NSLOG_PROCESS_INFO,&rotation_time); my_free(temp_buffer); /* record log file version format */ write_log_file_info(&rotation_time); if(stat_result==0){ chmod(log_file, log_file_stat.st_mode); chown(log_file, log_file_stat.st_uid, log_file_stat.st_gid); } /* log current host and service state */ log_host_states(CURRENT_STATES,&rotation_time); log_service_states(CURRENT_STATES,&rotation_time); /* free memory */ my_free(log_archive); return OK; }
/* rotates the main log file */ int rotate_log_file(time_t rotation_time) { char *temp_buffer = NULL; char method_string[16] = ""; char *log_archive = NULL; struct tm *t, tm_s; int rename_result = 0; int stat_result = -1; struct stat log_file_stat; if (log_rotation_method == LOG_ROTATION_NONE) { return OK; } else if (log_rotation_method == LOG_ROTATION_HOURLY) strcpy(method_string, "HOURLY"); else if (log_rotation_method == LOG_ROTATION_DAILY) strcpy(method_string, "DAILY"); else if (log_rotation_method == LOG_ROTATION_WEEKLY) strcpy(method_string, "WEEKLY"); else if (log_rotation_method == LOG_ROTATION_MONTHLY) strcpy(method_string, "MONTHLY"); else return ERROR; /* update the last log rotation time and status log */ last_log_rotation = time(NULL); update_program_status(FALSE); t = localtime_r(&rotation_time, &tm_s); stat_result = stat(log_file, &log_file_stat); close_log_file(); /* get the archived filename to use */ dummy = asprintf(&log_archive, "%s%sicinga-%02d-%02d-%d-%02d.log", log_archive_path, (log_archive_path[strlen(log_archive_path)-1] == '/') ? "" : "/", t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour); /* rotate the log file */ rename_result = my_rename(log_file, log_archive); log_fp = open_log_file(); if (rename_result) { my_free(log_archive); return ERROR; } /* record the log rotation after it has been done... */ dummy = asprintf(&temp_buffer, "LOG ROTATION: %s\n", method_string); write_to_all_logs_with_timestamp(temp_buffer, NSLOG_PROCESS_INFO, &rotation_time); my_free(temp_buffer); /* record log file version format */ write_log_file_info(&rotation_time); if (stat_result == 0) { chmod(log_file, log_file_stat.st_mode); dummy = chown(log_file, log_file_stat.st_uid, log_file_stat.st_gid); } /* log current host and service state if activated*/ if (log_current_states == TRUE) { log_host_states(CURRENT_STATES, &rotation_time); log_service_states(CURRENT_STATES, &rotation_time); } /* free memory */ my_free(log_archive); return OK; }