Skip to content

Commit

Permalink
Fix downtime and recheck functions for CheckMK 2.3 (#1047)
Browse files Browse the repository at this point in the history
* Add function _get_csrf_token to Multisite.py

* Add function _omd_get_version to Multisite.py

* Add function _omd_set_recheck to Multisite.py

* Add function _omd_set_downtime to Multisite.py

* Add function overrides for Checkmk 2.3+

---------

Co-authored-by: Jinho Kim <[email protected]>
  • Loading branch information
jkim2492 and Jinho Kim authored Jul 27, 2024
1 parent 9eb63ef commit f9e5441
Showing 1 changed file with 91 additions and 0 deletions.
91 changes: 91 additions & 0 deletions Nagstamon/Servers/Multisite.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import time
import copy
import html
from datetime import datetime
from zoneinfo import ZoneInfo

from Nagstamon.Objects import (GenericHost,
GenericService,
Expand Down Expand Up @@ -103,6 +105,10 @@ def init_HTTP(self):
'api_svcprob_act': self.monitor_url + '/view.py?_transid=-1&_do_actions=yes&_do_confirm=Yes!&view_name=svcproblems&filled_in=actions&lang=',
'human_events': self.monitor_url + '/index.py?%s' %
urllib.parse.urlencode({'start_url': 'view.py?view_name=events'}),
'omd_host_downtime': self.monitor_url + '/api/1.0/domain-types/downtime/collections/host',
'omd_svc_downtime': self.monitor_url + '/api/1.0/domain-types/downtime/collections/service',
'recheck': self.monitor_url + '/ajax_reschedule.py?_ajaxid=0',
'omd_version': self.monitor_url + '/api/1.0/version',
'transid': self.monitor_url + '/view.py?actions=yes&filled_in=actions&host=$HOST$&service=$SERVICE$&view_name=service'
}

Expand All @@ -114,6 +120,12 @@ def init_HTTP(self):
'PEND': 'PENDING',
}

# Function overrides for Checkmk 2.3+
version = self._omd_get_version()
if version >= [2, 3]:
self._set_downtime = self._omd_set_downtime
self._set_recheck = self._omd_set_recheck

if self.CookieAuth and not self.refresh_authentication:
# get cookie to access Checkmk web interface
if 'cookies' in dir(self.session):
Expand Down Expand Up @@ -526,6 +538,47 @@ def _set_downtime(self, host, service, author, comment, fixed, start_time, end_t
debug='Invalid start/end date/time given')


def _omd_set_downtime(self, host, service, author, comment, fixed, start_time, end_time, hours, minutes):
"""
_set_downtime function for Checkmk version 2.3+
"""
try:
# Headers required for Checkmk API
headers = {
"Authorization": f"Bearer {self.username} {self.password}",
"Content-Type": "application/json",
"Accept": "application/json",
}

# Only timezone aware dates are allowed
iso_start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M").replace(tzinfo=ZoneInfo('localtime')).isoformat()
iso_end_time = datetime.strptime(end_time, "%Y-%m-%d %H:%M").replace(tzinfo=ZoneInfo('localtime')).isoformat()
# Set parameters for host downtimes
url = self.urls["omd_host_downtime"]
params = {
"start_time": iso_start_time,
"end_time": iso_end_time,
"comment": author == self.username and comment or "%s: %s" % (author, comment),
"downtime_type": "host",
"host_name": host,
}

# Downtime type is "flexible" if "duration" is set
if fixed == 0:
params["duration"] = hours * 60 + minutes
# Parameter overrides for service downtimes
if service:
url = self.urls["omd_svc_downtime"]
params["downtime_type"] = "service"
params["service_descriptions"] = [service]

self.session.post(url, headers=headers, json=params)
except:
if conf.debug_mode:
self.Debug(server=self.get_name(), host=host,
debug='Invalid start/end date/time given')


def _set_acknowledge(self, host, service, author, comment, sticky, notify, persistent, all_services=None):
p = {
'_acknowledge': 'Acknowledge',
Expand All @@ -550,6 +603,21 @@ def _set_recheck(self, host, service):
self._action(self.hosts[host].site, host, service, p)


def _omd_set_recheck(self, host, service):
"""
_set_recheck function for Checkmk version 2.3+
"""
csrf_token = self._get_csrf_token(host, service)
data = {
"site": self.hosts[host].site,
"host": host,
"service": service,
"wait_svc": service,
"csrf_token": csrf_token,
}
self.FetchURL(self.urls["recheck"], cgi_data=data)


def recheck_all(self):
"""
special method for Checkmk as there is one URL for rescheduling all problems to be checked
Expand All @@ -574,3 +642,26 @@ def _get_transid(self, host, service):
transid = self.FetchURL(self.urls['transid'].replace('$HOST$', host).replace('$SERVICE$', service.replace(' ', '+')),
'obj').result.find(attrs={'name' : '_transid'})['value']
return transid


def _get_csrf_token(self, host, service):
"""
get csrf token for the session
"""
# since Checkmk 2.0 it seems to be a problem if service is empty so fill it with a definitively existing one
if not service:
service = "PING"
csrf_token = self.FetchURL(self.urls["transid"].replace("$HOST$", host).replace("$SERVICE$", service.replace(" ", "+")), "obj").result.find(attrs={"name": "csrf_token"})["value"]
return csrf_token


def _omd_get_version(self):
"""
get version of OMD Checkmk as [major_version, minor_version]
"""
try:
version = [int(v) for v in self.session.get(self.urls["omd_version"]).json()["versions"]["checkmk"].split(".")[:2]]
# If /version api is not supported, return the lowest non-negative pair
except:
version = [0, 0]
return version

4 comments on commit f9e5441

@HenriWahl
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jkim2492,

After running Nagstamon with your fixes for a while we found some problem running it on macOS: after the machine was in standby and waking up again, the Checkmk server connection was hanging. When trying to reconfigue it in settings dialog, Nagstamon freezes completely. Do you have any idea why this could happen?

Best regards
Henri

@jkim2492
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @HenriWahl,

I can't think of anything particular that would affect the connections after waking up. However, here are a few things that are done differently in this PR compared to the existing one.

  • Using self.session.post instead of self.FetchURL inside _omd_set_downtime
    • This change should not have any effect unless the CheckMK servers are of version 2.3+
    • I had trouble submitting json data using self.FetchURL and cgi_data parameter, so I opted to use self.session.post instead of modifying FetchURLs
  • Using self.session.get instead of self.FetchURL inside _omd_get_version
    • This change affects all versions of CheckMK
    • This was done to retrieve the json response from an api endpoint
  • Dependency on zoneinfo
    • This change affects all versions of CheckMK
    • zoneinfo module is included by default with Python 3.9+, but might cause problems if Python version is lower StackExchange post

Was the problem specific to macOS or was it also reproducible on Linux as well? I haven't noticed such problems on Ubuntu 22.04 yet.

@HenriWahl
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jkim2492 thanks for your reply. Thanks for the hints. I will try to use the fetchURL method.
We only had this on macOS.

@HenriWahl
Copy link
Owner

@HenriWahl HenriWahl commented on f9e5441 Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your hint was very useful. I applied fetch_url() instead of session.post() and session.get() and now it works without freezing. 👍

Please sign in to comment.