1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #ifndef CHECKABLE_H
4 #define CHECKABLE_H
5 
6 #include "base/atomic.hpp"
7 #include "base/timer.hpp"
8 #include "base/process.hpp"
9 #include "icinga/i2-icinga.hpp"
10 #include "icinga/checkable-ti.hpp"
11 #include "icinga/timeperiod.hpp"
12 #include "icinga/notification.hpp"
13 #include "icinga/comment.hpp"
14 #include "icinga/downtime.hpp"
15 #include "remote/endpoint.hpp"
16 #include "remote/messageorigin.hpp"
17 #include <condition_variable>
18 #include <cstdint>
19 #include <functional>
20 
21 namespace icinga
22 {
23 
24 /**
25  * @ingroup icinga
26  */
27 enum DependencyType
28 {
29 	DependencyState,
30 	DependencyCheckExecution,
31 	DependencyNotification
32 };
33 
34 /**
35  * Checkable Types
36  *
37  * @ingroup icinga
38  */
39 enum CheckableType
40 {
41 	CheckableHost,
42 	CheckableService
43 };
44 
45 /**
46  * @ingroup icinga
47  */
48 enum FlappingStateFilter
49 {
50 	FlappingStateFilterOk = 1,
51 	FlappingStateFilterWarning = 2,
52 	FlappingStateFilterCritical = 4,
53 	FlappingStateFilterUnknown = 8,
54 };
55 
56 class CheckCommand;
57 class EventCommand;
58 class Dependency;
59 
60 /**
61  * An Icinga service.
62  *
63  * @ingroup icinga
64  */
65 class Checkable : public ObjectImpl<Checkable>
66 {
67 public:
68 	DECLARE_OBJECT(Checkable);
69 	DECLARE_OBJECTNAME(Checkable);
70 
71 	static void StaticInitialize();
72 	static thread_local std::function<void(const Value& commandLine, const ProcessResult&)> ExecuteCommandProcessFinishedHandler;
73 
74 	Checkable();
75 
76 	std::set<Checkable::Ptr> GetParents() const;
77 	std::set<Checkable::Ptr> GetChildren() const;
78 	std::set<Checkable::Ptr> GetAllChildren() const;
79 
80 	void AddGroup(const String& name);
81 
82 	bool IsReachable(DependencyType dt = DependencyState, intrusive_ptr<Dependency> *failedDependency = nullptr, int rstack = 0) const;
83 
84 	AcknowledgementType GetAcknowledgement();
85 
86 	void AcknowledgeProblem(const String& author, const String& comment, AcknowledgementType type, bool notify = true, bool persistent = false, double changeTime = Utility::GetTime(), double expiry = 0, const MessageOrigin::Ptr& origin = nullptr);
87 	void ClearAcknowledgement(const String& removedBy, double changeTime = Utility::GetTime(), const MessageOrigin::Ptr& origin = nullptr);
88 
89 	int GetSeverity() const override;
90 	bool GetProblem() const override;
91 	bool GetHandled() const override;
92 	Timestamp GetNextUpdate() const override;
93 
94 	/* Checks */
95 	intrusive_ptr<CheckCommand> GetCheckCommand() const;
96 	TimePeriod::Ptr GetCheckPeriod() const;
97 
98 	long GetSchedulingOffset();
99 	void SetSchedulingOffset(long offset);
100 
101 	void UpdateNextCheck(const MessageOrigin::Ptr& origin = nullptr);
102 
103 	bool HasBeenChecked() const;
104 	virtual bool IsStateOK(ServiceState state) const = 0;
105 
106 	double GetLastCheck() const final;
107 
108 	virtual void SaveLastState(ServiceState state, double timestamp) = 0;
109 
110 	static void UpdateStatistics(const CheckResult::Ptr& cr, CheckableType type);
111 
112 	void ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros = nullptr);
113 	void ExecuteCheck();
114 	void ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrigin::Ptr& origin = nullptr);
115 
116 	Endpoint::Ptr GetCommandEndpoint() const;
117 
118 	static boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, const MessageOrigin::Ptr&)> OnNewCheckResult;
119 	static boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, StateType, const MessageOrigin::Ptr&)> OnStateChange;
120 	static boost::signals2::signal<void (const Checkable::Ptr&, const CheckResult::Ptr&, std::set<Checkable::Ptr>, const MessageOrigin::Ptr&)> OnReachabilityChanged;
121 	static boost::signals2::signal<void (const Checkable::Ptr&, NotificationType, const CheckResult::Ptr&,
122 		const String&, const String&, const MessageOrigin::Ptr&)> OnNotificationsRequested;
123 	static boost::signals2::signal<void (const Notification::Ptr&, const Checkable::Ptr&, const User::Ptr&,
124 		const NotificationType&, const CheckResult::Ptr&, const String&, const String&, const String&,
125 		const MessageOrigin::Ptr&)> OnNotificationSentToUser;
126 	static boost::signals2::signal<void (const Notification::Ptr&, const Checkable::Ptr&, const std::set<User::Ptr>&,
127 		const NotificationType&, const CheckResult::Ptr&, const String&,
128 		const String&, const MessageOrigin::Ptr&)> OnNotificationSentToAllUsers;
129 	static boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType,
130 		bool, bool, double, double, const MessageOrigin::Ptr&)> OnAcknowledgementSet;
131 	static boost::signals2::signal<void (const Checkable::Ptr&, const String&, double, const MessageOrigin::Ptr&)> OnAcknowledgementCleared;
132 	static boost::signals2::signal<void (const Checkable::Ptr&, double)> OnFlappingChange;
133 	static boost::signals2::signal<void (const Checkable::Ptr&)> OnNextCheckUpdated;
134 	static boost::signals2::signal<void (const Checkable::Ptr&)> OnEventCommandExecuted;
135 
136 	static Atomic<uint_fast64_t> CurrentConcurrentChecks;
137 
138 	/* Downtimes */
139 	int GetDowntimeDepth() const final;
140 
141 	void RemoveAllDowntimes();
142 	void TriggerDowntimes();
143 	bool IsInDowntime() const;
144 	bool IsAcknowledged() const;
145 
146 	std::set<Downtime::Ptr> GetDowntimes() const;
147 	void RegisterDowntime(const Downtime::Ptr& downtime);
148 	void UnregisterDowntime(const Downtime::Ptr& downtime);
149 
150 	/* Comments */
151 	void RemoveAllComments();
152 	void RemoveCommentsByType(int type, const String& removedBy = String());
153 
154 	std::set<Comment::Ptr> GetComments() const;
155 	Comment::Ptr GetLastComment() const;
156 	void RegisterComment(const Comment::Ptr& comment);
157 	void UnregisterComment(const Comment::Ptr& comment);
158 
159 	/* Notifications */
160 	void SendNotifications(NotificationType type, const CheckResult::Ptr& cr, const String& author = "", const String& text = "");
161 
162 	std::set<Notification::Ptr> GetNotifications() const;
163 	void RegisterNotification(const Notification::Ptr& notification);
164 	void UnregisterNotification(const Notification::Ptr& notification);
165 
166 	void ResetNotificationNumbers();
167 
168 	/* Event Handler */
169 	void ExecuteEventHandler(const Dictionary::Ptr& resolvedMacros = nullptr,
170 		bool useResolvedMacros = false);
171 
172 	intrusive_ptr<EventCommand> GetEventCommand() const;
173 
174 	/* Flapping Detection */
175 	bool IsFlapping() const;
176 
177 	/* Dependencies */
178 	void AddDependency(const intrusive_ptr<Dependency>& dep);
179 	void RemoveDependency(const intrusive_ptr<Dependency>& dep);
180 	std::vector<intrusive_ptr<Dependency> > GetDependencies() const;
181 
182 	void AddReverseDependency(const intrusive_ptr<Dependency>& dep);
183 	void RemoveReverseDependency(const intrusive_ptr<Dependency>& dep);
184 	std::vector<intrusive_ptr<Dependency> > GetReverseDependencies() const;
185 
186 	void ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& value) final;
187 	void ValidateRetryInterval(const Lazy<double>& lvalue, const ValidationUtils& value) final;
188 	void ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& value) final;
189 
190 	bool NotificationReasonApplies(NotificationType type);
191 	bool NotificationReasonSuppressed(NotificationType type);
192 	bool IsLikelyToBeCheckedSoon();
193 
194 	static void IncreasePendingChecks();
195 	static void DecreasePendingChecks();
196 	static int GetPendingChecks();
197 	static void AquirePendingCheckSlot(int maxPendingChecks);
198 
199 	static Object::Ptr GetPrototype();
200 
201 protected:
202 	void Start(bool runtimeCreated) override;
203 	void OnConfigLoaded() override;
204 	void OnAllConfigLoaded() override;
205 
206 private:
207 	mutable std::mutex m_CheckableMutex;
208 	bool m_CheckRunning{false};
209 	long m_SchedulingOffset;
210 
211 	static std::mutex m_StatsMutex;
212 	static int m_PendingChecks;
213 	static std::condition_variable m_PendingChecksCV;
214 
215 	/* Downtimes */
216 	std::set<Downtime::Ptr> m_Downtimes;
217 	mutable std::mutex m_DowntimeMutex;
218 
219 	static void NotifyFixedDowntimeStart(const Downtime::Ptr& downtime);
220 	static void NotifyFlexibleDowntimeStart(const Downtime::Ptr& downtime);
221 	static void NotifyDowntimeInternal(const Downtime::Ptr& downtime);
222 
223 	static void NotifyDowntimeEnd(const Downtime::Ptr& downtime);
224 
225 	static void FireSuppressedNotifications(const Timer * const&);
226 	static void CleanDeadlinedExecutions(const Timer * const&);
227 
228 	/* Comments */
229 	std::set<Comment::Ptr> m_Comments;
230 	mutable std::mutex m_CommentMutex;
231 
232 	/* Notifications */
233 	std::set<Notification::Ptr> m_Notifications;
234 	mutable std::mutex m_NotificationMutex;
235 
236 	/* Dependencies */
237 	mutable std::mutex m_DependencyMutex;
238 	std::set<intrusive_ptr<Dependency> > m_Dependencies;
239 	std::set<intrusive_ptr<Dependency> > m_ReverseDependencies;
240 
241 	void GetAllChildrenInternal(std::set<Checkable::Ptr>& children, int level = 0) const;
242 
243 	/* Flapping */
244 	static const std::map<String, int> m_FlappingStateFilterMap;
245 
246 	void UpdateFlappingStatus(ServiceState newState);
247 	static int ServiceStateToFlappingFilter(ServiceState state);
248 };
249 
250 }
251 
252 #endif /* CHECKABLE_H */
253 
254 #include "icinga/dependency.hpp"
255