Last active
July 28, 2020 20:55
-
-
Save eliphaslevy/41bc3cc8c3c127629ae71dc636b12d38 to your computer and use it in GitHub Desktop.
Create chart with multiple items from LLD
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
# coding:utf-8 | |
# vim:ts=8:sw=8:si:ci:ai | |
""" | |
Automatically create zabbix host graphs based on LLD items. | |
Recursively gets all hosts that have the template(s) and adds/updates | |
one or more charts on each host. | |
Add the ID of the template to masterTemplates dict, and add graph filters | |
that will match the items on the host to graphItems. | |
Unlike the perl script linked below, this script was built to generate one | |
chart for a bunch of specific items for a OLT port, rinse, repeat, for all | |
14 ports. Not that it cannot do a chart for all port items, but this is adds | |
too much interpositions/colors to be really useful, at least for me. | |
Inspiration: https://github.com/Eccenux/lld_all_graph | |
Depends on: https://pypi.org/project/zabbix-api/ | |
Why: why not? | |
The script reads a file named zabbix_api.ini containing: | |
[zabbix_api] | |
url=https://zabbix.url/zabbix/ | |
user=zabbix-api-user | |
password=c0a4bc75dd7ff08f83e2db77bbe0384e | |
""" | |
import os, sys, json, re, logging | |
from logging import info, warning, debug | |
from datetime import datetime as dt | |
from zabbix_api import ZabbixAPI | |
from ConfigParser import ConfigParser | |
mydir = os.path.dirname(os.path.realpath(__file__)) | |
myini = os.path.join(mydir,"zabbix_api.ini") | |
ini = ConfigParser() | |
ini.read(myini) | |
zbx_url = ini.get('zabbix_api','url') | |
zbx_usr = ini.get('zabbix_api','user') | |
zbx_pwd = ini.get('zabbix_api','password') | |
# templateId, templateName for searching | |
masterTemplates = { | |
18058: "Template Huawei Gpon Counter", | |
} | |
# templateId, graphName, itemName to search for, manual filter for item name in regex format (optional) | |
graphItems = { | |
18058: [ | |
#[ "Todas as portas - Contagem de clientes", "gpon.PortPonTotal", None, ], # this: too much items, unusable | |
], | |
} | |
# now customizing: adding single board graphs | |
for i in range(14): | |
graphItems[18058].append( | |
[ "Porta 0/%d - Contagem agregada de clientes" % i, "gpon.PortPonTotal", "gpon\.PortPonTotal\[\"0/%d/[0-9]+\"]" % i, ], | |
) | |
# max items are defined by max colors FIXME | |
colors = [ "5299AD", "5D549A", "87B457", "CF545E", "CDDA13", "5DAE99", "DD844C", "AE5C8A", "BD9F83", "6B9BD4", "B75F73", "646560", "335098", "5FBFDB", "D1CE85", "909090", "A16254", "E8678D", "62B55A", "A599AD", "6A5DD9", ] | |
DEBUG = os.environ.get('DEBUG','0') | |
assert DEBUG.isdigit() | |
DEBUG = int(DEBUG) | |
# ZAPI is too much verbose for me so I set separate level | |
if DEBUG == 0: | |
LOGLVL = logging.WARNING | |
ZAPI_LOGLVL = 0 | |
elif DEBUG == 1: | |
LOGLVL = logging.INFO | |
ZAPI_LOGLVL = logging.WARNING | |
else: | |
LOGLVL = logging.DEBUG | |
ZAPI_LOGLVL = logging.DEBUG | |
log = logging.basicConfig(level=LOGLVL) | |
zapi = ZabbixAPI(server=zbx_url, log_level=ZAPI_LOGLVL, timeout=180) | |
info('zapi logging in') | |
zapi.login(zbx_usr, zbx_pwd) | |
def searchTemplateHosts(filterHostName): | |
"""Search and returns this template's direcly assigned hosts and recurse on the template's children""" | |
info('zapi template get for %s' % filterHostName) | |
myTemplates = zapi.template.get({ | |
"filter": { "host": filterHostName, }, | |
"selectHosts": [ "hostid", "host", ], | |
"selectTemplates": [ "templateid", "host", ], | |
"output": [ "hosts", "templates", ], | |
}) | |
assert len(myTemplates) == 1 | |
myTemplate = myTemplates[0] | |
childHosts = myTemplate["hosts"] | |
childTemplates = myTemplate["templates"] | |
for template in childTemplates: | |
tplHosts = searchTemplateHosts(template["host"]) | |
childHosts += tplHosts | |
debug('got childHosts: %s' % childHosts) | |
return childHosts | |
def searchHostItems(filterHostId, searchItemName): | |
info('zapi item get for %s / %s' % (filterHostId, searchItemName)) | |
items = zapi.item.get({ | |
"hostids": filterHostId, | |
"search": { "key_": searchItemName, }, | |
"output": [ "hostid", "itemid", "key_", "lastvalue" ], | |
"sortfield": "itemid", | |
}) | |
debug('zapi items: %d' % len(items)) | |
return items | |
def searchHostGraphs(filterHostId, filterGraphName): | |
info('zapi graph get for %s / %s' % (filterHostId, filterGraphName)) | |
graphs = zapi.graph.get({ | |
"hostids": filterHostId, | |
"filter": { "name": filterGraphName, }, | |
"selectItems": [ "itemid", ], | |
"output": [ "name", ] | |
}) | |
debug('zapi graphs: %d' % len(graphs)) | |
return graphs | |
for templateId in masterTemplates: | |
info('locating hosts for templateId %d' % templateId) | |
hosts = searchTemplateHosts(masterTemplates[templateId]) | |
debug('got hosts: %s' % hosts) | |
for graphName, graphItemName, graphItemSearch in graphItems[templateId]: | |
info('adding/updating graph name: %s' % graphName) | |
for host in hosts: | |
debug('looking for items %s in host %s (item filter: %s)' % (graphItemName, host["hostid"], graphItemSearch)) | |
allItems = searchHostItems(host["hostid"], graphItemName) | |
if graphItemSearch: # regex filter | |
selectedItems = [] | |
re_items = re.compile(graphItemSearch) | |
for item in allItems: | |
if re_items.match(item["key_"]): | |
selectedItems.append(item) | |
else: | |
selectedItems = allItems | |
debug('items selected: %s' % selectedItems) | |
if len(selectedItems) > len(colors): # FIXME | |
warning('TOO MUCH ITEMS, IGNORING:\ngraph: %s\nhost: %s\nitem count: %d' % (graphName, host['host'], len(selectedItems))) | |
continue | |
if not selectedItems: | |
info('no items selected for this host') | |
continue | |
# add colors | |
i = 0 | |
for item in selectedItems: | |
item["color"] = colors[i] | |
i+=1 | |
graph = searchHostGraphs(host["hostid"], graphName) | |
if graph: | |
graph = graph[0] # one graph, but comes as a list | |
setCurr = set([item["itemid"] for item in graph["items"]]) | |
setSelected = set([item["itemid"] for item in selectedItems]) | |
if setCurr == setSelected: | |
debug("graph up to date!") | |
continue | |
debug("updating graph: %s" % graph) | |
zapi.graph.update({ | |
"graphid": graph["graphid"], | |
"gitems": selectedItems, | |
}) | |
else: | |
debug("creating graph") | |
zapi.graph.create({ | |
"hostid": host["hostid"], | |
"name": graphName, | |
"gitems": selectedItems, | |
}) | |
zapi.logout() | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment