Automatic setting the value of attribute “parents” of Host (with livestatus, wato-api und vsphere-plugin)
Hello folks,
I wanted to have an automatic function to set the curent parents value of vmware machines in the wato host configuration. Therfore I made a script to do it, that is periodically executed via crond of the cmk site user. Details below, have fun with it.
Regards
Stefan
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__doc__ = u"""
Environment: python 2.7
Need to make it run with python 3!
Target:
Set the value for attribute parents of each host,
that is hosted on a esx server (vmware).
Prerequisites:
Working piggyback function - > https://checkmk.de/cms_monitoring_vmware.html
HTTPS connection to Check_MK site
SSL certificates of of the ca embedded system wide, i.e. under ubuntu:
https://askubuntu.com/questions/645818/how-to-install-certificates-for-command-line
Simple description of the script:
Get all Hosts via check_MK Livestatus, then fetch status detail of monitoring
service ESX Hostsystem. Finally set via Check_MK wato API the host attribute parent,
that is different to the existing value.
Get it wun periodically via crond of check_mk site user, example for executing it each hour:
0 */1 * * * python /omd/sites/sitename/customScripts/LQgetHost-APIsetParent2.py 2>1&
"""
import json
import os
import requests
import socket
import time
__author__ = "Stefan Senftleben"
__version__ = "1.0.1"
__credits__ = ["Tribe29, code samples from check_mk website theme livestatus"]
__email__ = "stefan.senftleben@posteo.de"
__status__ = "Production"
class Livestatus:
def __init__(self):
self.address = "%s/tmp/run/live" % os.getenv("OMD_ROOT")
"""
for local/remote sites: TCP address/port for Livestatus socket
self.address = ("localhost", 6557)
"""
self.family = socket.AF_INET if type(self.address) == tuple else socket.AF_UNIX
self.sock = socket.socket(self.family, socket.SOCK_STREAM)
def getdata(self, *largs):
requestdata = largs[0]
"""Connect to livestatus unix socket and request data. """
self.sock.connect(self.address)
self.sock.sendall('{}'.format(requestdata))
self.sock.shutdown(socket.SHUT_WR)
self.chunks = []
while len(self.chunks) == 0 or self.chunks[-1] != "":
self.chunks.append(self.sock.recv(4096))
self.sock.close()
self.reply = "".join(self.chunks)
return self.reply
class Watoapi:
def __init__(self):
"""
class to some functions of the check_mk wato api.
self.params defines class variables. Edit to your needs -> username, password
Define in WATO an web api automation user:
https://checkmk.de/cms_wato_user.html#automation
"""
self.preparams = [
('_username', 'username'),
('_secret', 'password'),
]
self.sitename = '{}'.format(os.getenv("OMD_SITE"))
self.fqdn = '{}'.format(socket.getfqdn())
self.url = 'https://{}/{}/check_mk/webapi.py'.format(self.fqdn, self.sitename)
"""When connecting to a self signed https website, set here the system wide
ca certificates location. """
self.capath = '/etc/ssl/certs/ca-certificates.crt'
def getdata(self, *largs):
"""
Building some python dictionarys in form of the needed json request.
Parsing it to json format and do a request to the wato api.
"""
valuehostname = largs[0]
valueget = largs[1]
self.preparams.append(('output_format', 'json'))
self.preparams.append(('request_format', 'python'))
self.preparams.append(('action', 'get_host'))
self.params = tuple(self.preparams)
self.data = {}
self.dicthostname = {}
self.dicthostname["hostname"] = '{}'.format(valuehostname)
self.dataset = {}
self.dataset.update(self.dicthostname)
self.data['request'] = json.dumps(self.dataset)
self.response = requests.post(self.url, params=self.params, data=self.data, verify=self.capath)
self.loaded_jsondata = (json.loads(self.response.text))
# print(self.loaded_jsondata)
if valueget in self.loaded_jsondata['result']['attributes']:
self.watovalue = self.loaded_jsondata['result']['attributes'][valueget]
if valueget in self.loaded_jsondata['result']:
self.watovalue = self.loaded_jsondata['result'][valueget]
return self.watovalue
def changedata(self, *largs):
"""Method to change values of a host parameter"""
valuehostname = largs[0]
valueesxhost = largs[1]
self.preparams.append(('action', 'edit_host'))
self.params = tuple(self.preparams)
self.data = {}
self.dicthostname = {}
self.dictesxhost = {}
self.dictattrib = {}
self.dicthostname["hostname"] = '{}'.format(valuehostname)
self.dictesxhost["parents"] = ['{}'.format(valueesxhost)]
self.dictattrib["attributes"] = self.dictesxhost
self.dataset = {}
self.dataset.update(self.dictattrib)
self.dataset.update(self.dicthostname)
self.data['request'] = json.dumps(self.dataset)
self.response = requests.post(self.url, params=self.params, data=self.data, verify=self.capath)
self.loaded_jsondata = (json.loads(self.response.text))
# print(self.loaded_jsondata)
def activatechanges(self, *largs):
"""Method to activate changes in wato"""
valuesitename = largs[0]
valueforeign = largs[1]
valuecomment = largs[2]
self.preparams.append(('action', 'activate_changes'))
self.params = tuple(self.preparams)
self.data = {}
self.dictsitename = {}
self.dictforeignchanges = {}
self.dictcomment = {}
self.dictsitename["sites"] = ['{}'.format(valuesitename)]
self.dictforeignchanges["allow_foreign_changes"] = '{}'.format(valueforeign)
self.dictcomment["comment"] = '{}'.format(valuecomment)
self.dataset = {}
self.dataset.update(self.dictsitename)
self.dataset.update(self.dictforeignchanges)
self.dataset.update(self.dictcomment)
self.data['request'] = json.dumps(self.dataset)
self.response = requests.post(self.url, params=self.params, data=self.data, verify=self.capath)
self.loaded_jsondata = (json.loads(self.response.text))
print(self.loaded_jsondata)
def __exit__(self):
return
def main():
hostrequest = "GET hosts\nColumns: host_name\nOutputFormat: json\n"
cmklivestatus = Livestatus()
reply = cmklivestatus.getdata(hostrequest)
# print(json.loads(reply))
for element in json.loads(reply):
hostname = "".join(element)
wato = Watoapi()
watovalue = wato.getdata("{}".format(hostname), 'path')
servicerequest = "GET services\nColumns: host_name description plugin_output\nFilter: host_name = {}\nFilter: description = ESX Hostsystem\nOutputFormat: json\n".format(hostname)
# print('{}'.format(servicerequest))
cmklivestatus = Livestatus()
reply2 = cmklivestatus.getdata(servicerequest)
if len(reply2) == 3:
print(' - Host {} seems to be no virtual machine on ESX.'.format(hostname))
else:
for item in json.loads(reply2):
esxhost = ''
esxhost = "".join(item).split()[-1]
if esxhost != '':
if esxhost not in ''.join(wato.getdata(hostname, 'parents')):
print(' + Host {} is running on {}.'.format(hostname, esxhost))
wato.changedata(hostname, esxhost)
else:
print('= Host {}. The value of the attribut {} equals to the existing one.'.format(hostname, 'parents'))
# activate changes
wato = Watoapi()
wato.activatechanges('{}'.format(os.getenv("OMD_SITE")), 1, 'Change by a custom script -> crontab -l')
if __name__ == '__main__':
main()