Skip to content

Instantly share code, notes, and snippets.

@q1x
Last active November 22, 2017 14:03
Show Gist options
  • Save q1x/f18d9758de6dfa21f290898a0887f6c6 to your computer and use it in GitHub Desktop.
Save q1x/f18d9758de6dfa21f290898a0887f6c6 to your computer and use it in GitHub Desktop.
Zabbix dependencies on inventory type and location tag
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# import needed modules.
# pyzabbix is needed, see https://github.com/lukecyca/pyzabbix
#
import argparse
import ConfigParser
import os
import os.path
import time
import sys
import logging
import distutils.util
from pprint import pprint
from pyzabbix import ZabbixAPI
logger = logging.getLogger(__name__)
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.WARNING)
# define config helper function
def ConfigSectionMap(section):
dict1 = {}
options = Config.options(section)
for option in options:
try:
dict1[option] = Config.get(section, option)
if dict1[option] == -1:
DebugPrint("skip: %s" % option)
except:
print("exception on %s!" % option)
dict1[option] = None
return dict1
def PrintError(error):
sys.exit(error)
def hostfilter(hosts,field,value):
newlist=[]
for host in hosts:
if host['inventory'][field].lower() == value.lower():
newlist.append(host)
return newlist
# set default vars
defconf = os.getenv("HOME") + "/.zbx.conf"
username = ""
password = ""
api = ""
noverify = ""
# Define commandline arguments
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description='Creates Zabbix trigger dependencies for on-site equipment to the local default gateway, LLD triggers will be ignored.', epilog="""
This program can use .ini style configuration files to retrieve the needed API connection information.
To use this type of storage, create a conf file (the default is $HOME/.zbx.conf) that contains at least the [Zabbix API] section and any of the other parameters:
[Zabbix API]
username=johndoe
password=verysecretpassword
api=https://zabbix.mycompany.com/path/to/zabbix/frontend/
no_verify=true
""")
parser.add_argument('-u', '--username', help='User for the Zabbix api')
parser.add_argument('-p', '--password', help='Password for the Zabbix api user')
parser.add_argument('-a', '--api', help='Zabbix API URL')
parser.add_argument('--no-verify', help='Disables certificate validation when using a secure connection',action='store_true')
parser.add_argument('-c','--config', help='Config file location (defaults to $HOME/.zbx.conf)')
parser.add_argument('-v', '--verbose', help='Enables verbose output.',action='store_true')
parser.add_argument('-d', '--debug', help='Enables debug output.',action='store_true')
parser.add_argument('-t', '--trigger', help='Trigger description of the gateway reachability check',required=True)
parser.add_argument('--gwtype', help='Value of the inventory "type" field for gateway devices, default type is "router"',default='router')
parser.add_argument('--types', help='Device types that need to be made dependent of the gateway device, default types are "router", "switch", "access-point", "camera" and "phone"',nargs='+',default=['router','switch', 'access-point', 'camera', 'phone'])
args = parser.parse_args()
# load config module
Config = ConfigParser.ConfigParser()
Config
# if configuration argument is set, test the config file
if args.config:
if os.path.isfile(args.config) and os.access(args.config, os.R_OK):
Config.read(args.config)
# if not set, try default config file
else:
if os.path.isfile(defconf) and os.access(defconf, os.R_OK):
Config.read(defconf)
# try to load available settings from config file
try:
username=ConfigSectionMap("Zabbix API")['username']
password=ConfigSectionMap("Zabbix API")['password']
api=ConfigSectionMap("Zabbix API")['api']
noverify=bool(distutils.util.strtobool(ConfigSectionMap("Zabbix API")["no_verify"]))
except:
pass
# override settings if they are provided as arguments
if args.username:
username = args.username
if args.password:
password = args.password
if args.api:
api = args.api
if args.no_verify:
noverify = args.no_verify
# test for needed params
if not username:
sys.exit("Error: API User not set")
if not password:
sys.exit("Error: API Password not set")
if not api:
sys.exit("Error: API URL is not set")
if args.verbose:
logger.setLevel(logging.INFO)
if args.debug:
logger.setLevel(logging.DEBUG)
gateway_type = args.gwtype
devicetypes = args.types
# Setup Zabbix API connection
zapi = ZabbixAPI(api)
if noverify is True:
zapi.session.verify = False
# Login to the Zabbix API
zapi.login(username, password)
zapi.timeout=900
##################################
# Start actual API logic
##################################
# Zabbix version
zversion=zapi.apiinfo.version()
logger.info("Zabbix API version: %s", str(zversion))
# Fetch all hosts
hosts = zapi.host.get(**{"output" : ["host","name","inventory"],
"selectInventory" : ['type','tag','contract_number'],
"withInventory" : True
})
# Find gateway devices
gateways = hostfilter(hosts,'type',gateway_type)
if gateways:
for gateway in gateways:
logger.debug("Found gateway %s (%s)", gateway['host'], gateway['name'])
master = zapi.trigger.get(**{"output" : ["description"],
"filter":{'hostid': gateway['hostid'],'description': args.trigger}
})
if master:
master = master[0]
logger.debug(" - Gateway trigger has id %d", int(master['triggerid']))
if gateway['inventory']['tag'].strip():
devices = hostfilter(hosts,'tag',gateway['inventory']['tag'].strip())
for device in devices:
updated = 0
if device['inventory']['type'].lower() in devicetypes:
devmaster = zapi.trigger.get(**{"output" : ["description"],
"filter":{'hostid': device['hostid'],'description': args.trigger}
})
if devmaster:
devmaster = devmaster[0]
logger.debug(" |- Found dependent device %s (%s), main trigger is %d", str(device['host']), str(device['name']), int(devmaster['triggerid']))
slaves = zapi.trigger.get(**{"output" : ["description"],
"selectDependencies": 'extend',
"filter":{'hostid': device['hostid'],'flags': "0"}
})
for slave in slaves:
if slave['triggerid'] != master['triggerid']:
if not slave['dependencies']:
if slave['triggerid'] == devmaster['triggerid']:
try:
zapi.trigger.adddependencies(**{'triggerid': slave['triggerid'],'dependsOnTriggerid': master['triggerid']})
logger.info(" ||- Trigger %d ('%s') was made dependent of gateway trigger %d", int(slave['triggerid']),str(slave['description']), int(master['triggerid']))
updated = updated+1
except:
logger.error("*** Could not link %d ('%s') as a dependency to trigger %d", int(slave['triggerid']),str(slave['description']), int(master['triggerid']))
else:
try:
zapi.trigger.adddependencies(**{'triggerid': slave['triggerid'],'dependsOnTriggerid': devmaster['triggerid']})
logger.info(" ||- Trigger %d ('%s') was made dependent of device trigger %d", int(slave['triggerid']),str(slave['description']), int(devmaster['triggerid']))
updated = updated+1
except:
logger.error("*** Could not link %d ('%s') as a dependency to trigger %d", int(slave['triggerid']),str(slave['description']), int(devmaster['triggerid']))
if updated == 0:
logger.debug(" ||- No trigger dependencies were updated on this host")
else:
logger.debug(" |- Ignoring device %s (%s) as it doesn't match filter", str(device['host']), str(device['name']))
else:
logger.info("*** No tag found on %s, can't find related devices.",str(gateway['host']))
else:
logger.info("*** Could not find trigger '%s' on %s",str(args.trigger),str(gateway['host']))
else:
logger.info("*** Could not find gateway devices of type '%s'",str(args.gwtype))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment