From 188655c32dc787679a7bf045f111319cc0a518cb Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 22:09:32 +0200 Subject: [PATCH 01/18] Add support for expiring acknowledgements #302 Parts of this code were based on work done in Icinga v1 by Ricardo Bartels for https://github.com/Icinga/icinga-core/issues/369. Closes #302. Signed-off-by: Roel van Meer From e60e53bf4cc277474744d4d28ce381eae7d31309 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 14:59:22 +0200 Subject: [PATCH 02/18] Add command definitions for expiring acknowledgements Signed-off-by: Roel van Meer --- src/naemon/common.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/naemon/common.h b/src/naemon/common.h index a96c5eb95..44c6038e2 100644 --- a/src/naemon/common.h +++ b/src/naemon/common.h @@ -322,6 +322,9 @@ NAGIOS_END_DECL #define CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME 171 #define CMD_DEL_DOWNTIME_BY_START_TIME_COMMENT 172 +#define CMD_ACKNOWLEDGE_HOST_PROBLEM_EXPIRE 173 +#define CMD_ACKNOWLEDGE_SVC_PROBLEM_EXPIRE 174 + /* custom command introduced in Nagios 3.x */ #define CMD_CUSTOM_COMMAND 999 From b890f513d9eb76c4f9e47e6303e51c6db0ae946a Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:01:34 +0200 Subject: [PATCH 03/18] Add end_time argument to acknowledge_*_problem functions Signed-off-by: Roel van Meer --- src/naemon/commands.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index 9e0499ffb..a9e1cc671 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -73,8 +73,8 @@ static void disable_host_notifications(host *); /* disables host notifications static void enable_and_propagate_notifications(host *hst, struct propagation_parameters *params); static void disable_and_propagate_notifications(host *hst, struct propagation_parameters *params); static void schedule_and_propagate_downtime(host *temp_host, struct downtime_parameters *params); -static void acknowledge_host_problem(host *, char *, char *, int, int, int); /* acknowledges a host problem */ -static void acknowledge_service_problem(service *, char *, char *, int, int, int); /* acknowledges a service problem */ +static void acknowledge_host_problem(host *, char *, char *, int, int, int, time_t); /* acknowledges a host problem */ +static void acknowledge_service_problem(service *, char *, char *, int, int, int, time_t); /* acknowledges a service problem */ static void remove_host_acknowledgement(host *); /* removes a host acknowledgement */ static void remove_service_acknowledgement(service *); /* removes a service acknowledgement */ static void start_executing_service_checks(void); /* starts executing service checks */ @@ -1881,7 +1881,7 @@ static int host_command_handler(const struct external_command *ext_command, time return OK; case CMD_ACKNOWLEDGE_HOST_PROBLEM: acknowledge_host_problem(target_host, GV("author"), GV("comment"), GV_INT("sticky"), - GV_BOOL("notify"), GV_BOOL("persistent")); + GV_BOOL("notify"), GV_BOOL("persistent"), (time_t)0); return OK; case CMD_ENABLE_HOST_EVENT_HANDLER: enable_host_event_handler(target_host); @@ -2257,7 +2257,8 @@ static int service_command_handler(const struct external_command *ext_command, t case CMD_PROCESS_SERVICE_CHECK_RESULT: return process_passive_service_check(entry_time /*entry time as check time*/, target_service->host_name, target_service->description, GV_INT("status_code"), GV("plugin_output")); case CMD_ACKNOWLEDGE_SVC_PROBLEM: - acknowledge_service_problem(target_service, GV("author"), GV("comment"), GV_INT("sticky"), GV_BOOL("notify"), GV_BOOL("persistent")); + acknowledge_service_problem(target_service, GV("author"), GV("comment"), GV_INT("sticky"), + GV_BOOL("notify"), GV_BOOL("persistent"), (time_t)0); return OK; case CMD_ENABLE_PASSIVE_SVC_CHECKS: enable_passive_service_checks(target_service); @@ -3958,7 +3959,7 @@ static void schedule_and_propagate_downtime(host *temp_host, struct downtime_par /* acknowledges a host problem */ -static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data, int type, int notify, int persistent) +static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data, int type, int notify, int persistent, time_t end_time) { time_t current_time = 0L; @@ -3990,7 +3991,7 @@ static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data /* acknowledges a service problem */ -static void acknowledge_service_problem(service *svc, char *ack_author, char *ack_data, int type, int notify, int persistent) +static void acknowledge_service_problem(service *svc, char *ack_author, char *ack_data, int type, int notify, int persistent, time_t end_time) { time_t current_time = 0L; From efbcba115173b3f8c017b8d3f5a93ec4b3afa319 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:12:59 +0200 Subject: [PATCH 04/18] Register the new commands Signed-off-by: Roel van Meer --- src/naemon/commands.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index a9e1cc671..6d4c5f2c2 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -1883,6 +1883,10 @@ static int host_command_handler(const struct external_command *ext_command, time acknowledge_host_problem(target_host, GV("author"), GV("comment"), GV_INT("sticky"), GV_BOOL("notify"), GV_BOOL("persistent"), (time_t)0); return OK; + case CMD_ACKNOWLEDGE_HOST_PROBLEM_EXPIRE: + acknowledge_host_problem(target_host, GV("author"), GV("comment"), GV_INT("sticky"), + GV_BOOL("notify"), GV_BOOL("persistent"), GV_TIMESTAMP("end_time")); + return OK; case CMD_ENABLE_HOST_EVENT_HANDLER: enable_host_event_handler(target_host); return OK; @@ -2260,6 +2264,10 @@ static int service_command_handler(const struct external_command *ext_command, t acknowledge_service_problem(target_service, GV("author"), GV("comment"), GV_INT("sticky"), GV_BOOL("notify"), GV_BOOL("persistent"), (time_t)0); return OK; + case CMD_ACKNOWLEDGE_SVC_PROBLEM_EXPIRE: + acknowledge_service_problem(target_service, GV("author"), GV("comment"), GV_INT("sticky"), + GV_BOOL("notify"), GV_BOOL("persistent"), GV_TIMESTAMP("end_time")); + return OK; case CMD_ENABLE_PASSIVE_SVC_CHECKS: enable_passive_service_checks(target_service); return OK; @@ -2729,10 +2737,18 @@ void register_core_commands(void) "Allows you to acknowledge the current problem for the specified host. By acknowledging the current problem, future notifications (for the same host state) are disabled. If the 'sticky' option is set to one (1), the acknowledgement will remain until the host returns to an UP state. Otherwise the acknowledgement will automatically be removed when the host changes state. If the 'notify' option is set to one (1), a notification will be sent out to contacts indicating that the current host problem has been acknowledged. If the 'persistent' option is set to one (1), the comment associated with the acknowledgement will remain once the acknowledgement is removed. If not, the comment will be deleted when the acknowledgement is removed.", "host=host_name;int=sticky;bool=notify;bool=persistent;str=author;str=comment"); command_register(core_command, CMD_ACKNOWLEDGE_HOST_PROBLEM); + core_command = command_create("ACKNOWLEDGE_HOST_PROBLEM_EXPIRE", host_command_handler, + "Allows you to acknowledge the current problem for the specified host for a limitied time. By acknowledging the current problem, future notifications (for the same host state) are disabled. The 'end_time' option determines the time after which the acknowledgement is cleared automatically. If the 'sticky' option is set to one (1), the acknowledgement will remain until the host returns to an UP state. Otherwise the acknowledgement will automatically be removed when the host changes state. If the 'notify' option is set to one (1), a notification will be sent out to contacts indicating that the current host problem has been acknowledged. If the 'persistent' option is set to one (1), the comment associated with the acknowledgement will remain once the acknowledgement is removed. If not, the comment will be deleted when the acknowledgement is removed.", "host=host_name;int=sticky;bool=notify;bool=persistent;timestamp=end_time;str=author;str=comment"); + command_register(core_command, CMD_ACKNOWLEDGE_HOST_PROBLEM_EXPIRE); + core_command = command_create("ACKNOWLEDGE_SVC_PROBLEM", service_command_handler, "Allows you to acknowledge the current problem for the specified service. By acknowledging the current problem, future notifications (for the same servicestate) are disabled. If the 'sticky' option is set to one (1), the acknowledgement will remain until the service returns to an OK state. Otherwise the acknowledgement will automatically be removed when the service changes state. If the 'notify' option is set to one (1), a notification will be sent out to contacts indicating that the current service problem has been acknowledged. If the 'persistent' option is set to one (1), the comment associated with the acknowledgement will remain once the acknowledgement is removed. If not, the comment will be deleted when the acknowledgement is removed.", "service=service;int=sticky;bool=notify;bool=persistent;str=author;str=comment"); command_register(core_command, CMD_ACKNOWLEDGE_SVC_PROBLEM); + core_command = command_create("ACKNOWLEDGE_SVC_PROBLEM_EXPIRE", service_command_handler, + "Allows you to acknowledge the current problem for the specified service. By acknowledging the current problem, future notifications (for the same servicestate) are disabled. The 'end_time' option determines the time after which the acknowledgement is cleared automatically. If the 'sticky' option is set to one (1), the acknowledgement will remain until the service returns to an OK state. Otherwise the acknowledgement will automatically be removed when the service changes state. If the 'notify' option is set to one (1), a notification will be sent out to contacts indicating that the current service problem has been acknowledged. If the 'persistent' option is set to one (1), the comment associated with the acknowledgement will remain once the acknowledgement is removed. If not, the comment will be deleted when the acknowledgement is removed.", "service=service;int=sticky;bool=notify;bool=persistent;timestamp=end_time;str=author;str=comment"); + command_register(core_command, CMD_ACKNOWLEDGE_SVC_PROBLEM_EXPIRE); + core_command = command_create("START_EXECUTING_SVC_CHECKS", global_command_handler, "Enables active checks of services on a program-wide basis.", NULL); command_register(core_command, CMD_START_EXECUTING_SVC_CHECKS); From c0d7d56262a4b70f62a3e389f396d28186dd8b8d Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:13:19 +0200 Subject: [PATCH 05/18] Support end_time in the broker Signed-off-by: Roel van Meer --- src/naemon/broker.c | 3 ++- src/naemon/broker.h | 2 +- src/naemon/commands.c | 4 ++-- src/naemon/nebstructs.h | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/naemon/broker.c b/src/naemon/broker.c index 04b124f73..dabcfdf7b 100644 --- a/src/naemon/broker.c +++ b/src/naemon/broker.c @@ -847,7 +847,7 @@ void broker_retention_data(int type, int flags, int attr) /* send acknowledgement data to broker */ -void broker_acknowledgement_data(int type, int flags, int attr, int acknowledgement_type, void *data, char *ack_author, char *ack_data, int subtype, int notify_contacts, int persistent_comment) +void broker_acknowledgement_data(int type, int flags, int attr, int acknowledgement_type, void *data, char *ack_author, char *ack_data, int subtype, int notify_contacts, int persistent_comment, time_t end_time) { nebstruct_acknowledgement_data ds; host *temp_host = NULL; @@ -880,6 +880,7 @@ void broker_acknowledgement_data(int type, int flags, int attr, int acknowledgem ds.is_sticky = (subtype == ACKNOWLEDGEMENT_STICKY) ? TRUE : FALSE; ds.notify_contacts = notify_contacts; ds.persistent_comment = persistent_comment; + ds.end_time = end_time; /* make callbacks */ neb_make_callbacks(NEBCALLBACK_ACKNOWLEDGEMENT_DATA, (void *)&ds); diff --git a/src/naemon/broker.h b/src/naemon/broker.h index 47cc7ace0..4e7b0b775 100644 --- a/src/naemon/broker.h +++ b/src/naemon/broker.h @@ -191,7 +191,7 @@ void broker_adaptive_contact_data(int, int, int, contact *, int, unsigned long, int broker_external_command(int, int, int, int, time_t, char *, char *); void broker_aggregated_status_data(int, int, int); void broker_retention_data(int, int, int); -void broker_acknowledgement_data(int, int, int, int, void *, char *, char *, int, int, int); +void broker_acknowledgement_data(int, int, int, int, void *, char *, char *, int, int, int, time_t); void broker_statechange_data(int, int, int, int, void *, int, int, int, int); int broker_vault_macro(char *, char **, int *, nagios_macros *); diff --git a/src/naemon/commands.c b/src/naemon/commands.c index 6d4c5f2c2..1ec822500 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -3983,7 +3983,7 @@ static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data if (hst->current_state == STATE_UP) return; - broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_ACKNOWLEDGEMENT, (void *)hst, ack_author, ack_data, type, notify, persistent); + broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_ACKNOWLEDGEMENT, (void *)hst, ack_author, ack_data, type, notify, persistent, end_time); /* send out an acknowledgement notification */ if (notify == TRUE) @@ -4015,7 +4015,7 @@ static void acknowledge_service_problem(service *svc, char *ack_author, char *ac if (svc->current_state == STATE_OK) return; - broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_ACKNOWLEDGEMENT, (void *)svc, ack_author, ack_data, type, notify, persistent); + broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_ACKNOWLEDGEMENT, (void *)svc, ack_author, ack_data, type, notify, persistent, end_time); /* send out an acknowledgement notification */ if (notify == TRUE) diff --git a/src/naemon/nebstructs.h b/src/naemon/nebstructs.h index 68f701e07..76c72cc33 100644 --- a/src/naemon/nebstructs.h +++ b/src/naemon/nebstructs.h @@ -470,6 +470,7 @@ typedef struct nebstruct_acknowledgement_struct { int persistent_comment; int notify_contacts; void *object_ptr; + time_t end_time; } nebstruct_acknowledgement_data; From 7d6af7de58231855d1ccac9a4b762309734eb4ab Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:28:21 +0200 Subject: [PATCH 06/18] Set acknowledgement_end_time in host and service structs Signed-off-by: Roel van Meer --- src/naemon/commands.c | 14 ++++++++++++-- src/naemon/objects_host.h | 1 + src/naemon/objects_service.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index 1ec822500..bdfe3cf97 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -3995,11 +3995,16 @@ static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data /* set the acknowledgement type */ hst->acknowledgement_type = type ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL; + /* set the acknowledgement expire time */ + time(¤t_time); + if (end_time <= current_time) + end_time = (time_t)0; + hst->acknowledgement_end_time = end_time; + /* update the status log with the host info */ update_host_status(hst, FALSE); /* add a comment for the acknowledgement */ - time(¤t_time); add_new_host_comment(ACKNOWLEDGEMENT_COMMENT, hst->name, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL); return; @@ -4027,11 +4032,16 @@ static void acknowledge_service_problem(service *svc, char *ack_author, char *ac /* set the acknowledgement type */ svc->acknowledgement_type = type ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL; + /* set the acknowledgement expire time */ + time(¤t_time); + if (end_time <= current_time) + end_time = (time_t)0; + svc->acknowledgement_end_time = end_time; + /* update the status log with the service info */ update_service_status(svc, FALSE); /* add a comment for the acknowledgement */ - time(¤t_time); add_new_service_comment(ACKNOWLEDGEMENT_COMMENT, svc->host_name, svc->description, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL); return; diff --git a/src/naemon/objects_host.h b/src/naemon/objects_host.h index 780a77f7a..3609deb4f 100644 --- a/src/naemon/objects_host.h +++ b/src/naemon/objects_host.h @@ -77,6 +77,7 @@ struct host { customvariablesmember *custom_variables; int problem_has_been_acknowledged; int acknowledgement_type; + time_t acknowledgement_end_time; int check_type; int current_state; int last_state; diff --git a/src/naemon/objects_service.h b/src/naemon/objects_service.h index d8358ee02..4db852172 100644 --- a/src/naemon/objects_service.h +++ b/src/naemon/objects_service.h @@ -68,6 +68,7 @@ struct service { struct customvariablesmember *custom_variables; int problem_has_been_acknowledged; int acknowledgement_type; + time_t acknowledgement_end_time; int host_problem_at_last_check; int check_type; int current_state; From 079b85b5b5dd666f1fd31d130c399fd82ec3fd32 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:31:19 +0200 Subject: [PATCH 07/18] Ensure host and service comments know about expiry Signed-off-by: Roel van Meer --- src/naemon/commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index bdfe3cf97..f36225f0f 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -4005,7 +4005,7 @@ static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data update_host_status(hst, FALSE); /* add a comment for the acknowledgement */ - add_new_host_comment(ACKNOWLEDGEMENT_COMMENT, hst->name, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL); + add_new_host_comment(ACKNOWLEDGEMENT_COMMENT, hst->name, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, (end_time != 0) ? TRUE : FALSE, end_time, NULL); return; } @@ -4042,7 +4042,7 @@ static void acknowledge_service_problem(service *svc, char *ack_author, char *ac update_service_status(svc, FALSE); /* add a comment for the acknowledgement */ - add_new_service_comment(ACKNOWLEDGEMENT_COMMENT, svc->host_name, svc->description, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL); + add_new_service_comment(ACKNOWLEDGEMENT_COMMENT, svc->host_name, svc->description, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, (end_time != 0) ? TRUE : FALSE, end_time, NULL); return; } From ebfe3a6720a3e019ba1c3a0c305b422f8b678a6a Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:37:14 +0200 Subject: [PATCH 08/18] Ensure acknowledgement_end_time is set (or cleared) Signed-off-by: Roel van Meer --- src/naemon/checks_host.c | 2 ++ src/naemon/checks_service.c | 4 ++++ src/naemon/commands.c | 2 ++ src/naemon/objects_host.c | 1 + src/naemon/objects_service.c | 1 + 5 files changed, 10 insertions(+) diff --git a/src/naemon/checks_host.c b/src/naemon/checks_host.c index 35f0fdb39..aa7f41dcd 100644 --- a/src/naemon/checks_host.c +++ b/src/naemon/checks_host.c @@ -969,6 +969,7 @@ static int handle_host_state(host *hst, int *alert_recorded) hst->problem_has_been_acknowledged = FALSE; hst->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + hst->acknowledgement_end_time = (time_t)0; /* remove any non-persistant comments associated with the ack */ delete_host_acknowledgement_comments(hst); @@ -976,6 +977,7 @@ static int handle_host_state(host *hst, int *alert_recorded) hst->problem_has_been_acknowledged = FALSE; hst->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + hst->acknowledgement_end_time = (time_t)0; /* remove any non-persistant comments associated with the ack */ delete_host_acknowledgement_comments(hst); diff --git a/src/naemon/checks_service.c b/src/naemon/checks_service.c index 1031e67a0..1f30b5d9a 100644 --- a/src/naemon/checks_service.c +++ b/src/naemon/checks_service.c @@ -636,6 +636,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue temp_service->problem_has_been_acknowledged = FALSE; temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + temp_service->acknowledgement_end_time = (time_t)0; /* remove any non-persistant comments associated with the ack */ delete_service_acknowledgement_comments(temp_service); @@ -643,6 +644,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue temp_service->problem_has_been_acknowledged = FALSE; temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + temp_service->acknowledgement_end_time = (time_t)0; /* remove any non-persistant comments associated with the ack */ delete_service_acknowledgement_comments(temp_service); @@ -705,6 +707,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* reset the acknowledgement flag (this should already have been done, but just in case...) */ temp_service->problem_has_been_acknowledged = FALSE; temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + temp_service->acknowledgement_end_time = (time_t)0; /* verify the route to the host and send out host recovery notifications */ if (temp_host->current_state != STATE_UP) { @@ -788,6 +791,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue temp_service->current_notification_number = 0; temp_service->problem_has_been_acknowledged = FALSE; temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + temp_service->acknowledgement_end_time = (time_t)0; temp_service->notified_on = 0; } diff --git a/src/naemon/commands.c b/src/naemon/commands.c index f36225f0f..2d7ee2e7f 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -4054,6 +4054,7 @@ static void remove_host_acknowledgement(host *hst) /* set the acknowledgement flag */ hst->problem_has_been_acknowledged = FALSE; + hst->acknowledgement_end_time = (time_t)0; /* update the status log with the host info */ update_host_status(hst, FALSE); @@ -4071,6 +4072,7 @@ static void remove_service_acknowledgement(service *svc) /* set the acknowledgement flag */ svc->problem_has_been_acknowledged = FALSE; + svc->acknowledgement_end_time = (time_t)0; /* update the status log with the service info */ update_service_status(svc, FALSE); diff --git a/src/naemon/objects_host.c b/src/naemon/objects_host.c index 8b0d8251d..ca18d5670 100644 --- a/src/naemon/objects_host.c +++ b/src/naemon/objects_host.c @@ -74,6 +74,7 @@ host *create_host(const char *name) new_host->check_type = CHECK_TYPE_ACTIVE; new_host->state_type = HARD_STATE; new_host->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + new_host->acknowledgement_end_time = (time_t)0; new_host->check_options = CHECK_OPTION_NONE; diff --git a/src/naemon/objects_service.c b/src/naemon/objects_service.c index 5d719baca..758c2d615 100644 --- a/src/naemon/objects_service.c +++ b/src/naemon/objects_service.c @@ -80,6 +80,7 @@ service *create_service(host *hst, const char *description) new_service->description = nm_strdup(description); new_service->display_name = new_service->description; new_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + new_service->acknowledgement_end_time = (time_t)0; new_service->check_type = CHECK_TYPE_ACTIVE; new_service->state_type = HARD_STATE; new_service->check_options = CHECK_OPTION_NONE; From c32e9a9f9c536b818010b7d5bea291475020e492 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:42:44 +0200 Subject: [PATCH 09/18] Read and write acknowledgement_end_time in retention data Signed-off-by: Roel van Meer --- src/naemon/xrddefault.c | 6 ++++++ src/naemon/xsddefault.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/naemon/xrddefault.c b/src/naemon/xrddefault.c index 2dd3e17c9..b312682af 100644 --- a/src/naemon/xrddefault.c +++ b/src/naemon/xrddefault.c @@ -203,6 +203,7 @@ int xrddefault_save_state_information(void) } fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged); fprintf(fp, "acknowledgement_type=%d\n", temp_host->acknowledgement_type); + fprintf(fp, "acknowledgement_end_time=%lu\n", temp_host->acknowledgement_end_time); if (conf_host && conf_host->checks_enabled != temp_host->checks_enabled) { fprintf(fp, "config:active_checks_enabled=%d\n", conf_host->checks_enabled); fprintf(fp, "active_checks_enabled=%d\n", temp_host->checks_enabled); @@ -311,6 +312,7 @@ int xrddefault_save_state_information(void) } fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged); fprintf(fp, "acknowledgement_type=%d\n", temp_service->acknowledgement_type); + fprintf(fp, "acknowledgement_end_time=%lu\n", temp_service->acknowledgement_end_time); if (conf_svc && conf_svc->flap_detection_enabled != temp_service->flap_detection_enabled) { fprintf(fp, "config:flap_detection_enabled=%d\n", conf_svc->flap_detection_enabled); fprintf(fp, "flap_detection_enabled=%d\n", temp_service->flap_detection_enabled); @@ -1092,6 +1094,8 @@ int xrddefault_read_state_information(void) temp_host->problem_has_been_acknowledged = (atoi(val) > 0) ? TRUE : FALSE; } else if (!strcmp(var, "acknowledgement_type")) { temp_host->acknowledgement_type = atoi(val); + } else if (!strcmp(var, "acknowledgement_end_time")) { + temp_host->acknowledgement_end_time = strtoul(val, NULL, 10); } else if (!strcmp(var, "notifications_enabled")) { RETAIN_BOOL(host, temp_host, notifications_enabled, MODATTR_NOTIFICATIONS_ENABLED); } else if (!strcmp(var, "active_checks_enabled")) { @@ -1355,6 +1359,8 @@ int xrddefault_read_state_information(void) temp_service->problem_has_been_acknowledged = (atoi(val) > 0) ? TRUE : FALSE; } else if (!strcmp(var, "acknowledgement_type")) { temp_service->acknowledgement_type = atoi(val); + } else if (!strcmp(var, "acknowledgement_end_time")) { + temp_service->acknowledgement_end_time = strtoul(val, NULL, 10); } else if (!strcmp(var, "notifications_enabled")) { RETAIN_BOOL(service, temp_service, notifications_enabled, MODATTR_NOTIFICATIONS_ENABLED); } else if (!strcmp(var, "active_checks_enabled")) { diff --git a/src/naemon/xsddefault.c b/src/naemon/xsddefault.c index c4ee72dbf..35e8b9978 100644 --- a/src/naemon/xsddefault.c +++ b/src/naemon/xsddefault.c @@ -222,6 +222,7 @@ int xsddefault_save_status_data(void) fprintf(fp, "\tnotifications_enabled=%d\n", temp_host->notifications_enabled); fprintf(fp, "\tproblem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged); fprintf(fp, "\tacknowledgement_type=%d\n", temp_host->acknowledgement_type); + fprintf(fp, "\tacknowledgement_end_time=%lu\n", temp_host->acknowledgement_end_time); fprintf(fp, "\tactive_checks_enabled=%d\n", temp_host->checks_enabled); fprintf(fp, "\tpassive_checks_enabled=%d\n", temp_host->accept_passive_checks); fprintf(fp, "\tevent_handler_enabled=%d\n", temp_host->event_handler_enabled); @@ -292,6 +293,7 @@ int xsddefault_save_status_data(void) fprintf(fp, "\tevent_handler_enabled=%d\n", temp_service->event_handler_enabled); fprintf(fp, "\tproblem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged); fprintf(fp, "\tacknowledgement_type=%d\n", temp_service->acknowledgement_type); + fprintf(fp, "\tacknowledgement_end_time=%lu\n", temp_service->acknowledgement_end_time); fprintf(fp, "\tflap_detection_enabled=%d\n", temp_service->flap_detection_enabled); fprintf(fp, "\tprocess_performance_data=%d\n", temp_service->process_performance_data); fprintf(fp, "\tobsess=%d\n", temp_service->obsess); From 8b18dc5f2d0b1779fc34fc5156f2cf4ae1c012e6 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 16:04:44 +0200 Subject: [PATCH 10/18] Create and handle host ack expire event Signed-off-by: Roel van Meer --- src/naemon/commands.c | 83 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index 2d7ee2e7f..35b8f9974 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -77,6 +77,8 @@ static void acknowledge_host_problem(host *, char *, char *, int, int, int, time static void acknowledge_service_problem(service *, char *, char *, int, int, int, time_t); /* acknowledges a service problem */ static void remove_host_acknowledgement(host *); /* removes a host acknowledgement */ static void remove_service_acknowledgement(service *); /* removes a service acknowledgement */ +static void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ +static void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ static void start_executing_service_checks(void); /* starts executing service checks */ static void stop_executing_service_checks(void); /* stops executing service checks */ static void start_accepting_passive_service_checks(void); /* starts accepting passive service check results */ @@ -3983,6 +3985,14 @@ static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data if (hst->current_state == STATE_UP) return; + /* get the time */ + time(¤t_time); + + /* if the end time is set but in the past, it has already expired + and we don't need to do anything */ + if (end_time > 0 && end_time <= current_time) + return; + broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_ACKNOWLEDGEMENT, (void *)hst, ack_author, ack_data, type, notify, persistent, end_time); /* send out an acknowledgement notification */ @@ -3995,10 +4005,11 @@ static void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data /* set the acknowledgement type */ hst->acknowledgement_type = type ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL; + /* if the ack expires in the future, schedule an event to clear it */ + if (end_time > current_time) + schedule_event(end_time - current_time, handle_host_acknowledgement_expire_event, (void *)hst); + /* set the acknowledgement expire time */ - time(¤t_time); - if (end_time <= current_time) - end_time = (time_t)0; hst->acknowledgement_end_time = end_time; /* update the status log with the host info */ @@ -4020,6 +4031,14 @@ static void acknowledge_service_problem(service *svc, char *ack_author, char *ac if (svc->current_state == STATE_OK) return; + /* get the time */ + time(¤t_time); + + /* if the end time is set but in the past, it has already expired + and we don't need to do anything */ + if (end_time > 0 && end_time <= current_time) + return; + broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_ACKNOWLEDGEMENT, (void *)svc, ack_author, ack_data, type, notify, persistent, end_time); /* send out an acknowledgement notification */ @@ -4032,10 +4051,11 @@ static void acknowledge_service_problem(service *svc, char *ack_author, char *ac /* set the acknowledgement type */ svc->acknowledgement_type = type ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL; + /* if the ack expires in the future, schedule an event to clear it */ + if (end_time > current_time) + schedule_event(end_time - current_time, handle_service_acknowledgement_expire_event, (void *)svc); + /* set the acknowledgement expire time */ - time(¤t_time); - if (end_time <= current_time) - end_time = (time_t)0; svc->acknowledgement_end_time = end_time; /* update the status log with the service info */ @@ -4083,6 +4103,57 @@ static void remove_service_acknowledgement(service *svc) return; } +/* removes an expired host acknowledgement */ +static void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop) +{ + time_t current_time = 0L; + + log_debug_info(DEBUGL_EVENTS, 2, "Running event handler for host acknowledgement expiry\n"); + if (evprop->user_data) { + if (evprop->execution_type == EVENT_EXEC_NORMAL) { + /* get the host */ + host *hst = (host *)evprop->user_data; + + /* get the time */ + time(¤t_time); + + /* if the host ack has an end time now or in the + past, remove the ack */ + if (hst->problem_has_been_acknowledged && + hst->acknowledgement_end_time > 0 && + hst->acknowledgement_end_time <= current_time) { + log_debug_info(DEBUGL_EVENTS, 2, "Removing host acknowledgement for host '%s'\n", hst->name); + remove_host_acknowledgement(hst); + } + } + } +} + +/* removes an expired service acknowledgement */ +static void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop) +{ + time_t current_time = 0L; + + log_debug_info(DEBUGL_EVENTS, 2, "Running event handler for service acknowledgement expiry\n"); + if (evprop->user_data) { + if (evprop->execution_type == EVENT_EXEC_NORMAL) { + /* get the service */ + service *svc = (service *)evprop->user_data; + + /* get the time */ + time(¤t_time); + + /* if the service ack has an end time now or in the + past, remove the ack */ + if (svc->problem_has_been_acknowledged && + svc->acknowledgement_end_time > 0 && + svc->acknowledgement_end_time <= current_time) { + log_debug_info(DEBUGL_EVENTS, 2, "Removing service acknowledgement for service '%s' on host '%s'\n", svc->description, svc->host_name); + remove_service_acknowledgement(svc); + } + } + } +} /* starts executing service checks */ static void start_executing_service_checks(void) From 72b07a8542bb73e240f74e0657db3d234ec1da06 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 10 Aug 2022 22:28:22 +0200 Subject: [PATCH 11/18] Reschedule events when starting If neamon starts and the retention data contains expiring acks that still need to happen, ensure the expire events are properly scheduled. Signed-off-by: Roel van Meer --- src/naemon/commands.c | 8 ++++---- src/naemon/xrddefault.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index 35b8f9974..7d1846783 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -77,8 +77,8 @@ static void acknowledge_host_problem(host *, char *, char *, int, int, int, time static void acknowledge_service_problem(service *, char *, char *, int, int, int, time_t); /* acknowledges a service problem */ static void remove_host_acknowledgement(host *); /* removes a host acknowledgement */ static void remove_service_acknowledgement(service *); /* removes a service acknowledgement */ -static void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ -static void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ +void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ +void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ static void start_executing_service_checks(void); /* starts executing service checks */ static void stop_executing_service_checks(void); /* stops executing service checks */ static void start_accepting_passive_service_checks(void); /* starts accepting passive service check results */ @@ -4104,7 +4104,7 @@ static void remove_service_acknowledgement(service *svc) } /* removes an expired host acknowledgement */ -static void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop) +void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop) { time_t current_time = 0L; @@ -4130,7 +4130,7 @@ static void handle_host_acknowledgement_expire_event(struct nm_event_execution_p } /* removes an expired service acknowledgement */ -static void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop) +void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop) { time_t current_time = 0L; diff --git a/src/naemon/xrddefault.c b/src/naemon/xrddefault.c index b312682af..95fb8985a 100644 --- a/src/naemon/xrddefault.c +++ b/src/naemon/xrddefault.c @@ -14,8 +14,13 @@ #include "defaults.h" #include "nm_alloc.h" #include "broker.h" +#include "events.h" #include +/* from commands.c */ +void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ +void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ + /******************************************************************/ /********************* INIT/CLEANUP FUNCTIONS *********************/ /******************************************************************/ @@ -636,6 +641,23 @@ int xrddefault_read_state_information(void) if (temp_host->last_hard_state_change == (time_t)0) temp_host->last_hard_state_change = temp_host->last_state_change; + /* if there was an expiring ack */ + if (temp_host->problem_has_been_acknowledged && temp_host->acknowledgement_end_time > 0) { + + /* get the time */ + time(¤t_time); + + /* and if the expiry time is in the future */ + if (temp_host->acknowledgement_end_time > current_time) { + /* schedule the expiry event */ + schedule_event(temp_host->acknowledgement_end_time - current_time, handle_host_acknowledgement_expire_event, (void *)temp_host); + } else { + /* otherwise unacknowledge the problem */ + temp_host->problem_has_been_acknowledged = FALSE; + temp_host->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + temp_host->acknowledgement_end_time = (time_t)0; + } + } /* update host status */ update_host_status(temp_host, FALSE); } @@ -678,6 +700,23 @@ int xrddefault_read_state_information(void) if (temp_service->last_hard_state_change == (time_t)0) temp_service->last_hard_state_change = temp_service->last_state_change; + /* if there was an expiring ack */ + if (temp_service->problem_has_been_acknowledged && temp_service->acknowledgement_end_time > 0) { + + /* get the time */ + time(¤t_time); + + /* and if the expiry time is in the future */ + if (temp_service->acknowledgement_end_time > current_time) { + /* schedule the expiry event */ + schedule_event(temp_service->acknowledgement_end_time - current_time, handle_service_acknowledgement_expire_event, (void *)temp_service); + } else { + /* otherwise unacknowledge the problem */ + temp_service->problem_has_been_acknowledged = FALSE; + temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; + temp_service->acknowledgement_end_time = (time_t)0; + } + } /* update service status */ update_service_status(temp_service, FALSE); } From 6881dfa7b32dd8d8241fbc927eef3440bdba5eb8 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Wed, 3 Aug 2022 15:18:44 +0200 Subject: [PATCH 12/18] Add tests for ACKNOWLEDGE_HOST_PROBLEM_EXPIRE Signed-off-by: Roel van Meer --- t-tap/test_commands.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/t-tap/test_commands.c b/t-tap/test_commands.c index 9028aeddd..0d02434c9 100644 --- a/t-tap/test_commands.c +++ b/t-tap/test_commands.c @@ -509,6 +509,19 @@ void test_host_commands(void) ok(!target_host->problem_has_been_acknowledged, "REMOVE_HOST_ACKNOWLEDGEMENT removes a host acknowledgement"); target_host->current_state = STATE_UP; + target_host->current_state = STATE_DOWN; + ok(CMD_ERROR_OK == process_external_command1("[1234567890] ACKNOWLEDGE_HOST_PROBLEM_EXPIRE;host1;2;0;0;4102441200;myself;expire in the future"), "core command: ACKNOWLEDGE_HOST_PROBLEM_EXPIRE"); + ok(target_host->problem_has_been_acknowledged, "ACKNOWLEDGE_HOST_PROBLEM_EXPIRE with future end_time acknowledges a host problem"); + + ok(CMD_ERROR_OK == process_external_command1("[1234567890] REMOVE_HOST_ACKNOWLEDGEMENT;host1"), "core command: REMOVE_HOST_ACKNOWLEDGEMENT"); + ok(!target_host->problem_has_been_acknowledged, "REMOVE_HOST_ACKNOWLEDGEMENT removes a host acknowledgement with expiry"); + target_host->current_state = STATE_UP; + + target_host->current_state = STATE_DOWN; + ok(CMD_ERROR_OK == process_external_command1("[1234567890] ACKNOWLEDGE_HOST_PROBLEM_EXPIRE;host1;2;0;0;946681200;myself;expire in the past"), "core command: ACKNOWLEDGE_HOST_PROBLEM_EXPIRE"); + ok(!target_host->problem_has_been_acknowledged, "ACKNOWLEDGE_HOST_PROBLEM_EXPIRE with past end_time doesn't acknowledge a host problem"); + target_host->current_state = STATE_UP; + ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_EVENT_HANDLER;host1"), "core command: DISABLE_HOST_EVENT_HANDLER"); ok(!target_host->event_handler_enabled, "DISABLE_HOST_EVENT_HANDLER disables event handler for a host"); @@ -670,7 +683,7 @@ void test_core_commands(void) int main(int /*@unused@*/ argc, char /*@unused@*/ **arv) { const char *test_config_file = TESTDIR "naemon.cfg"; - plan_tests(507); + plan_tests(513); init_event_queue(); config_file_dir = nspath_absolute_dirname(test_config_file, NULL); From fad6c9074401ed38303d3f3e40319222126a2b3a Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Tue, 6 Sep 2022 16:41:50 +0200 Subject: [PATCH 13/18] Don't declare functions twice --- src/naemon/commands.c | 2 -- src/naemon/commands.h | 4 ++++ src/naemon/xrddefault.c | 5 +---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/naemon/commands.c b/src/naemon/commands.c index 7d1846783..af69fe44a 100644 --- a/src/naemon/commands.c +++ b/src/naemon/commands.c @@ -77,8 +77,6 @@ static void acknowledge_host_problem(host *, char *, char *, int, int, int, time static void acknowledge_service_problem(service *, char *, char *, int, int, int, time_t); /* acknowledges a service problem */ static void remove_host_acknowledgement(host *); /* removes a host acknowledgement */ static void remove_service_acknowledgement(service *); /* removes a service acknowledgement */ -void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ -void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ static void start_executing_service_checks(void); /* starts executing service checks */ static void stop_executing_service_checks(void); /* stops executing service checks */ static void start_accepting_passive_service_checks(void); /* starts accepting passive service check results */ diff --git a/src/naemon/commands.h b/src/naemon/commands.h index b7539d99a..21db023c3 100644 --- a/src/naemon/commands.h +++ b/src/naemon/commands.h @@ -10,6 +10,7 @@ #include "objects_contact.h" #include "objects_host.h" #include "objects_service.h" +#include "events.h" NAGIOS_BEGIN_DECL @@ -220,6 +221,9 @@ int shutdown_command_file_worker(void); int disconnect_command_file_worker(void); int command_worker_get_pid(void); +void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ +void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ + NAGIOS_END_DECL #endif diff --git a/src/naemon/xrddefault.c b/src/naemon/xrddefault.c index 95fb8985a..38446f36b 100644 --- a/src/naemon/xrddefault.c +++ b/src/naemon/xrddefault.c @@ -15,12 +15,9 @@ #include "nm_alloc.h" #include "broker.h" #include "events.h" +#include "commands.h" #include -/* from commands.c */ -void handle_host_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired host acknowledgement */ -void handle_service_acknowledgement_expire_event(struct nm_event_execution_properties *evprop); /* removes an expired service acknowledgement */ - /******************************************************************/ /********************* INIT/CLEANUP FUNCTIONS *********************/ /******************************************************************/ From ac16d0fd19769a6b99a8541c55f473a4781478e3 Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Tue, 6 Sep 2022 20:51:43 +0200 Subject: [PATCH 14/18] Separate clearing and destroying event queue In tests, we want to be able to remove all events but not destroy the queue. --- src/naemon/events.c | 17 +++++++++++++---- src/naemon/events.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/naemon/events.c b/src/naemon/events.c index 8a37a3997..f5441bdbb 100644 --- a/src/naemon/events.c +++ b/src/naemon/events.c @@ -268,9 +268,20 @@ void init_event_queue(void) event_queue = evheap_create(); } -void destroy_event_queue(void) +void clear_event_queue(void) { struct timed_event *ev; + + if (event_queue == NULL) + return; + + while ((ev = evheap_head(event_queue)) != NULL) { + destroy_event(ev); + } +} + +void destroy_event_queue(void) +{ /* * Since naemon doesn't know if things is started, we can't trust that * destroy event queue actually means we have an event queue to destroy @@ -278,9 +289,7 @@ void destroy_event_queue(void) if (event_queue == NULL) return; - while ((ev = evheap_head(event_queue)) != NULL) { - destroy_event(ev); - } + clear_event_queue(); evheap_destroy(event_queue); event_queue = NULL; } diff --git a/src/naemon/events.h b/src/naemon/events.h index 386826132..b12dba2bd 100644 --- a/src/naemon/events.h +++ b/src/naemon/events.h @@ -58,6 +58,7 @@ long get_timed_event_time_left_ms(timed_event *ev); /* Main function */ void init_event_queue(void); /* creates the queue nagios_squeue */ int event_poll(void); /* main monitoring/event handler loop */ +void clear_event_queue(void); /* remove all events from the event queue */ void destroy_event_queue(void); /* destroys the queue nagios_squeue */ NAGIOS_END_DECL From 739690adf20524c3a9d95fbf671215a7a48afa3f Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Tue, 6 Sep 2022 22:24:08 +0200 Subject: [PATCH 15/18] Properly remove references to events when destroying After destroying the check events, references to those events must be cleared. If not, scheduling a new check event will try to destroy the event that is still referenced, which causes a segfault. --- src/naemon/checks_host.c | 3 +++ src/naemon/checks_service.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/naemon/checks_host.c b/src/naemon/checks_host.c index aa7f41dcd..e7f486207 100644 --- a/src/naemon/checks_host.c +++ b/src/naemon/checks_host.c @@ -188,6 +188,9 @@ static void handle_host_check_event(struct nm_event_execution_properties *evprop /* update the status log */ update_host_status(hst, FALSE); } + } else if (evprop->execution_type == EVENT_EXEC_ABORTED) { + /* If the event is destroyed, remove the reference. */ + hst->next_check_event = NULL; } } diff --git a/src/naemon/checks_service.c b/src/naemon/checks_service.c index 1f30b5d9a..6d1abc9b4 100644 --- a/src/naemon/checks_service.c +++ b/src/naemon/checks_service.c @@ -240,6 +240,9 @@ static void handle_service_check_event(struct nm_event_execution_properties *evp /* Otherwise, run the event */ run_scheduled_service_check(temp_service, options, latency); + } else if (evprop->execution_type == EVENT_EXEC_ABORTED) { + /* If the event is destroyed, remove the reference. */ + temp_service->next_check_event = NULL; } } From 2d2e3d1bec91c148c611bf2256f93202c669ad0b Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Tue, 6 Sep 2022 22:32:22 +0200 Subject: [PATCH 16/18] Allow event processing when testing commands --- t-tap/test_commands.c | 1 + 1 file changed, 1 insertion(+) diff --git a/t-tap/test_commands.c b/t-tap/test_commands.c index 0d02434c9..fe0040538 100644 --- a/t-tap/test_commands.c +++ b/t-tap/test_commands.c @@ -691,6 +691,7 @@ int main(int /*@unused@*/ argc, char /*@unused@*/ **arv) assert(OK == read_all_object_data(test_config_file)); assert(OK == initialize_downtime_data()); assert(OK == initialize_retention_data()); + nagios_iobs = iobroker_create(); test_register(); test_parsing(); test_core_commands(); From 9e0bb482f1d56616d3ef256609030faf6c03161d Mon Sep 17 00:00:00 2001 From: Roel van Meer Date: Tue, 6 Sep 2022 22:27:25 +0200 Subject: [PATCH 17/18] Add test for expiring acknowledgement This adds a test that checks if the acknowledgement expiry event does its work. It starts by removing all events from the event queue. We then run the command, with expiration set in two seconds. After waiting three seconds, we process a single event (we should have only one event in the queue at this point). After processing the event, the acknowledgement should be gone. --- t-tap/test_commands.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/t-tap/test_commands.c b/t-tap/test_commands.c index fe0040538..4377efbaf 100644 --- a/t-tap/test_commands.c +++ b/t-tap/test_commands.c @@ -522,6 +522,16 @@ void test_host_commands(void) ok(!target_host->problem_has_been_acknowledged, "ACKNOWLEDGE_HOST_PROBLEM_EXPIRE with past end_time doesn't acknowledge a host problem"); target_host->current_state = STATE_UP; + clear_event_queue(); + target_host->current_state = STATE_DOWN; + nm_asprintf(&cmdstr, "[1234567890] ACKNOWLEDGE_HOST_PROBLEM_EXPIRE;host1;2;0;0;%llu;myself;expire in two seconds", (unsigned long long int)time(NULL)+2); + ok(CMD_ERROR_OK == process_external_command1(cmdstr), "core command: ACKNOWLEDGE_HOST_PROBLEM_EXPIRE"); + ok(target_host->problem_has_been_acknowledged, "ACKNOWLEDGE_HOST_PROBLEM_EXPIRE acknowledgement present before event"); + sleep(3); + event_poll(); + ok(!target_host->problem_has_been_acknowledged, "ACKNOWLEDGE_HOST_PROBLEM_EXPIRE acknowledgement gone after event"); + free(cmdstr); + ok(CMD_ERROR_OK == process_external_command1("[1234567890] DISABLE_HOST_EVENT_HANDLER;host1"), "core command: DISABLE_HOST_EVENT_HANDLER"); ok(!target_host->event_handler_enabled, "DISABLE_HOST_EVENT_HANDLER disables event handler for a host"); @@ -683,7 +693,7 @@ void test_core_commands(void) int main(int /*@unused@*/ argc, char /*@unused@*/ **arv) { const char *test_config_file = TESTDIR "naemon.cfg"; - plan_tests(513); + plan_tests(516); init_event_queue(); config_file_dir = nspath_absolute_dirname(test_config_file, NULL); From 4e327e3e175d65feffcf4c0eba282522d23d998d Mon Sep 17 00:00:00 2001 From: Sven Nierlein Date: Wed, 14 Sep 2022 11:37:30 +0200 Subject: [PATCH 18/18] Update test_commands.c fix number of tests --- t-tap/test_commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t-tap/test_commands.c b/t-tap/test_commands.c index 68452a40a..b8af68fde 100644 --- a/t-tap/test_commands.c +++ b/t-tap/test_commands.c @@ -714,7 +714,7 @@ void test_core_commands(void) int main(int /*@unused@*/ argc, char /*@unused@*/ **arv) { const char *test_config_file = TESTDIR "naemon.cfg"; - plan_tests(516); + plan_tests(519); init_event_queue(); config_file_dir = nspath_absolute_dirname(test_config_file, NULL);