/* * Called when a notification chain starts. This is used to * avoid sending notifications from a node that isn't supposed * to send it */ static neb_cb_result * hook_notification(merlin_event *pkt, void *data) { nebstruct_notification_data *ds = (nebstruct_notification_data *)data; struct merlin_notify_stats *notif_stats = NULL; merlin_node *owning_node = NULL; struct host *hst; struct service *svc; unsigned int object_id; int check_type; if (ds->type == NEBTYPE_NOTIFICATION_END) { int ret = 0; /* Always propagate results to peers and masters */ pkt->hdr.selection = DEST_PEERS_MASTERS; if (ds->notification_type == HOST_NOTIFICATION) { hst = (struct host *)ds->object_ptr; ds->object_ptr = (void *)(uintptr_t)(hst->current_notification_number); ds->start_time.tv_usec = hst->no_more_notifications; ds->start_time.tv_sec = hst->last_notification; ds->end_time.tv_usec = 0; ds->end_time.tv_sec = hst->next_notification; } else if (ds->notification_type == SERVICE_NOTIFICATION) { svc = (struct service *)ds->object_ptr; ds->object_ptr = (void *)(uintptr_t)(svc->current_notification_number); ds->start_time.tv_usec = svc->no_more_notifications; ds->start_time.tv_sec = svc->last_notification; ds->end_time.tv_usec = 0; ds->end_time.tv_sec = svc->next_notification; } else { lerr("Unknown notification type %i", ds->notification_type); } /* * If it is a custom notification it should always be sent directly * because we won't have a pending check result waiting to be sent. * The same goes for when we've ended up here as a result of a received * merlin event. In this case, if a poller sends a check result which * generates a notification that we're responsible for, we notify and * let fellow nodes know that we've notified directly. * Otherwise, we're are to expect a check result to be sent to fellow * nodes directly after and we don't want it to overwrite the data * sent in the notification packet, so we hold the notification packet * until next check result is sent. */ if(ds->reason_type == NOTIFICATION_CUSTOM || (merlin_sender && recv_event)) { if (merlin_sender && recv_event && recv_event->hdr.type != NEBCALLBACK_EXTERNAL_COMMAND_DATA) { pkt->hdr.selection = get_sel_id(merlin_sender->hostgroups); } ret = send_generic(pkt, data); } else { ret = hold_notification_packet(pkt, ds); } return neb_cb_result_create(ret); } /* don't count or (try to) block notifications after they're sent */ if (ds->type != NEBTYPE_NOTIFICATION_START) return 0; if (ds->notification_type == HOST_NOTIFICATION){ hst = ds->object_ptr; object_id = hst->id; check_type = hst->check_type; owning_node = pgroup_host_node(hst->id); ldebug("notif: Checking host notification for %s", hst->name); } else { svc = ds->object_ptr; object_id = svc->id; check_type = svc->check_type; owning_node = pgroup_service_node(svc->id); ldebug("notif: Checking service notification for %s;%s", svc->host_name, svc->description); } notif_stats = &merlin_notify_stats[ds->reason_type][ds->notification_type][check_type]; /* * If we're a poller and we have set "notifies = no" in our configuration * AND we currently have one or more masters online, we should NOT notify. */ if (online_masters && !(ipc.flags & MERLIN_NODE_NOTIFIES)) { ldebug("notif: Poller blocking notification in favour of master"); notif_stats->master++; return neb_cb_result_create_full(NEBERROR_CALLBACKCANCEL, "Notification will be handled by master(s)"); } /* Figure out who should handle the notification */ if (owning_node == &ipc) { ldebug("notif: Local node is owner, allowing notification"); notif_stats->sent++; return neb_cb_result_create(0); } else if (owning_node->type == MODE_POLLER) { if (owning_node->flags & MERLIN_NODE_NOTIFIES) { ldebug("notif: Poller can notify. Cancelling notification"); notif_stats->poller++; return neb_cb_result_create_full(NEBERROR_CALLBACKCANCEL, "Notification will be handled by a poller (%s)", owning_node->name); } else { /* Poller can't notify, who should handle it instead? */ if ((num_peers == 0 || should_run_check(object_id)) && pgroup_num_notify(owning_node) == 0 ) { notif_stats->sent++; ldebug("notif: Poller can't notify, notifying in its place"); return neb_cb_result_create(0); } else { ldebug("notif: Poller can't notify, a peer will notify"); notif_stats->peer++; return neb_cb_result_create_full(NEBERROR_CALLBACKCANCEL, "Poller can't notify, a peer will notify"); } } } else if (owning_node->type == MODE_PEER) { ldebug("notif: Cancelling notification, a peer (%s) handles it", owning_node->name); notif_stats->peer++; return neb_cb_result_create_full(NEBERROR_CALLBACKCANCEL, "Notification will be handled by a peer (%s)", owning_node->name); } ldebug("notif: Unable to determine who should notify - allowing"); notif_stats->sent++; return neb_cb_result_create(0); }
/* * Return a (list of) merlin node(s) associated * with a particular selection name, or null if * the selection name is invalid */ linked_item *nodes_by_sel_name(const char *name) { return nodes_by_sel_id(get_sel_id(name)); }