Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for expiring acknowledgements #391

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/naemon/broker.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/naemon/broker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down
5 changes: 5 additions & 0 deletions src/naemon/checks_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -969,13 +972,15 @@ 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);
} else if (hst->acknowledgement_type == ACKNOWLEDGEMENT_STICKY && hst->current_state == STATE_UP) {

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);
Expand Down
7 changes: 7 additions & 0 deletions src/naemon/checks_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -636,13 +639,15 @@ 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);
} else if (temp_service->acknowledgement_type == ACKNOWLEDGEMENT_STICKY && temp_service->current_state == STATE_OK) {

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);
Expand Down Expand Up @@ -705,6 +710,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) {
Expand Down Expand Up @@ -788,6 +794,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;
}

Expand Down
122 changes: 110 additions & 12 deletions src/naemon/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -1881,7 +1881,11 @@ 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_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);
Expand Down Expand Up @@ -2257,7 +2261,12 @@ 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_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);
Expand Down Expand Up @@ -2728,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);
Expand Down Expand Up @@ -3958,15 +3975,23 @@ 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;

/* cannot acknowledge a non-existent problem */
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);
/* get the time */
time(&current_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 */
if (notify == TRUE)
Expand All @@ -3978,27 +4003,41 @@ 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 */
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(&current_time);
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;
}


/* 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;

/* cannot acknowledge a non-existent problem */
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);
/* get the time */
time(&current_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 */
if (notify == TRUE)
Expand All @@ -4010,12 +4049,18 @@ 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 */
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(&current_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);
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;
}
Expand All @@ -4027,6 +4072,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);
Expand All @@ -4044,6 +4090,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);
Expand All @@ -4054,6 +4101,57 @@ static void remove_service_acknowledgement(service *svc)
return;
}

/* removes an expired host acknowledgement */
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(&current_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 */
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(&current_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)
Expand Down
4 changes: 4 additions & 0 deletions src/naemon/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "objects_contact.h"
#include "objects_host.h"
#include "objects_service.h"
#include "events.h"

NAGIOS_BEGIN_DECL

Expand Down Expand Up @@ -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
3 changes: 3 additions & 0 deletions src/naemon/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading