int CompatUtility::GetCheckableInCheckPeriod(const Checkable::Ptr& checkable) { TimePeriod::Ptr timeperiod = checkable->GetCheckPeriod(); /* none set means always checked */ if (!timeperiod) return 1; return (timeperiod->IsInside(Utility::GetTime()) ? 1 : 0); }
int CompatUtility::GetCheckableInNotificationPeriod(const Checkable::Ptr& checkable) { for (const Notification::Ptr& notification : checkable->GetNotifications()) { TimePeriod::Ptr timeperiod = notification->GetPeriod(); if (!timeperiod || timeperiod->IsInside(Utility::GetTime())) return 1; } return 0; }
Value ContactsTable::InServiceNotificationPeriodAccessor(const Value& row) { User::Ptr user = static_cast<User::Ptr>(row); if (!user) return Empty; TimePeriod::Ptr timeperiod = user->GetPeriod(); if (!timeperiod) return Empty; return (timeperiod->IsInside(Utility::GetTime()) ? 1 : 0); }
Value ServicesTable::InCheckPeriodAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; TimePeriod::Ptr timeperiod = service->GetCheckPeriod(); /* none set means always checked */ if (!timeperiod) return 1; return Convert::ToLong(timeperiod->IsInside(Utility::GetTime())); }
Value ServicesTable::InNotificationPeriodAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; for (const Notification::Ptr& notification : service->GetNotifications()) { TimePeriod::Ptr timeperiod = notification->GetPeriod(); if (!timeperiod || timeperiod->IsInside(Utility::GetTime())) return 1; } return 0; }
bool Dependency::IsAvailable(DependencyType dt) const { Checkable::Ptr parent = GetParent(); Host::Ptr parentHost; Service::Ptr parentService; tie(parentHost, parentService) = GetHostService(parent); /* ignore if it's the same checkable object */ if (parent == GetChild()) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Parent and child " << (parentService ? "service" : "host") << " are identical."; return true; } /* ignore pending */ if (!parent->GetLastCheckResult()) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' hasn't been checked yet."; return true; } if (GetIgnoreSoftStates()) { /* ignore soft states */ if (parent->GetStateType() == StateTypeSoft) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is in a soft state."; return true; } } else { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' failed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is in a soft state."; } int state; if (parentService) state = ServiceStateToFilter(parentService->GetState()); else state = HostStateToFilter(parentHost->GetState()); /* check state */ if (state & GetStateFilter()) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' matches state filter."; return true; } /* ignore if not in time period */ TimePeriod::Ptr tp = GetPeriod(); if (tp && !tp->IsInside(Utility::GetTime())) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Outside time period."; return true; } if (dt == DependencyCheckExecution && !GetDisableChecks()) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Checks are not disabled."; return true; } else if (dt == DependencyNotification && !GetDisableNotifications()) { Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' passed: Notifications are not disabled"; return true; } Log(LogNotice, "Dependency") << "Dependency '" << GetName() << "' failed. Parent " << (parentService ? "service" : "host") << " '" << parent->GetName() << "' is " << (parentService ? Service::StateToString(parentService->GetState()) : Host::StateToString(parentHost->GetState())); return false; }
void CheckerComponent::CheckThreadProc() { Utility::SetThreadName("Check Scheduler"); IcingaApplication::Ptr icingaApp = IcingaApplication::GetInstance(); boost::mutex::scoped_lock lock(m_Mutex); for (;;) { typedef boost::multi_index::nth_index<CheckableSet, 1>::type CheckTimeView; CheckTimeView& idx = boost::get<1>(m_IdleCheckables); while (idx.begin() == idx.end() && !m_Stopped) m_CV.wait(lock); if (m_Stopped) break; auto it = idx.begin(); CheckableScheduleInfo csi = *it; double wait = csi.NextCheck - Utility::GetTime(); //#ifdef I2_DEBUG // Log(LogDebug, "CheckerComponent") // << "Pending checks " << Checkable::GetPendingChecks() // << " vs. max concurrent checks " << icingaApp->GetMaxConcurrentChecks() << "."; //#endif /* I2_DEBUG */ if (Checkable::GetPendingChecks() >= icingaApp->GetMaxConcurrentChecks()) wait = 0.5; if (wait > 0) { /* Wait for the next check. */ m_CV.timed_wait(lock, boost::posix_time::milliseconds(long(wait * 1000))); continue; } Checkable::Ptr checkable = csi.Object; m_IdleCheckables.erase(checkable); bool forced = checkable->GetForceNextCheck(); bool check = true; if (!forced) { if (!checkable->IsReachable(DependencyCheckExecution)) { Log(LogNotice, "CheckerComponent") << "Skipping check for object '" << checkable->GetName() << "': Dependency failed."; check = false; } Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); if (host && !service && (!checkable->GetEnableActiveChecks() || !icingaApp->GetEnableHostChecks())) { Log(LogNotice, "CheckerComponent") << "Skipping check for host '" << host->GetName() << "': active host checks are disabled"; check = false; } if (host && service && (!checkable->GetEnableActiveChecks() || !icingaApp->GetEnableServiceChecks())) { Log(LogNotice, "CheckerComponent") << "Skipping check for service '" << service->GetName() << "': active service checks are disabled"; check = false; } TimePeriod::Ptr tp = checkable->GetCheckPeriod(); if (tp && !tp->IsInside(Utility::GetTime())) { Log(LogNotice, "CheckerComponent") << "Skipping check for object '" << checkable->GetName() << "': not in check period '" << tp->GetName() << "'"; check = false; } } /* reschedule the checkable if checks are disabled */ if (!check) { m_IdleCheckables.insert(GetCheckableScheduleInfo(checkable)); lock.unlock(); Log(LogDebug, "CheckerComponent") << "Checks for checkable '" << checkable->GetName() << "' are disabled. Rescheduling check."; checkable->UpdateNextCheck(); lock.lock(); continue; } csi = GetCheckableScheduleInfo(checkable); Log(LogDebug, "CheckerComponent") << "Scheduling info for checkable '" << checkable->GetName() << "' (" << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", checkable->GetNextCheck()) << "): Object '" << csi.Object->GetName() << "', Next Check: " << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", csi.NextCheck) << "(" << csi.NextCheck << ")."; m_PendingCheckables.insert(csi); lock.unlock(); if (forced) { ObjectLock olock(checkable); checkable->SetForceNextCheck(false); } Log(LogDebug, "CheckerComponent") << "Executing check for '" << checkable->GetName() << "'"; Checkable::IncreasePendingChecks(); Utility::QueueAsyncCallback(std::bind(&CheckerComponent::ExecuteCheckHelper, CheckerComponent::Ptr(this), checkable)); lock.lock(); } }
bool Notification::CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force, bool reminder) { if (!force) { TimePeriod::Ptr tp = user->GetPeriod(); if (tp && !tp->IsInside(Utility::GetTime())) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << " and user '" << user->GetName() << "': user period not in timeperiod '" << tp->GetName() << "'"; return false; } unsigned long ftype = type; Log(LogDebug, "Notification") << "User notification, Type '" << NotificationTypeToStringInternal(type) << "', TypeFilter: " << NotificationFilterToString(user->GetTypeFilter(), GetTypeFilterMap()) << " (FType=" << ftype << ", TypeFilter=" << GetTypeFilter() << ")"; if (!(ftype & user->GetTypeFilter())) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << " and user '" << user->GetName() << "': type '" << NotificationTypeToStringInternal(type) << "' does not match type filter: " << NotificationFilterToString(user->GetTypeFilter(), GetTypeFilterMap()) << "."; return false; } /* check state filters it this is not a recovery notification */ if (type != NotificationRecovery) { Checkable::Ptr checkable = GetCheckable(); Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); unsigned long fstate; String stateStr; if (service) { fstate = ServiceStateToFilter(service->GetState()); stateStr = NotificationServiceStateToString(service->GetState()); } else { fstate = HostStateToFilter(host->GetState()); stateStr = NotificationHostStateToString(host->GetState()); } Log(LogDebug, "Notification") << "User notification, State '" << stateStr << "', StateFilter: " << NotificationFilterToString(user->GetStateFilter(), GetStateFilterMap()) << " (FState=" << fstate << ", StateFilter=" << user->GetStateFilter() << ")"; if (!(fstate & user->GetStateFilter())) { Log(LogNotice, "Notification") << "Not " << (reminder ? "reminder " : " ") << "sending notifications for notification object '" << GetName() << " and user '" << user->GetName() << "': state '" << stateStr << "' does not match state filter: " << NotificationFilterToString(user->GetStateFilter(), GetStateFilterMap()) << "."; return false; } } } else { Log(LogNotice, "Notification") << "Not checking " << (reminder ? "reminder " : " ") << "notification filters for notification object '" << GetName() << "' and user '" << user->GetName() << "': Notification was forced."; } return true; }
void Notification::BeginExecuteNotification(NotificationType type, const CheckResult::Ptr& cr, bool force, bool reminder, const String& author, const String& text) { Log(LogNotice, "Notification") << "Attempting to send " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << "'."; Checkable::Ptr checkable = GetCheckable(); if (!force) { TimePeriod::Ptr tp = GetPeriod(); if (tp && !tp->IsInside(Utility::GetTime())) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << "': not in timeperiod '" << tp->GetName() << "'"; return; } double now = Utility::GetTime(); Dictionary::Ptr times = GetTimes(); if (times && type == NotificationProblem) { Value timesBegin = times->Get("begin"); Value timesEnd = times->Get("end"); if (timesBegin != Empty && timesBegin >= 0 && now < checkable->GetLastHardStateChange() + timesBegin) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << "': before specified begin time (" << Utility::FormatDuration(timesBegin) << ")"; /* we need to adjust the next notification time * to now + begin delaying the first notification */ double nextProposedNotification = now + timesBegin + 1.0; if (GetNextNotification() > nextProposedNotification) SetNextNotification(nextProposedNotification); return; } if (timesEnd != Empty && timesEnd >= 0 && now > checkable->GetLastHardStateChange() + timesEnd) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << "': after specified end time (" << Utility::FormatDuration(timesEnd) << ")"; return; } } unsigned long ftype = type; Log(LogDebug, "Notification") << "Type '" << NotificationTypeToStringInternal(type) << "', TypeFilter: " << NotificationFilterToString(GetTypeFilter(), GetTypeFilterMap()) << " (FType=" << ftype << ", TypeFilter=" << GetTypeFilter() << ")"; if (!(ftype & GetTypeFilter())) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << "': type '" << NotificationTypeToStringInternal(type) << "' does not match type filter: " << NotificationFilterToString(GetTypeFilter(), GetTypeFilterMap()) << "."; return; } /* ensure that recovery notifications are always sent, no state filter checks necessary */ if (type != NotificationRecovery) { Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); unsigned long fstate; String stateStr; if (service) { fstate = ServiceStateToFilter(service->GetState()); stateStr = NotificationServiceStateToString(service->GetState()); } else { fstate = HostStateToFilter(host->GetState()); stateStr = NotificationHostStateToString(host->GetState()); } Log(LogDebug, "Notification") << "State '" << stateStr << "', StateFilter: " << NotificationFilterToString(GetStateFilter(), GetStateFilterMap()) << " (FState=" << fstate << ", StateFilter=" << GetStateFilter() << ")"; if (!(fstate & GetStateFilter())) { Log(LogNotice, "Notification") << "Not sending " << (reminder ? "reminder " : " ") << "notifications for notification object '" << GetName() << "': state '" << stateStr << "' does not match state filter: " << NotificationFilterToString(GetStateFilter(), GetStateFilterMap()) << "."; return; } } } else { Log(LogNotice, "Notification") << "Not checking " << (reminder ? "reminder " : " ") << "notification filters for notification object '" << GetName() << "': Notification was forced."; } { ObjectLock olock(this); UpdateNotificationNumber(); double now = Utility::GetTime(); SetLastNotification(now); if (type == NotificationProblem && GetInterval() <= 0) SetNoMoreNotifications(true); else SetNoMoreNotifications(false); if (type == NotificationProblem && GetInterval() > 0) SetNextNotification(now + GetInterval()); if (type == NotificationProblem) SetLastProblemNotification(now); } std::set<User::Ptr> allUsers; std::set<User::Ptr> users = GetUsers(); std::copy(users.begin(), users.end(), std::inserter(allUsers, allUsers.begin())); for (const UserGroup::Ptr& ug : GetUserGroups()) { std::set<User::Ptr> members = ug->GetMembers(); std::copy(members.begin(), members.end(), std::inserter(allUsers, allUsers.begin())); } std::set<User::Ptr> allNotifiedUsers; Array::Ptr notifiedProblemUsers = GetNotifiedProblemUsers(); for (const User::Ptr& user : allUsers) { String userName = user->GetName(); if (!user->GetEnableNotifications()) { Log(LogNotice, "Notification") << "Disabled notifications for user '" << userName << "'. Not sending notification."; continue; } if (!CheckNotificationUserFilters(type, user, force, reminder)) { Log(LogNotice, "Notification") << "Notification filters for user '" << userName << "' not matched. Not sending notification."; continue; } /* on recovery, check if user was notified before */ if (type == NotificationRecovery) { if (!notifiedProblemUsers->Contains(userName)) { Log(LogNotice, "Notification") << "We did not notify user '" << userName << "' for a problem before. Not sending recovery notification."; continue; } } Log(LogInformation, "Notification") << "Sending " << (reminder ? "reminder " : "") << "'" << NotificationTypeToStringInternal(type) << "' notification '" << GetName() << " for user '" << userName << "'"; Utility::QueueAsyncCallback(boost::bind(&Notification::ExecuteNotificationHelper, this, type, user, cr, force, author, text)); /* collect all notified users */ allNotifiedUsers.insert(user); /* store all notified users for later recovery checks */ if (type == NotificationProblem && !notifiedProblemUsers->Contains(userName)) notifiedProblemUsers->Add(userName); } /* if this was a recovery notification, reset all notified users */ if (type == NotificationRecovery) notifiedProblemUsers->Clear(); /* used in db_ido for notification history */ Service::OnNotificationSentToAllUsers(this, checkable, allNotifiedUsers, type, cr, author, text, MessageOrigin::Ptr()); }