Ejemplo n.º 1
0
Archivo: hooks.c Proyecto: op5/merlin
/*
 * 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);
}
Ejemplo n.º 2
0
Archivo: node.c Proyecto: ageric/merlin
/*
 * 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));
}