@@ -46,7 +46,9 @@ REGISTER_APIFUNCTION(SetRemovalInfo, event, &ClusterEvents::SetRemovalInfoAPIHan
4646void ClusterEvents::StaticInitialize ()
4747{
4848 Checkable::OnNewCheckResult.connect (&ClusterEvents::CheckResultHandler);
49- Checkable::OnNextCheckChanged.connect (&ClusterEvents::NextCheckChangedHandler);
49+ Checkable::OnNextCheckChanged.connect ([](const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin) {
50+ NextCheckChangedHandler (checkable, origin);
51+ });
5052 Checkable::OnLastCheckStartedChanged.connect (&ClusterEvents::LastCheckStartedChangedHandler);
5153 Checkable::OnStateBeforeSuppressionChanged.connect (&ClusterEvents::StateBeforeSuppressionChangedHandler);
5254 Checkable::OnSuppressedNotificationsChanged.connect (&ClusterEvents::SuppressedNotificationsChangedHandler);
@@ -183,7 +185,7 @@ Value ClusterEvents::CheckResultAPIHandler(const MessageOrigin::Ptr& origin, con
183185 return Empty;
184186}
185187
186- void ClusterEvents::NextCheckChangedHandler (const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin)
188+ void ClusterEvents::NextCheckChangedHandler (const Checkable::Ptr& checkable, const MessageOrigin::Ptr& origin, bool isFromOldClient )
187189{
188190 ApiListener::Ptr listener = ApiListener::GetInstance ();
189191
@@ -199,6 +201,7 @@ void ClusterEvents::NextCheckChangedHandler(const Checkable::Ptr& checkable, con
199201 if (service)
200202 params->Set (" service" , service->GetShortName ());
201203 params->Set (" next_check" , checkable->GetNextCheck ());
204+ params->Set (" origin_client_old" , isFromOldClient);
202205
203206 Dictionary::Ptr message = new Dictionary ();
204207 message->Set (" jsonrpc" , " 2.0" );
@@ -245,7 +248,25 @@ Value ClusterEvents::NextCheckChangedAPIHandler(const MessageOrigin::Ptr& origin
245248 if (nextCheck < Application::GetStartTime () + 60 )
246249 return Empty;
247250
248- checkable->SetNextCheck (params->Get (" next_check" ), false , origin);
251+ bool isOriginClientOld = params->Get (" origin_client_old" ).ToBool ();
252+ if (isOriginClientOld || endpoint->GetIcingaVersion () < 21600 ) { // TODO: Exact required version??
253+ // All older Icinga 2 versions trigger the `event::SetNextCheck` event endlessly, so we can't let the
254+ // `Checkable::OnNextCheckChanged` know about this change, as it would cause too much noise in Icinga DB
255+ // and the like. So, we just update the timestamp silently and manually call `Checkable::OnRescheduleCheck`
256+ // to inform the checker about this change.
257+ checkable->SetNextCheck (params->Get (" next_check" ), true , origin);
258+ Checkable::OnRescheduleCheck (checkable, nextCheck);
259+ // In case this message has to be relayed to other cluster nodes we directly call the `NextCheckChangedHandler`.
260+ // The `isOriginClientOld` flag is necessary e.g. in a 3-level cluster setup where a very old agent sends
261+ // the message to its satellite that then relays it to the master. The master then needs to know that this
262+ // event originates from an old node and thus has to be treated specially.
263+ NextCheckChangedHandler (checkable, origin, true );
264+ } else {
265+ // Peer is running the expected Icinga 2 version, so we can just do the normal flow.
266+ // The `Checkable::OnNextCheckChanged` signal will be emitted as usual and all listeners
267+ // will be informed about this change.
268+ checkable->SetNextCheck (params->Get (" next_check" ), false , origin);
269+ }
249270
250271 return Empty;
251272}
0 commit comments