diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6bd89eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.py[co] +.idea +*.swp +*~ +build +dist +*.egg-info diff --git a/README.md b/README.md new file mode 100644 index 0000000..91e8076 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +python zabbix api - https://github.com/gescheit/scripts/tree/master/zabbix + diff --git a/checks/README.md b/checks/README.md new file mode 100644 index 0000000..a6cf552 --- /dev/null +++ b/checks/README.md @@ -0,0 +1,4 @@ +functions.sh - functions for locking and caching +disksmart.sh - check SMART of all disks in system +- Work under FreeBSD and linux +- Use caching and locking diff --git a/checks/disksmart.sh b/checks/disksmart.sh new file mode 100755 index 0000000..39fcdb5 --- /dev/null +++ b/checks/disksmart.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# check SMART of all disks in system +BASENAME=$(dirname $0) +. ${BASENAME}/functions.sh +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/zabbix/bin +RES="" +ME="disksmart_check" +TIMEOUT=600 +ERRLOG_COUNT_THRESHOLD=100 +if [ `which smartctl >/dev/null; echo $?` -ne 0 ]; then + echo "no smartctl" + exit 1 +fi + +checkSmartExitStatus() +{ + STATUS=$1 +#if [ $(($STATUS & 1<<0)) -gt 0 ]; then echo "Command line did not parse"; fi +# if [ $(($STATUS & 1<<1)) -gt 0 ]; then echo "Device open failed"; fi + if [ $(($STATUS & 1<<2)) -gt 0 ]; then echo "Some command to the disk failed, or there was a checksum error in a SMART data structure"; fi + if [ $(($STATUS & 1<<3)) -gt 0 ]; then echo "DISK FAILING"; fi + if [ $(($STATUS & 1<<4)) -gt 0 ]; then echo "found prefail Attr <= threshold"; fi +# if [ $(($STATUS & 1<<5)) -gt 0 ]; then echo "Some attributes have been <= threshold at some time in the past"; fi + if [ $(($STATUS & 1<<7)) -gt 0 ]; then echo "self-test log contains records of errors"; fi +} + + +CACHE=`getFromCache "$ME" $TIMEOUT` +if [ -z "$CACHE" ]; then + + lockf ${ME} 15 + [ $? -eq 0 ] || exit # unable to get lockfile + DISKS="`sudo smartctl --scan-open`" + if [ $? -ne 0 ]; then # old smartctl + if [ `uname` = "Linux" ]; then + DISKS="`ls -1 /dev/ | grep -E '^sd[a-z]$' 2>/dev/null | sed 's|^|/dev/|' | sed 's|$|,|'`" + elif [ `uname` = "FreeBSD" ]; then + DISKS="`ls -1 /dev/ | grep -E '^(ad[0-9]+|da[0-9]+|ada[0-9]+)$' 2>/dev/null | sed 's|^|/dev/|' | sed 's|$|,|'`" + fi + else + DISKS="`echo \"$DISKS\" | sed 's|\ [\#\[].*|,|'`" + fi + OIFS="${IFS}" + NIFS=$"," + + IFS="${NIFS}" + + for DISK in ${DISKS}; do + IFS='${OIFS}' + if [ -z "$DISK" ]; then + continue + fi + DISK=${DISK%%\#*} + DISK=${DISK%-*} + DISK=`echo $DISK| xargs` + sudo smartctl -q silent -a $DISK 2>/dev/null + SMARTSTATUS=$? + ERRLOG_COUNT=0 + if [ $SMARTSTATUS -ne 0 ]; then + SMARTSTR=`checkSmartExitStatus \$SMARTSTATUS` + if [ $((${SMARTSTATUS} & 1<<2)) -gt 0 ]; then + sudo smartctl -a $DISK 2>/dev/null | grep -qE '(Vendor.*VMware|Vendor.*SUPER|Device.*DELL|device.*CD/DVD|Device.*processor|Device.*enclosure|Product.*Array|Virtual.*disk)' + if [ $? -eq 0 ]; then + continue + fi + sudo smartctl -i -A -l error -l selftest $DISK 2>/dev/null 1>/dev/null # try without health check + if [ $? -eq 0 ]; then + continue + fi + fi + if [ $((${SMARTSTATUS} & 1<<6)) -gt 0 ]; then + ERRLOG_COUNT="`sudo smartctl -l error $DISK 2>/dev/null | grep Error\ Count`" + ERRLOG_COUNT=${ERRLOG_COUNT##*: } + ERRLOG_COUNT=${ERRLOG_COUNT%% *} + fi + if [ -n "${SMARTSTR}" -o \( ${ERRLOG_COUNT} -gt ${ERRLOG_COUNT_THRESHOLD} \) ]; then + SMARTSTR="ton of errors in log" + RES="${RES}${DISK} ${SMARTSTR} +" + fi + fi + IFS="${NIFS}" + done + IFS="${OIFS}" + if [ -z "$RES" ]; then + RES="OK" + fi + + writeToCache "$ME" "$RES" + unlockf $ME +else + RES=${CACHE} +fi + +echo "$RES" | tr -s "\n\n" "\n" diff --git a/checks/functions.sh b/checks/functions.sh new file mode 100644 index 0000000..dc3d4b7 --- /dev/null +++ b/checks/functions.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +LOCKDIR="/tmp" +CACHEDIR=$LOCKDIR + +getFromCache() +{ + CACHEFILE="$CACHEDIR/$1.cache" + TIMEOUT="$2" + CURRENTTIME="`date +%s`" + if [ -s ${CACHEFILE} ]; then + CACHEDATA=`cat ${CACHEFILE}` + OLDDATATIME=${CACHEDATA%%,*} + OLDDATA=${CACHEDATA#*,} + + if [ $OLDDATATIME -gt $((CURRENTTIME-TIMEOUT)) ]; then + echo "$OLDDATA" + return 0 + else + return 1 + fi + fi +} + +writeToCache() +{ + CACHEFILE="$CACHEDIR/$1.cache" + DATA="$2" + CURRENTTIME="`date +%s`" + echo "$CURRENTTIME,$DATA" > "$CACHEFILE" + [ "`id -u -n`" = "zabbix" ] || chown zabbix "$CACHEFILE" + return 0 +} + +lockf() +{ + LOCKFILE="$LOCKDIR/$1.lock" + if [ -n "$2" ]; then + RETRY=$2 + else + RETRY=1 + fi + while [ $RETRY -gt 0 ]; do + RETRY=`expr $RETRY - 1` + if (set -o noclobber; echo "$$" > "$LOCKFILE") 2> /dev/null; then + trap 'rm -f "$LOCKFILE"; exit $?' INT TERM EXIT + return 0 + fi + if [ -f "$LOCKFILE" ]; then + kill -0 `cat "$LOCKFILE"` 1>/dev/null 2>&1 + if [ $? -ne 0 ]; then + rm -f "$LOCKFILE" + if [ $? -ne 0 ]; then + echo "unable to remove lock" + return 1 + fi + fi + fi + sleep 1 + done + echo "Locking failed. Held by $(cat $LOCKFILE)" + return 1 +} + +unlockf() +{ + LOCKFILE="$LOCKDIR/$1.lock" + rm -f "$LOCKFILE" + trap - INT TERM EXIT + return 0 +} diff --git a/cobbler/cobbler_mass_update.py b/cobbler/cobbler_mass_update.py deleted file mode 100755 index ecb2f30..0000000 --- a/cobbler/cobbler_mass_update.py +++ /dev/null @@ -1,237 +0,0 @@ -#!/bin/env python - -# This script is intended to allow a fast way to mass-update cobbler's -# mgmt_classes. - -import optparse -import xmlrpclib -import sys - -from copy import deepcopy -from getpass import getpass - - -def get_options(): - """ command-line options """ - - usage = "usage: %prog [options]" - OptionParser = optparse.OptionParser - parser = OptionParser(usage) - - parser.add_option("-a", "--add", action="store", type="string", \ - dest="additions", help="Add or insert these classes (space delimited) into all systems or profiles") - parser.add_option("-d", "--delete", action="store", type="string", \ - dest="deletes", help="delete these classes (space delimited) from all systems or profiles") - parser.add_option("--host", action="store", type="string", \ - dest="host", help="Change only a single host.") - parser.add_option("-p", "--password", action="store", type="string", \ - dest="password", help="Password to log into cobbler.") - parser.add_option("--profile", action="store", type="string", \ - dest="profile", help="Change only a single profile.") - parser.add_option("--newname", action="store", type="string", \ - dest="newname", help="New name for class specified by --rename") - parser.add_option("-r", "--rename", action="store", type="string", \ - dest="rename", help="Rename a single class. Requires --newname") - parser.add_option("-s", "--server", action="store", type="string", \ - dest="server", help="Cobbler server.") - parser.add_option("-t", "--test", action="store_true", dest="test_only", \ - help="Test changes. Show what would change. (Doesn't require auth)") - parser.add_option("-u", "--username", action="store", type="string", \ - dest="username", help="Username to log into cobbler.") - parser.add_option("-v", "--verbose", action="store_true", dest="verbose", \ - help="Increase verbosity. Print additional information.") - - options, args = parser.parse_args() - - # XXX: ugh. brute force method of showing the help text if no options are set - if len(args) < 1 and not options.additions \ - and not options.deletes and not options.host \ - and not options.password and not options.profile \ - and not options.newname and not options.rename \ - and not options.server and not options.test_only \ - and not options.username and not options.verbose: - parser.print_help() - sys.exit(-1) - - if options.rename and not options.newname: - print "Rename requires --newname" - sys.exit(-1) - - if not options.test_only: - sys.stderr.write("Warning: username and password are required for" + \ - "making changes to Cobbler.\n") - if not options.username: - options.username = raw_input('Username: ') - if not options.password: - options.password = getpass() - - if not options.server: - options.server = "localhost" - - return options, args - -def __pre(obj): - if options.test_only or options.verbose: - print "Name: %s" % obj['name'] - print "Current value: %s" % obj['mgmt_classes'] - return check_inherited(obj) - -def __post(obj): - if options.test_only or options.verbose: - print "New value: %s" % obj['mgmt_classes'] - -def extend_classes(obj): - if __pre(obj): - classes = options.additions.split(" ") - obj['mgmt_classes'].extend(classes) - __post(obj) - -def rename_classes(obj): - if __pre(obj): - if options.rename in obj['mgmt_classes']: - obj['mgmt_classes'].remove(options.rename) - obj['mgmt_classes'].append(options.newname) - __post(obj) - -def delete_classes(obj): - if __pre(obj): - classes = options.deletes.split(" ") - for clazz in classes: - if clazz in obj['mgmt_classes']: - obj['mgmt_classes'].remove(clazz) - __post(obj) - -def check_inherited(obj): - if "<>" in obj['mgmt_classes']: - sys.stderr.write("Warning: unable to make changes to %s. Inherited.\n" \ - % obj['name']) - return False - return True - -if __name__ == "__main__": - options, args = get_options() - - url = "http://%s/cobbler_api" % options.server - - try: - server = xmlrpclib.Server(url) - server.ping() - except: - traceback.print_exc() - sys.exit(-1) - - if not options.test_only: - token = server.login(options.username,options.password) - - if not token: - sys.stderr.write("Error obtaining auth token.\n") - sys.exit(-1) - - if options.verbose: - print "Token: " + token - - # Profiles loop. - if not options.host: - profiles = server.get_profiles() - for profile in profiles: - orig_profile = deepcopy(profile) - - if not options.test_only: - handle = server.get_profile_handle(profile['name'],token) - - if not handle: - sys.stderr.write("Error obtaining handle on %s.\n" \ - % profile['name']) - sys.exit(-1) - - if options.verbose: - print "Handle: " + handle - - if options.additions: - if options.profile and options.profile not in profile['name']: - continue - else: - extend_classes(profile) - elif options.rename and options.newname: - if options.profile and options.profile not in profile['name']: - continue - else: - rename_classes(profile) - elif options.deletes: - if options.profile and options.profile not in profile['name']: - continue - else: - delete_classes(profile) - - if orig_profile['mgmt_classes'] != profile['mgmt_classes'] and not options.test_only: - try: - ret = server.modify_profile(handle, "mgmt_classes", \ - profile['mgmt_classes'], token) - - if options.verbose: - print "Modify result: " + str(ret) - - ret = server.save_profile(handle, token) - - if options.verbose: - print "Save result: " + str(ret) - except xmlrpclib.Fault as err: - sys.stderr.write("Error: %s\n" % err.faultString) - - # add some white-spacing between each spin through the loop. - if options.verbose or options.test_only: - print "" - - # Systems loop. - if not options.profile: - systems = server.get_systems() - for system in systems: - orig_system = deepcopy(system) - - if not options.test_only: - handle = server.get_system_handle(system['name'],token) - - if not handle: - sys.stderr.write("Error obtaining handle on %s.\n" \ - % profile['name']) - sys.exit(-1) - - if options.verbose: - print "Handle: " + handle - - if options.additions: - if options.host and options.host not in system['name']: - continue - else: - extend_classes(system) - elif options.rename and options.newname: - if options.host and options.host not in system['name']: - continue - else: - rename_classes(system) - elif options.deletes: - if options.host and options.host not in system['name']: - continue - else: - delete_classes(system) - - if orig_system['mgmt_classes'] != system['mgmt_classes'] and not options.test_only: - try: - ret = server.modify_system(handle, "mgmt_classes", \ - system['mgmt_classes'], token) - - if options.verbose: - print "Modify result: " + str(ret) - - ret = server.save_system(handle, token) - - if options.verbose: - print "Save result: " + str(ret) - except xmlrpclib.Fault as err: - sys.stderr.write("Error: %s\n" % err.faultString) - - # add some white-spacing between each spin through the loop. - if options.verbose or options.test_only: - print "" - - diff --git a/ldap/parse_sudoers.py b/ldap/parse_sudoers.py deleted file mode 100755 index e402aa2..0000000 --- a/ldap/parse_sudoers.py +++ /dev/null @@ -1,537 +0,0 @@ -#!/usr/bin/env python -# -# This program parses a sudoers file and can be used to test who has -# what access -# -# Author: Joel Heenan 30/09/2008 -# Author: Brett Lentz 30/09/2009 - added ldif support -# -# This software may be freely redistributed under the terms of the GNU -# general public license. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -import re,grp,socket,sys,os,commands -from optparse import OptionParser - -#TODO: fix ldif output: -# on the same host, if there are different runas users across multiple commands, -# it's output into a single DN. - -try: - import netgroup - netgroupSupport = True -except: - netgroupSupport = False - -class SudoCmnd: - def __init__(self,runas,passwd,command,sp,comment="",options=None): - self.runas = runas - self.passwd = passwd - self.command = command - self.sp = sp - self.comment = comment - self.options = options - - def __repr__(self): - commands = [] - for cmndAlias in self.sp.cmndAliases: - if(cmndAlias == self.command): - commands = self.sp.cmndAliases[cmndAlias] - - if(self.passwd): - str = "(%s) %s\n" % (self.runas, self.command) - else: - str = "(%s) NOPASSWD: %s" % (self.runas, self.command) - for command in commands: - str += "\t%s\n" % command - return str - - def matchCommand(self,command): - if(command == self.command): - return True - for cmndAlias in self.sp.cmndAliases: - if(cmndAlias == self.command): - return self.sp.matchCmndAlias(self.sp.cmndAliases[cmndAlias],command) - return self.sp.matchCmndAlias([self.command],command) - - def getLDIF(self): - my_ldif = [] - commands = {} - aliases = self.sp.cmndAliases.keys() - - for cmndAlias in self.sp.cmndAliases: - if(cmndAlias == self.command): - for cmd in self.sp.cmndAliases[cmndAlias]: - commands[cmd] = 1 - elif self.command not in aliases: - commands[self.command] = 1 - - if self.runas and self.runas not in ["ANY", "ALL"]: - my_ldif.append("sudoRunas: %s" % self.runas) - if not self.passwd: - my_ldif.append("sudoOption: !authenticate") - for command in commands.keys(): - my_ldif.append("sudoCommand: %s" % command) - return my_ldif - -class SudoRule: - def __init__(self,user,server,command,sp,options=None): - self.user = user - self.server = server - self.command = command - self.sp = sp - self.options = options - - def __repr__(self): - return "%s %s %s" % (self.user,self.server,self.command) - - def matchUser(self,user): - if(user == self.user): - return True - for userAlias in self.sp.userAliases: - if(userAlias == self.user): #I'm a user alias - return self.sp.matchUserAlias(self.sp.userAliases[userAlias],user) - return self.sp.matchUserAlias([self.user],user) - - def matchHost(self,host): - if(host == self.server): - return True - for hostAlias in self.sp.hostAliases: - if(hostAlias == self.server): #I'm a host alias - return self.sp.matchHostAlias(self.sp.hostAliases[hostAlias],host) - return self.sp.matchHostAlias([self.server],host) - - def getLDIF(self): - my_ldif = [] - - users = [] - aliased = False - for userAlias in self.sp.userAliases: - if(userAlias == self.user): #I'm a user alias - users.extend(self.sp.userAliases[userAlias]) - aliased = True - - if not aliased: - users.append(self.user) - - for user in users: - my_ldif.append("sudoUser: %s" % user) - - found = False - for hostAlias in self.sp.hostAliases: - if hostAlias == self.server: - for host in self.sp.hostAliases[hostAlias]: - my_ldif.append("sudoHost: %s" % host) - found = True - - if not found: - my_ldif.append("sudoHost: %s" % self.server) - - for cmd in self.command: - my_ldif.extend(cmd.getLDIF()) - - return my_ldif - -class SudoersParser: - def __init__(self, options=None): - self.hostAliases = {} - self.userAliases = {} - self.cmndAliases = {} - self.rules = [] - self.options = options - - self.netgroupWarning = 'netgroup syntax used in file but no python netgroup support. Install the python netgroup module for support' - - def _readfile(self, file): - fh = open(file,"r") - return fh.readlines() - - def getLDIF(self): - my_ldif = [] - for rule in self.rules: - my_ldif.append(rule.getLDIF()) - return my_ldif - - def getSudoers(self): - my_sudoers = [] - for rule in self.rules: - cmd = "" - for cmnd in rule.command.command: - if rule.command.runas not in [ "ANY", "ALL", "root" ]: - cmd += "(%s) " % rule.command.runas - - #FIXME: if one command is NOPASSWD, they all are. - if not rule.command.passwd: - cmd += "NOPASSWD: " - - cmd += cmnd.strip() + ", " - cmd = re.sub(",\s*$", "", cmd) # remove the final comma. - - if rule.command.comment: - my_sudoers.append("# %s" % rule.command.comment) - - my_sudoers.append("%s %s = %s" % (rule.user, \ - rule.server, cmd)) - return my_sudoers - - def parseFile(self,file): - lines = self._readfile(file) - lines = self._collapseLines(lines) - - defaultsRE = re.compile("^\s*Defaults") - hostAliasRE = re.compile("^\s*Host_Alias") - userAliasRE = re.compile("^\s*User_Alias") - cmndAliasRE = re.compile("^\s*Cmnd_Alias") - - for line in lines: - if(defaultsRE.search(line)): - # don't currently do anything with these - continue - if(hostAliasRE.search(line)): - self.hostAliases.update(self._parseAlias(line,"Host_Alias")) - continue - if(userAliasRE.search(line)): - self.userAliases.update(self._parseAlias(line,"User_Alias")) - continue - if(cmndAliasRE.search(line)): - self.cmndAliases.update(self._parseAlias(line,"Cmnd_Alias")) - continue - - rule = self._parseRule(line) - if(rule): - self.rules.extend(rule) - - def parseLDIF(self, file): - lines = self._readfile(file) - - nameRE = re.compile("^\s*dn: ") - optionsRE = re.compile("^\s*sudoOption") - hostRE = re.compile("^\s*sudoHost") - userRE = re.compile("^\s*sudoUser") - cmndRE = re.compile("^\s*sudoCommand") - runasRE = re.compile("^\s*sudoRunAs") - - obj = {} - seen = False - dn = "" - - # parse the ldif into individual objects. - for line in lines: - if nameRE.search(line): - seen = True - dn = line[3:].strip() - obj[dn] = [] - continue - - if re.compile("^\s*$").search(line): - seen = False - dn = "" - continue - - # capture everything between the dn and the final empty line. - if seen: - obj[dn].append(line.strip()) - - - rule = {} - sudo_rules = [] - for sudoer in obj: - hosts = [] - users = [] - cmds = [] - runas = "ANY" - passwd = True - option = None - - for line in obj[sudoer]: - if hostRE.search(line): - host = self._parseLDIFAlias(line,"sudoHost") - hosts.append(host) - self.hostAliases.update({host:host}) - continue - if userRE.search(line): - user = self._parseLDIFAlias(line,"sudoUser") - users.append(user) - self.userAliases.update({user:user}) - continue - if cmndRE.search(line): - cmd = self._parseLDIFAlias(line,"sudoCommand").strip() - cmds.append(cmd) - self.cmndAliases.update({cmd:cmd}) - continue - if runasRE.search(line): - runas = self._parseLDIFRunas(line) - continue - if optionsRE.search(line): - passwd, option = self._parseLDIFOptions(line) - continue - - # the joys of normalizing many:many relationships. :-\ - for host in hosts: - for user in users: - sudo_rules.append(SudoRule(user,host,SudoCmnd(runas,passwd,cmds,self,sudoer,self.options),self,self.options,)) - - self.rules.extend(sudo_rules) - - # what commands can a user run on a particular host? - # note: we assume that the current user/group environment is the - # same as the host - def getCommands(self,user,host="localhost"): - if(host=="localhost" or host==None): - host=socket.gethostname() - - print "\nTesting what %s can run on %s\n" % (user,host) - match = False - for rule in self.rules: - if(rule.matchUser(user) and rule.matchHost(host)): - match = True - for cmnd in rule.command: - print cmnd - if(not match): - print "No matches - check spelling\n" - - def canRunCommand(self,user,command,host="localhost"): - """ - Can the user run this particular command? - """ - if(host=="localhost" or host==None): - host=socket.gethostname() - for rule in self.rules: - if(rule.matchUser(user) and rule.matchHost(host)): - for cmnd in rule.command: - if(cmnd.matchCommand(command)): - print "User %s can run command %s" % (user,command) - return True - print "User %s can not run command %s" % (user,command) - return False - - # given the contents of a user alias, see if it matches a particular user - def matchUserAlias(self,userAlias, user): - for entry in userAlias: - if(entry == user): - return True - elif(entry[0] == "%"): - return self._userInGroup(entry[1:],user) - elif(entry[0] == "+"): - return self._userInNetgroup(entry[1:],user) - return False - - def matchHostAlias(self,hostAlias,host): - for entry in hostAlias: - if(entry == "ALL"): - return True - elif(entry.find(host) == 0): - return True - elif(entry[0] == '+'): - return self._hostInNetgroup(entry[1:],host) - return False - - def matchCmndAlias(self,cmndAlias,command): - match = False - for entry in cmndAlias: - negate = False - if(entry[0] == "!"): - negate = True - entry = entry[1:] - if(entry.find(command) == 0): - if(negate): - return False - match = True - if(os.path.normpath(entry) == os.path.dirname(command)): - if(negate): - return False - match = True - if(entry == "ALL"): - match = True - return match - - def _userInGroup(self,group,user): - try: - (gr_name, gr_passwd, gr_gid, gr_mem) = grp.getgrnam(group) - except KeyError: -# print "warning: group %s was not found" % group - return False - if(user in gr_mem): - return True - - def _userInNetgroup(self,group,searchUser): - if(netgroupSupport): - return netgroup.innetgr(group,user=searchUser) - else: - print self.netgroupWarning - - def _hostInNetgroup(self,searchNetgroup,searchHost): - if(netgroupSupport): - return netgroup.innetgr(searchNetgroup,host=searchHost) - else: - print self.netgroupWarning - - def _parseAlias(self,line,marker): - res = {} - - aliasRE = re.compile("\s*%s\s*(\S+)\s*=\s*((\S+,?\s*)+)" % marker) - m = aliasRE.search(line) - if(m): - alias = str(m.group(1)) - nodes = str(m.group(2)).split(",") - nodes = [ node.strip() for node in nodes ] - res[alias] = nodes - - return res - - def _parseLDIFAlias(self, line, marker): - aliasRE = re.compile("^\s*%s: " % marker) - return aliasRE.sub("", line).strip() - - def _parseLDIFOptions(self, line): - passwd = True - option = None - - optionRE = re.compile("^\s*sudoOption:\s*") - - m = optionRE.match(line) - if (m): - if "!authenticate" in optionRE.sub("", line): - passwd = False - else: - option = optionRE.sub("",line).strip() - - return passwd, option - - def _parseLDIFRunas(self, line): - runas = "ANY" - runasRE = re.compile("^\s*sudoRunAs:\s*") - m = runasRE.search(line) - if (m): - runas = runasRE.sub("", line).strip() - return runas - - def _parseRule(self,line): - sudo_rules = [] - - ruleRE = re.compile("\s*(\S+)\s*(.*=.*)") - runasRE = re.compile("^\s*\((\S+)\)(.*)") - - #remove the colon at the end of NOPASSWDs. Makes parsing easier. - line = re.sub("NOPASSWD:", "NOPASSWD", line, 0) - - m = ruleRE.search(line) - if m: - user = str(m.group(1)) - - for rule in str(m.group(2)).split(":"): - hosts, commands = rule.split("=") - parsedCommands = [] - seenCommands = {} - - #TODO: we should probably make SudoCmnd store a list of hosts. - for host in hosts.split(","): - host = host.strip() - - cmnds = commands.split(",") - cmnds = [ cmnd.strip() for cmnd in cmnds ] - for cmnd in cmnds: - unparsed = cmnd - m = runasRE.search(unparsed) - if m: - runas = str(m.group(1)) - unparsed = str(m.group(2)) - else: - runas = "ANY" - pos = unparsed.find("NOPASSWD") - if pos > -1: - passwd = False - unparsed = unparsed[pos+len("NOPASSWD"):] - else: - passwd = True - unparsed = unparsed.strip() - - if unparsed not in seenCommands.keys(): - parsedCommands.append(SudoCmnd(runas,passwd,unparsed,self,self.options)) - seenCommands[unparsed] = 1 - sudo_rules.append(SudoRule(user,host,parsedCommands,self,self.options)) - return sudo_rules - - def _collapseLines(self,lines): - res = [] - currentline = "" - - for line in lines: - if(line.rstrip()[-1:] == "\\"): - currentline += line.rstrip()[:-1] - else: - currentline += line - res.append(currentline) - currentline = "" - - return res - -def createParser(): - parser = OptionParser(usage="%prog [options] -u user") - parser.add_option("-f", "--file", dest="sudoersFile", metavar="FILE", - help="sudoers file to parser (default /etc/sudoers)", default="/etc/sudoers") - parser.add_option("-s", "--host", dest="host", metavar="HOST", - help="host (default is this host)") - parser.add_option("-u", "--user", dest="user", metavar="USER", - help="username to lookup (mandatory)") - parser.add_option("-c", "--command", dest="command", metavar="COMMAND", - help="Instead of printing all commands, test whether this command can be run") - parser.add_option("-l", "--ldif", dest="ldif", action="store_true", - help="Print out the sudoers file in LDIF format") - parser.add_option("--parse-ldif", dest="parse_ldif", action="store_true", - help="parse an LDIF file and output an equivalent sudoers file.") - parser.add_option("-v", "--verbose", dest="verbose", action="store_true", - help="Increase verbosity. Provides debugging output") - return parser - -def main(): - parser = createParser() - (options,args) = parser.parse_args() - if not options.user and not options.ldif and not options.parse_ldif: - parser.print_help() - sys.exit(1) - - sp = SudoersParser(options) - - if options.parse_ldif: - sp.parseLDIF(options.sudoersFile) - else: - sp.parseFile(options.sudoersFile) - - if(options.command): - cmnd = options.command - if(options.command.find('/') == -1): - cmnd = commands.getstatusoutput('which %s' % options.command.split(" ")[0])[1] - elif(options.command[0] != '/'): - cmnd = os.path.normpath(os.path.join(os.getcwd(),options.command)) - if(sp.canRunCommand(options.user,cmnd,options.host)): - - sys.exit(0) - else: - sys.exit(1) - elif options.user or options.host: - sp.getCommands(options.user,options.host) - elif options.ldif: - my_ldif = sp.getLDIF() - - counter = 0 - for x in my_ldif: - print "dn: cn=CN_GOES_HERE_%s,ou=sudoers,ou=ENV_GOES_HERE,dc=example,dc=com" % counter - print "cn: CN_GOES_HERE_%s" % counter - for y in x: - print y - print "objectClass: sudoRole" - print "objectClass: top" - print "\n" - counter += 1 - elif options.parse_ldif: - my_sudoers = sp.getSudoers() - for line in my_sudoers: - print str(line) - -if(__name__ == "__main__"): - main() - diff --git a/yum_repo/libupdate.py b/yum_repo/libupdate.py deleted file mode 100644 index b8a13f7..0000000 --- a/yum_repo/libupdate.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/env python - -# This is a collection of functions that was split off from the original update -# scanner. This code was needed for the other new tools for updating the -# yum repositories. - -### TODO: This could be more OOP-y. Make it a class, add accessors, etc. -### I just don't care enough to do this right now. - -# Author: Brett Lentz - -import os -import rpm -import re - -from fnmatch import fnmatch - -def _build_rpmdict(rpmlist, dir=".", verbose=False): - """ Scans through the given directory, extracts RPM headers from the files - in the rpmlist. """ - - rpmdict = {} - dupes = {} - for pkg in rpmlist: - hdr = get_rpm_hdr(dir + "/" + pkg) - - # Ugh. Unsanitary repo. We'll try to make the best of it. - # We're going to use whichever package rpm.labelCompare - # deems is the "best". - if rpmdict.has_key(hdr['name']): - e1, v1, r1 = get_evr(hdr) - e2, v2, r2 = get_evr(rpmdict[hdr['name']]['hdr']) - - # return 1: a is newer than b - # 0: a and b are the same version - # -1: b is newer than a - if rpm.labelCompare((e1,v1,r1), (e2,v2,r2)) == 1: - rpmdict[hdr['name']] = { "pkg" : pkg, "hdr" : hdr } - if verbose: - print "WARNING! Duplicate package: %s. Using %s" % \ - (hdr['name'], pkg) - else: - if verbose: - print "WARNING! Duplicate package: %s. Using %s" % \ - (hdr['name'], rpmdict[hdr['name']]['pkg']) - dupes[hdr['name']] = { "pkg" : pkg, "hdr" : hdr } - else: - rpmdict[hdr['name']] = { "pkg" : pkg, "hdr" : hdr } - - return rpmdict, dupes - -def _compare_rpmlists(srclist, destlist, verbose=False): - """ compares two lists of rpms, looking for new/updated rpms """ - - updates = {} - newpkgs = {} - keys = srclist.keys() - keys.sort() - for pkg in keys: - if verbose: - print "DEBUG: Examining %s" % pkg - - if destlist.has_key(pkg): - e1, v1, r1 = get_evr(srclist[pkg]['hdr']) - e2, v2, r2 = get_evr(destlist[pkg]['hdr']) - - # return 1: a is newer than b - # 0: a and b are the same version - # -1: b is newer than a - if rpm.labelCompare((e1,v1,r1), (e2,v2,r2)) == 1: - if verbose: - print "INFO: " \ - "Update found: %s - s(%s, %s, %s) d(%s, %s, %s)" % \ - (pkg, e1, v1, r1, e2, v2, r2) - updates[pkg] = srclist[pkg] - else: - if verbose: - e1 = str(srclist[pkg]['hdr']['epoch']) - v1 = str(srclist[pkg]['hdr']['version']) - r1 = str(srclist[pkg]['hdr']['release']) - print "INFO: New package found: %s (%s, %s, %s)" % \ - (pkg, e1, v1, r1) - newpkgs[pkg] = srclist[pkg] - return updates, newpkgs - -def _get_rpm_list(dir, verbose=False): - """ fetches RPM header data from any packages in a given directory """ - - filelist = os.listdir(dir) - rpmlist = [] - for file in filelist: - if re.compile("\.rpm$").search(file): - rpmlist.append(file) - - if verbose: - print "INFO: reading %s" % (dir) - - rpmdict, dupes = _build_rpmdict(rpmlist,dir,verbose) - return rpmdict, dupes - -def _get_rpm_list_for_pkg(name, dir, verbose=False): - """ fetches RPM header data for the named package in a given directory """ - filelist = os.listdir(dir) - rpmlist = [] - for file in filelist: - if re.compile("\.rpm$").search(file) and \ - fnmatch(file, "*"+name+"*"): - rpmlist.append(file) - - if verbose: - print "INFO: reading %s" % (dir) - - rpmdict, dupes = _build_rpmdict(rpmlist,dir,verbose) - return rpmdict, dupes - -def get_rpm_hdr(filename): - try: - fdno = os.open(filename, os.O_RDONLY) - except IOError, (errno, strerror): - print "Unable to open dir %s: %s" % (dir, strerror) - sys.exit(-1) - - ts = rpm.TransactionSet() - ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES) - hdr = ts.hdrFromFdno(fdno) - os.close(fdno) - return hdr - -def get_evr(hdr): - """ return epoch, version, release from rpm header """ - try: - e = str(hdr['epoch']) - v = str(hdr['version']) - r = str(hdr['release']) - return e, v, r - except KeyError: - print "KEYERROR: " - print hdr.keys() - raise - -def get_updates_list(src, dest, verbose=False): - """ Given a source and a destination, compare all of the rpms in the two - directories, and compile four pieces of information: - 1. packages in destination that have updates in source - 2. packages in source that do not exist in destination (i.e. are new - to destination) - 3. duplicate packages in source (e.g. foo-1.0.1-1 and foo-1.0.1-2) - 4. duplicate packages in destination. - """ - srclist, srcdupes = _get_rpm_list(src,verbose) - destlist, destdupes = _get_rpm_list(dest,verbose) - - if verbose: - print "DEBUG: srclist: %s" % srclist.keys().sort() - print "DEBUG: destlist: %s" % destlist.keys().sort() - - updates, newpkgs = _compare_rpmlists(srclist,destlist,verbose) - return updates, newpkgs, srcdupes, destdupes - -def get_updates_for_pkg(name, src, dest, verbose=False): - """ given the name of a package, check src directory for newer versions of - the package that don't exist in the dest directory. - """ - - srclist, srcdupes = _get_rpm_list_for_pkg(name,src,verbose) - destlist, destdupes = _get_rpm_list_for_pkg(name,dest,verbose) - - if verbose: - print "DEBUG: srclist: %s" % srclist.keys().sort() - print "DEBUG: destlist: %s" % destlist.keys().sort() - - updates, newpkgs = _compare_rpmlists(srclist,destlist,verbose) - return updates, newpkgs, srcdupes, destdupes - -def get_updates_for_pkglist(pkglist, src, dest, verbose=False): - """ given a list of packages, check src directory for newer versions of all - packages in the list that don't exist in the dest directory. - """ - - _srclist = {} - _srcdupes = {} - _destlist = {} - _destdupes = {} - - for name in pkglist: - srclist, srcdupes = _get_rpm_list_for_pkg(name,src,verbose) - destlist, destdupes = _get_rpm_list_for_pkg(name,dest,verbose) - # merge the dicts. this is a lossy operation. hopefully we've - # identified any dupes by this point. - _srclist.update(srclist) - _srcdupes.update(srcdupes) - _destlist.update(destlist) - _destdupes.update(destdupes) - - updates, newpkgs = _compare_rpmlists(_srclist, _destlist, verbose) - return updates, newpkgs, _srcdupes, _destdupes - -def get_deps(filename): - """ retrieve dependencies for a given rpm """ - - hdr = get_rpm_hdr(filename) - return hdr.dsOfHeader() diff --git a/yum_repo/trickle.py b/yum_repo/trickle.py deleted file mode 100755 index 0336bb1..0000000 --- a/yum_repo/trickle.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/env python - -# This script is intended to be used for moving rpms from an 'upstream' -# repository to a 'downstream' repository. All it really does is some version -# comparisons and, if it detects a newer version, it copies the file from the -# source location to the destination location. - -# Author: Brett Lentz - -import optparse -import shutil -import sys -from libupdate import get_updates_list, get_updates_for_pkglist - - -def get_options(): - """ command-line options """ - - usage = "usage: %prog [options] -s SRC -d DEST" - OptionParser = optparse.OptionParser - parser = OptionParser(usage) - - required = optparse.OptionGroup(parser, "Required") - optional = optparse.OptionGroup(parser, "Optional") - - required.add_option("-d", "--dest-dir", action="store", type="string", \ - dest="dest", help="Directory containing older RPMs to be updated.") - required.add_option("-s", "--src-dir", action="store", type="string", \ - dest="src", help="Directory containing newer RPMs to update from.") - optional.add_option("-n", "--new", action="store_true", dest="include_newpkgs", \ - help="Include new packages. (i.e. packages that don't exist in the " \ - "destination)") - optional.add_option("-p", "--pkgs", action="store", type="string", \ - dest="pkgs", help="Space-delimited list of package names to check " \ - "for updates. Note: uses globbing to match against \'*PKG*.rpm\'") - optional.add_option("-t", "--test", action="store_true", dest="test", \ - help="Show what would happen, but don't alter the filesystem.") - optional.add_option("-v", "--verbose", action="store_true", dest="verbose", \ - help="Increases verbosity.") - - parser.add_option_group(required) - parser.add_option_group(optional) - options, args = parser.parse_args() - - if not options.src or not options.dest: - parser.print_help() - sys.exit(-1); - - return options, args - -def copy_file(src, dst): - if options.test or options.verbose: - print "Copying " + src + " to " + dst - - if not options.test: - try: - shutil.copy(src, dst) - except IOError, err: - print err - -if __name__ == "__main__": - options, args = get_options() - - if options.pkgs: - updates, newpkgs, srcdupes, destdupes = \ - get_updates_for_pkglist(options.pkgs.split(" "), options.src, \ - options.dest, options.verbose) - else: - updates, newpkgs, srcdupes, destdupes = get_updates_list(options.src, \ - options.dest, options.verbose) - - for pkg in updates: - copy_file(options.src + "/" + updates[pkg]['pkg'], options.dest) - - if options.include_newpkgs: - for pkg in newpkgs: - copy_file(options.src + "/" + newpkgs[pkg]['pkg'], options.dest) - diff --git a/zabbix/MANIFEST.in b/zabbix/MANIFEST.in new file mode 100644 index 0000000..bb3ec5f --- /dev/null +++ b/zabbix/MANIFEST.in @@ -0,0 +1 @@ +include README.md diff --git a/zabbix/README.md b/zabbix/README.md new file mode 100644 index 0000000..032253a --- /dev/null +++ b/zabbix/README.md @@ -0,0 +1,30 @@ +This is an implementation of the Zabbix API in Python. +Please note that the Zabbix API is still in a draft state, +and subject to change. + +Implementations of the Zabbix API in other languages may +be found on the wiki. + +Zabbix 1.8, 2.0, 2.2, 2.4, 3.0 and 3.2 are supported. +Python 2 and 3 are supported. + +Future versions must be supported too, if there is no deep changes. + +Installation: +```sh +# pip install zabbix-api +``` + +Short example: + +```python +>>> from zabbix_api import ZabbixAPI +>>> zapi = ZabbixAPI(server="https://server/") +>>> zapi.login("login", "password") +>>> zapi.trigger.get({"expandExpression": "extend", "triggerids": range(0, 100)}) +``` + +See also: +* http://www.zabbix.com/wiki/doc/api +* https://www.zabbix.com/documentation/2.4/manual/api +* http://www.zabbix.com/forum/showthread.php?t=15218 diff --git a/zabbix/zabbix_item_add_example.py b/zabbix/examples/zabbix_item_add_example.py similarity index 94% rename from zabbix/zabbix_item_add_example.py rename to zabbix/examples/zabbix_item_add_example.py index 9aa5f0e..ce18554 100644 --- a/zabbix/zabbix_item_add_example.py +++ b/zabbix/examples/zabbix_item_add_example.py @@ -5,7 +5,7 @@ ''' from zabbix_api import ZabbixAPI -server="127.0.0.1" +server="http://127.0.0.1" username="api" password="apipass" diff --git a/zabbix/zabbix_rpc_test.py b/zabbix/examples/zabbix_rpc_test.py similarity index 100% rename from zabbix/zabbix_rpc_test.py rename to zabbix/examples/zabbix_rpc_test.py diff --git a/zabbix/examples/zabbix_screen.py b/zabbix/examples/zabbix_screen.py new file mode 100755 index 0000000..9403128 --- /dev/null +++ b/zabbix/examples/zabbix_screen.py @@ -0,0 +1,138 @@ +#!/usr/bin/python + +import sys, os +from zabbix_api import ZabbixAPI + +from argparse import ArgumentParser + +debug_flag = False +progname = os.path.basename(sys.argv[0]) + +def error(msg) : + sys.stderr.write('%s:%s\n' % (progname, msg)) + sys.exit(255) + +def debug(msg) : + if debug_flag : + sys.stderr.write('%s:DEBUG:%s\n' % (progname, msg)) + +parser = ArgumentParser(description = 'Create Zabbix Screen with specified criteria') +parser.add_argument('--url', dest = 'url', default = 'http://localhost/zabbix', help = 'Zabbix server address') +parser.add_argument('-u', '--user', dest = 'user', default = 'admin', help = 'Zabbix user') +parser.add_argument('-p', '--password', dest = 'password', default = '', help = 'Zabbix password') + +parser.add_argument('-S', '--screen', dest = 'screen', required = True, help = 'Screen name') +parser.add_argument('-U', '--update', dest = 'update', default = False, action = 'store_true', help = 'Screen name') + +# if None, calculate from found items +parser.add_argument('-H', dest = 'hsize', type = int, default = 2, help = 'Horizontal size of screen') + +parser.add_argument('--host', dest = 'host', default = None, help = '(Part of) Host to search for (either host or group must be spcified)') +parser.add_argument('--group', dest = 'group', default = None, help = 'Group name to search for (either host or group must be spcified)') +parser.add_argument('--graph', dest = 'graph', required = True, help = '(Part of) Graph name to search for') + +args = parser.parse_args() + +zapi = ZabbixAPI(server = args.url, path = "", log_level = 0) +zapi.login(args.user, args.password) + +# Check if the screen is already exists + +screen = zapi.screen.get({'filter': {"name":args.screen}, 'selectScreenItems':'extend', 'output':'extend'}) + +debug('screen_result = %s' % (screen)) + + +if screen and not args.update : + error('Screen already exists') + +if screen : + screen = screen[0] + +# Search for item and add to the screen +host_list = [] +if args.host : + for host in zapi.host.get({'search':{'name':args.host}}) : + host_list.append(host['hostid']) +elif args.group : + result = zapi.hostgroup.get({'filter':{'name': args.group}, 'output':'extend', 'selectHosts': 'extend'}) + host_map = {} + for r in result : + for host in r['hosts'] : + host_map[host['hostid']] = host['hostid'] + host_list = host_map.values() + +debug('Host matches criteria = %s' % str(host_list)) + +# Look for graph item + +if host_list : + result = zapi.graph.get({'hostids':host_list, 'search':{'name':args.graph}, 'output':'extend'}) +else : + result = zapi.graph.get({'search':{'name':args.graph}, 'output':'extend'}) + +# Screen creation +hsize = args.hsize + +if screen and int(screen['hsize']) != int(hsize) : + error("Couldn't update screen, existing screen hsize = %s, request screen hsize = %s" % (screen['hsize'], hsize)) + +# calculate vsize +num_item = len(result) +if screen and screen['screenitems'] : + num_item += len(screen['screenitems']) +vsize = num_item / hsize +if num_item % hsize != 0 : + vsize += 1 + +debug('calculated hsize = %d, vsize = %d' % (hsize, vsize)) + +hpos = 0 +vpos = 0 +if screen : + for i in screen['screenitems'] : + if hpos < int(i['x']) : + hpos = int(i['x']) + if vpos < int(i['y']) : + vpos = int(i['y']) + + if hpos >= (hsize - 1) : + hpos = 0 + vpos += 1 + +screen_items = [] + +for graph in result : + data = {'colspan': 1, + 'rowspan': 1, + 'resourcetype': 0, + 'resourceid': graph['graphid'], + 'x': hpos, + 'y': vpos, + 'width': 500, + 'height': 100, + } + if screen : + data['screenid'] = screen['screenid'] + screen_items.append(data) + hpos += 1 + if hpos >= hsize : + hpos = 0 + vpos += 1 + +if debug_flag : + for i in screen_items : + debug('item = %s' % i) + +if screen : + zapi.screen.update({'screenid': screen['screenid'], 'hsize': hsize, 'vsize': vsize}) + for i in screen_items : + zapi.screenitem.create(i) + +else : + # Create the screen + # need to know number of item first + screen_creation_result = zapi.screen.create({'name': args.screen, 'hsize': hsize, 'vsize':vsize, 'screenitems': screen_items}) + + debug('Screen creation result = %s' % screen_creation_result) + diff --git a/zabbix/setup.py b/zabbix/setup.py new file mode 100755 index 0000000..a74d0e2 --- /dev/null +++ b/zabbix/setup.py @@ -0,0 +1,41 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +""" +Zabbix API +""" +import os +from setuptools import setup, find_packages, findall + + +def read_descr(fname): + filepath = os.path.join(os.path.dirname(__file__), fname) + try: + import pypandoc + long_description = pypandoc.convert_file(filepath, 'rst') + except(IOError, ImportError): + long_description = open(filepath).read() + + return long_description + + +setup( + name='zabbix-api', + url='https://github.com/gescheit/scripts', + version='0.5.6', + license='GNU LGPL 2.1', + author='Aleksandr Balezin', + author_email='gescheit12@gmail.com', + description='Zabbix API', + long_description=read_descr('README.md'), + py_modules=['zabbix_api'], + include_package_data=True, + zip_safe=False, + platforms='any', + classifiers=[ + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + 'Development Status :: 5 - Production/Stable', + ] +) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 6ab9e56..000f76f 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -1,3121 +1,396 @@ -# This is a port of the ruby zabbix api found here: -# http://trac.red-tux.net/browser/ruby/api/zbx_api.rb -# -#LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html -#Zabbix API Python Library. -#Original Ruby Library is Copyright (C) 2009 Andrew Nelson nelsonab(at)red-tux(dot)net -#Python Library is Copyright (C) 2009 Brett Lentz brett.lentz(at)gmail(dot)com -# -#This library is free software; you can redistribute it and/or -#modify it under the terms of the GNU Lesser General Public -#License as published by the Free Software Foundation; either -#version 2.1 of the License, or (at your option) any later version. -# -#This library is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -#Lesser General Public License for more details. -# -#You should have received a copy of the GNU Lesser General Public -#License along with this library; if not, write to the Free Software -#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - -# NOTES: -# The API requires zabbix 1.8 or later. -# Currently, not all of the API is implemented, and some functionality is -# broken. This is a work in progress. - -import base64 -import hashlib -import httplib -import logging -import string -import sys -import urllib2 -import urllib -import json -from socket import gaierror - -default_log_handler = logging.StreamHandler(sys.stdout) -__logger = logging.getLogger("zabbix_api") -__logger.addHandler(default_log_handler) -__logger.log(10,"Starting logging") - -try: - # Python 2.5+ - import json - __logger.log(15,"Using native json library") -except ImportError: - # Python 2.4 - import simplejson as json - __logger.log(15,"Using simplejson library") - -class ZabbixAPIException(Exception): - """ generic zabbix api exception - code list: - -32602 - already exists - """ - pass - -class InvalidProtoError(ZabbixAPIException): - """ Recived an invalid proto """ - pass - -class ZabbixAPI(object): - __username__ = '' - __password__ = '' - - auth = '' - id = 0 - url = '/api_jsonrpc.php' - params = None - method = None - # HTTP or HTTPS - proto = 'http' - # HTTP authentication - httpuser = None - httppasswd = None - - # sub-class instances. - user = None - usergroup = None - host = None - item = None - hostgroup = None - application = None - trigger = None - sysmap = None - template = None - drule = None - # Constructor Params: - # server: Server to connect to - # path: Path leading to the zabbix install - # proto: Protocol to use. http or https - # We're going to use proto://server/path to find the JSON-RPC api. - # - # user: HTTP auth username - # passwd: HTTP auth password - # log_level: logging level - # **kwargs: Data to pass to each api module - def __init__( self, server='http://localhost/zabbix',user=None,passwd=None, log_level=logging.WARNING, **kwargs): - """ Create an API object. """ - self._setuplogging() - self.set_log_level(log_level) - - self.server=server - self.url=server+'/api_jsonrpc.php' - self.proto=self.server.split("://")[0] - #self.proto=proto - self.httpuser=user - self.httppasswd=passwd - - self.user = ZabbixAPIUser(self,**kwargs) - self.usergroup = ZabbixAPIUserGroup(self,**kwargs) - self.host = ZabbixAPIHost(self,**kwargs) - self.item = ZabbixAPIItem(self,**kwargs) - self.hostgroup = ZabbixAPIHostGroup(self,**kwargs) - self.application = ZabbixAPIApplication(self,**kwargs) - self.trigger = ZabbixAPITrigger(self,**kwargs) - self.sysmap = ZabbixAPISysMap(self,**kwargs) - self.template = ZabbixAPITemplate(self,**kwargs) - self.action = ZabbixAPIAction(self,**kwargs) - self.alert = ZabbixAPIAlert(self,**kwargs) - self.info = ZabbixAPIInfo(self,**kwargs) - self.event = ZabbixAPIEvent(self,**kwargs) - self.graph = ZabbixAPIGraph(self,**kwargs) - self.graphitem = ZabbixAPIGraphItem(self,**kwargs) - self.map = ZabbixAPIMap(self,**kwargs) - self.screen = ZabbixAPIScreen(self,**kwargs) - self.script = ZabbixAPIScript(self,**kwargs) - self.usermacro = ZabbixAPIUserMacro(self,**kwargs) - self.map = ZabbixAPIMap(self,**kwargs) - self.map = ZabbixAPIMap(self,**kwargs) - self.drule = ZabbixAPIDRule(self,**kwargs) - self.id = 0 - - self.debug(logging.INFO, "url: "+ self.url) - - def _setuplogging(self): - self.logger = logging.getLogger("zabbix_api.%s"%self.__class__.__name__) - - def set_log_level(self, level): - self.debug(logging.INFO, "Set logging level to %d" % level) - self.logger.setLevel(level) - - def debug(self, level, var="", msg=None): - strval = str(level) + ": " - if msg: - strval = strval + str(msg) - if var != "": - strval = strval + str(var) - - self.logger.log(level,strval) - - def json_obj(self, method, params={}): - obj = { 'jsonrpc' : '2.0', - 'method' : method, - 'params' : params, - 'auth' : self.auth, - 'id' : self.id - } - - self.debug(logging.DEBUG, "json_obj: " + str(obj)) - - return json.dumps(obj) - - def login(self, user='', password='', save=True): - if user != '': - l_user = user - l_password = password - - if save: - self.__username__ = user - self.__password__ = password - elif self.__username__ != '': - l_user = self.__username__ - l_password = self.__password__ - else: - raise ZabbixAPIException("No authentication information available.") - - # don't print the raw password. - hashed_pw_string = "md5(" + hashlib.md5(l_password).hexdigest() + ")" - self.debug(logging.DEBUG,"Trying to login with %s:%s"% \ - (repr(l_user),repr(hashed_pw_string))) - obj = self.json_obj('user.authenticate', { 'user' : l_user, - 'password' : l_password }) - result = self.do_request(obj) - self.auth = result['result'] - - def test_login(self): - if self.auth != '': - obj = self.json_obj('user.checkAuthentication', {'sessionid' : self.auth}) - result = self.do_request(obj) - - if not result['result']: - self.auth = '' - return False # auth hash bad - return True # auth hash good - else: - return False - - def do_request(self, json_obj): - headers = { 'Content-Type' : 'application/json-rpc', - 'User-Agent' : 'python/zabbix_api' } - - if self.httpuser: - self.debug(logging.INFO,"HTTP Auth enabled") - auth='Basic ' + string.strip(base64.encodestring(self.httpuser + ':' + self.httppasswd)) - headers['Authorization'] = auth - - self.debug(logging.INFO, "Sending: " + str(json_obj)) - self.debug(logging.DEBUG, "Sending headers: " + str(headers)) - - request=urllib2.Request(url=self.url, data=json_obj,headers=headers) - - if self.proto=="https": - https_handler=urllib2.HTTPSHandler(debuglevel=0) - opener=urllib2.build_opener(https_handler) - elif self.proto=="http": - http_handler=urllib2.HTTPHandler(debuglevel=0) - opener=urllib2.build_opener(http_handler) - else: - raise ZabbixAPIException("Unknow protocol %s"%self.proto) - - urllib2.install_opener(opener) - response=opener.open(request,timeout=50) - - self.debug(logging.INFO, "Response Code: " + str(response.code)) - - # NOTE: Getting a 412 response code means the headers are not in the - # list of allowed headers. - if response.code != 200: - raise ZabbixAPIException("HTTP ERROR %s: %s" - % (response.status, response.reason)) - reads=response.read() - if len(reads)==0: - raise ZabbixAPIException("Received zero answer") - try: - jobj = json.loads(reads) - except ValueError,msg: - print "unable to decode. returned string: %s"%reads - sys.exit(-1) - self.debug(logging.DEBUG, "Response Body: " + str(jobj)) - - self.id += 1 - - if 'error' in jobj: - msg = "Error %s: %s, %s" % (jobj['error']['code'], - jobj['error']['message'], jobj['error']['data']) - raise ZabbixAPIException(msg,jobj['error']['code']) - return jobj - - def logged_in(self): - if self.auth != '': - return True - return False - - def api_version(self, **options): - self.__checkauth__() - obj = self.do_request(self.json_obj('APIInfo.version', options)) - return obj['result'] - - def __checkauth__(self): - if not self.logged_in(): - raise ZabbixAPIException("Not logged in.") - -class ZabbixAPISubClass(ZabbixAPI): - """ wrapper class to ensure all calls go through the parent object """ - parent = None - - def __init__(self, parent, **kwargs): - self._setuplogging() - self.debug(logging.INFO,"Creating %s"%self.__class__.__name__) - - self.parent = parent - # Save any extra info passed in - for key,val in kwargs.items(): - setattr(self,key,val) - self.debug(logging.WARNING,"Set %s:%s"%(repr(key),repr(val))) - - def __checkauth__(self): - self.parent.__checkauth__() - - def do_request(self, req): - return self.parent.do_request(req) - - def json_obj(self, method, param): - return self.parent.json_obj(method, param) - -def checkauth(fn): - """ Decorator to check authentication of the decorated method """ - def ret(self,*args): - self.__checkauth__() - return fn(self,args) - return ret - -def dojson(name): - def decorator(fn): - def wrapper(self,opts): - self.logger.log(logging.DEBUG, \ - "Going to do_request for %s with opts %s" \ - %(repr(fn),repr(opts))) - return self.do_request(self.json_obj(name,opts))['result'] - return wrapper - return decorator - -class ZabbixAPIUser(ZabbixAPISubClass): - @dojson('user.get') - @checkauth - def get(self,**opts): - """ * Get Users data - * - * First part of parameters are filters which limits the output result set, these filters are set only if appropriate parameter is set. - * For example if "type" is set, then method returns only users of given type. - * Second part of parameters extends result data, adding data about others objects that are related to objects we get. - * For example if "select_usrgrps" parameter is set, resulting objects will have additional property 'usrgrps' containing object with - * data about User UserGroups. - * Third part of parameters affect output. For example "sortfield" will be set to 'alias', result will be sorted by User alias. - * All Parameters are optional! - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] filter by Node IDs - * @param array $options['usrgrpids'] filter by UserGroup IDs - * @param array $options['userids'] filter by User IDs - * @param boolean $options['type'] filter by User type [ USER_TYPE_ZABBIX_USER: 1, USER_TYPE_ZABBIX_ADMIN: 2, USER_TYPE_SUPER_ADMIN: 3 ] - * @param boolean $options['select_usrgrps'] extend with UserGroups data for each User - * @param boolean $options['get_access'] extend with access data for each User - * @param boolean $options['extendoutput'] output only User IDs if not set. - * @param boolean $options['count'] output only count of objects in result. ( result returned in property 'rowscount' ) - * @param string $options['pattern'] filter by Host name containing only give pattern - * @param int $options['limit'] output will be limited to given number - * @param string $options['sortfield'] output will be sorted by given property [ 'userid', 'alias' ] - * @param string $options['sortorder'] output will be sorted in given order [ 'ASC', 'DESC' ] - * @return array - """ - return opts - - @dojson('user.checkAuthentication') - @checkauth - def checkAuthentication(self,**opts): - """ * Check if session ID is authenticated - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $session - * @param array $session['sessionid'] Session ID - * @return boolean - """ - return opts - - @dojson('user.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get User ID by User alias - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $user_data - * @param array $user_data['alias'] User alias - * @return string|boolean """ - return opts - - @dojson('user.add') - @checkauth - def add(self,**opts): - """ * Add Users - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $users multidimensional array with Users data - * @param string $users['name'] - * @param string $users['surname'] - * @param array $users['alias'] - * @param string $users['passwd'] - * @param string $users['url'] - * @param int $users['autologin'] - * @param int $users['autologout'] - * @param string $users['lang'] - * @param string $users['theme'] - * @param int $users['refresh'] - * @param int $users['rows_per_page'] - * @param int $users['type'] - * @param array $users['user_medias'] - * @param string $users['user_medias']['mediatypeid'] - * @param string $users['user_medias']['address'] - * @param int $users['user_medias']['severity'] - * @param int $users['user_medias']['active'] - * @param string $users['user_medias']['period'] - * @return array|boolean - """ - return opts - - @dojson('user.update') - @checkauth - def update(self,**opts): - """ * Update Users - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $users multidimensional array with Users data - * @param string $users['userid'] - * @param string $users['name'] - * @param string $users['surname'] - * @param array $users['alias'] - * @param string $users['passwd'] - * @param string $users['url'] - * @param int $users['autologin'] - * @param int $users['autologout'] - * @param string $users['lang'] - * @param string $users['theme'] - * @param int $users['refresh'] - * @param int $users['rows_per_page'] - * @param int $users['type'] - * @param array $users['user_medias'] - * @param string $users['user_medias']['mediatypeid'] - * @param string $users['user_medias']['address'] - * @param int $users['user_medias']['severity'] - * @param int $users['user_medias']['active'] - * @param string $users['user_medias']['period'] - * @return boolean """ - return opts - - @dojson('user.updateProfile') - @checkauth - def updateProfile(self,**opts): - """ * Update Users - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $users multidimensional array with Users data - * @param string $users['userid'] - * @param string $users['name'] - * @param string $users['surname'] - * @param array $users['alias'] - * @param string $users['passwd'] - * @param string $users['url'] - * @param int $users['autologin'] - * @param int $users['autologout'] - * @param string $users['lang'] - * @param string $users['theme'] - * @param int $users['refresh'] - * @param int $users['rows_per_page'] - * @param int $users['type'] - * @param array $users['user_medias'] - * @param string $users['user_medias']['mediatypeid'] - * @param string $users['user_medias']['address'] - * @param int $users['user_medias']['severity'] - * @param int $users['user_medias']['active'] - * @param string $users['user_medias']['period'] - * @return boolean """ - return opts - - @dojson('user.delete') - @checkauth - def delete(self,**opts): - """ * Delete Users - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $users - * @param array $users[0,...]['userids'] - * @return boolean - """ - return opts - - @dojson('user.addMedia') - @checkauth - def addMedia(self,**opts): - """ * Add Medias for User - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $media_data - * @param string $media_data['userid'] - * @param string $media_data['medias']['mediatypeid'] - * @param string $media_data['medias']['address'] - * @param int $media_data['medias']['severity'] - * @param int $media_data['medias']['active'] - * @param string $media_data['medias']['period'] - * @return boolean - """ - return opts - - @dojson('user.deleteMedia') - @checkauth - def deleteMedia(self,**opts): - """ * Delete User Medias - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $medias - * @param array $medias[...][mediaid] - * @return boolean - """ - return opts - - @dojson('user.updateMedia') - @checkauth - def updateMedia(self,**opts): - """ * Update Medias for User - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $media_data - * @param array $media_data['users'] - * @param array $media_data['users']['userid'] - * @param array $media_data['medias'] - * @param string $media_data['medias']['mediatypeid'] - * @param string $media_data['medias']['sendto'] - * @param int $media_data['medias']['severity'] - * @param int $media_data['medias']['active'] - * @param string $media_data['medias']['period'] - * @return boolean - """ - return opts - -class ZabbixAPIHost(ZabbixAPISubClass): - - @dojson('host.get') - @checkauth - def get(self,**opts): - """ * Get Host data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] Node IDs - * @param array $options['groupids'] HostGroup IDs - * @param array $options['hostids'] Host IDs - * @param boolean $options['monitored_hosts'] only monitored Hosts - * @param boolean $options['templated_hosts'] include templates in result - * @param boolean $options['with_items'] only with items - * @param boolean $options['with_monitored_items'] only with monitored items - * @param boolean $options['with_historical_items'] only with historical items - * @param boolean $options['with_triggers'] only with triggers - * @param boolean $options['with_monitored_triggers'] only with monitored triggers - * @param boolean $options['with_httptests'] only with http tests - * @param boolean $options['with_monitored_httptests'] only with monitored http tests - * @param boolean $options['with_graphs'] only with graphs - * @param boolean $options['editable'] only with read-write permission. Ignored for SuperAdmins - * @param int $options['extendoutput'] return all fields for Hosts - * @param boolean $options['select_groups'] select HostGroups - * @param boolean $options['select_templates'] select Templates - * @param boolean $options['select_items'] select Items - * @param boolean $options['select_triggers'] select Triggers - * @param boolean $options['select_graphs'] select Graphs - * @param boolean $options['select_applications'] select Applications - * @param boolean $options['select_macros'] select Macros - * @param boolean $options['select_profile'] select Profile - * @param int $options['count'] count Hosts, returned column name is rowscount - * @param string $options['pattern'] search hosts by pattern in Host name - * @param string $options['extend_pattern'] search hosts by pattern in Host name, ip and DNS - * @param int $options['limit'] limit selection - * @param string $options['sortfield'] field to sort by - * @param string $options['sortorder'] sort order - * @return array|boolean Host data as array or false if error - """ - return opts - - @dojson('host.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get Host ID by Host name - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $host_data - * @param string $host_data['host'] - * @return int|boolean - """ - return opts - - @dojson('host.create') - @checkauth - def create(self,**opts): - """ * Add Host - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $hosts multidimensional array with Hosts data - * @param string $hosts['host'] Host name. - * @param array $hosts['groups'] array of HostGroup objects with IDs add Host to. - * @param int $hosts['port'] Port. OPTIONAL - * @param int $hosts['status'] Host Status. OPTIONAL - * @param int $hosts['useip'] Use IP. OPTIONAL - * @param string $hosts['dns'] DNS. OPTIONAL - * @param string $hosts['ip'] IP. OPTIONAL - * @param int $hosts['proxy_hostid'] Proxy Host ID. OPTIONAL - * @param int $hosts['useipmi'] Use IPMI. OPTIONAL - * @param string $hosts['ipmi_ip'] IPMAI IP. OPTIONAL - * @param int $hosts['ipmi_port'] IPMI port. OPTIONAL - * @param int $hosts['ipmi_authtype'] IPMI authentication type. OPTIONAL - * @param int $hosts['ipmi_privilege'] IPMI privilege. OPTIONAL - * @param string $hosts['ipmi_username'] IPMI username. OPTIONAL - * @param string $hosts['ipmi_password'] IPMI password. OPTIONAL - * @return boolean - """ - return opts - - @dojson('host.update') - @checkauth - def update(self,**opts): - """ * Update Host - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $hosts multidimensional array with Hosts data - * @param string $hosts['host'] Host name. - * @param int $hosts['port'] Port. OPTIONAL - * @param int $hosts['status'] Host Status. OPTIONAL - * @param int $hosts['useip'] Use IP. OPTIONAL - * @param string $hosts['dns'] DNS. OPTIONAL - * @param string $hosts['ip'] IP. OPTIONAL - * @param int $hosts['proxy_hostid'] Proxy Host ID. OPTIONAL - * @param int $hosts['useipmi'] Use IPMI. OPTIONAL - * @param string $hosts['ipmi_ip'] IPMAI IP. OPTIONAL - * @param int $hosts['ipmi_port'] IPMI port. OPTIONAL - * @param int $hosts['ipmi_authtype'] IPMI authentication type. OPTIONAL - * @param int $hosts['ipmi_privilege'] IPMI privilege. OPTIONAL - * @param string $hosts['ipmi_username'] IPMI username. OPTIONAL - * @param string $hosts['ipmi_password'] IPMI password. OPTIONAL - * @param string $hosts['groups'] groups - * @return boolean - """ - return opts - - @dojson('host.massUpdate') - @checkauth - def massUpdate(self,**opts): - """ * Mass update hosts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $hosts multidimensional array with Hosts data - * @param array $hosts['hosts'] Array of Host objects to update - * @param string $hosts['fields']['host'] Host name. - * @param array $hosts['fields']['groupids'] HostGroup IDs add Host to. - * @param int $hosts['fields']['port'] Port. OPTIONAL - * @param int $hosts['fields']['status'] Host Status. OPTIONAL - * @param int $hosts['fields']['useip'] Use IP. OPTIONAL - * @param string $hosts['fields']['dns'] DNS. OPTIONAL - * @param string $hosts['fields']['ip'] IP. OPTIONAL - * @param int $hosts['fields']['proxy_hostid'] Proxy Host ID. OPTIONAL - * @param int $hosts['fields']['useipmi'] Use IPMI. OPTIONAL - * @param string $hosts['fields']['ipmi_ip'] IPMAI IP. OPTIONAL - * @param int $hosts['fields']['ipmi_port'] IPMI port. OPTIONAL - * @param int $hosts['fields']['ipmi_authtype'] IPMI authentication type. OPTIONAL - * @param int $hosts['fields']['ipmi_privilege'] IPMI privilege. OPTIONAL - * @param string $hosts['fields']['ipmi_username'] IPMI username. OPTIONAL - * @param string $hosts['fields']['ipmi_password'] IPMI password. OPTIONAL - * @return boolean - """ - return opts - - @dojson('host.massAdd') - @checkauth - def massAdd(self,**opts): - """ * Add Hosts to HostGroups. All Hosts are added to all HostGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['groups'] - * @param array $data['hosts'] - * @return boolean - """ - return opts - - @dojson('host.massRemove') - @checkauth - def massRemove(self,**opts): - """ * remove Hosts to HostGroups. All Hosts are added to all HostGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['groups'] - * @param array $data['hosts'] - * @return boolean - """ - return opts - - @dojson('host.delete') - @checkauth - def delete(self,**opts): - """ * Delete Host - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $hosts - * @param array $hosts[0, ...]['hostid'] Host ID to delete - * @return array|boolean - """ - return opts - -class ZabbixAPIItem(ZabbixAPISubClass): - @dojson('item.get') - @checkauth - def get(self,**opts): - """ * Get items data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['triggerids'] - * @param array $options['applicationids'] - * @param boolean $options['status'] - * @param boolean $options['templated_items'] - * @param boolean $options['editable'] - * @param boolean $options['count'] - * @param string $options['pattern'] - * @param int $options['limit'] - * @param string $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('item.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get itemid by host.name and item.key - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $item_data - * @param array $item_data['key_'] - * @param array $item_data['hostid'] - * @return int|boolean -""" - return opts - - @dojson('item.create') - @checkauth - def create(self,**opts): - """ * Create item - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * Input array $items has following structure and default values : - * - * array( array( - * *'description' => *, - * *'key_' => *, - * *'hostid' => *, - * 'delay' => 60, - * 'history' => 7, - * 'status' => ITEM_STATUS_ACTIVE, - * 'type' => ITEM_TYPE_ZABBIX, - * 'snmp_community' => '', - * 'snmp_oid' => '', - * 'value_type' => ITEM_VALUE_TYPE_STR, - * 'data_type' => ITEM_DATA_TYPE_DECIMAL, - * 'trapper_hosts' => 'localhost', - * 'snmp_port' => 161, - * 'units' => '', - * 'multiplier' => 0, - * 'delta' => 0, - * 'snmpv3_securityname' => '', - * 'snmpv3_securitylevel' => 0, - * 'snmpv3_authpassphrase' => '', - * 'snmpv3_privpassphrase' => '', - * 'formula' => 0, - * 'trends' => 365, - * 'logtimefmt' => '', - * 'valuemapid' => 0, - * 'delay_flex' => '', - * 'params' => '', - * 'ipmi_sensor' => '', - * 'applications' => array(), - * 'templateid' => 0 - * ), ...); - * - * - * @param array $items multidimensional array with items data - * @return array|boolean -""" - return opts - - @dojson('item.update') - @checkauth - def update(self,**opts): - """ * Update item - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $items multidimensional array with items data - * @return boolean -""" - return opts - - @dojson('item.delete') - @checkauth - def delete(self,**opts): - """ * Delete items - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $items multidimensional array with item objects - * @param array $items[0,...]['itemid'] - * @return deleted items -""" - return opts - -class ZabbixAPIUserGroup(ZabbixAPISubClass): - - @dojson('usergroup.get') - @checkauth - def get(self,**opts): - """ * Get UserGroups - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] Node IDs - * @param array $options['usrgrpids'] UserGroup IDs - * @param array $options['userids'] User IDs - * @param boolean $options['status'] - * @param boolean $options['with_gui_access'] - * @param boolean $options['with_api_access'] - * @param boolean $options['select_users'] - * @param int $options['extendoutput'] - * @param int $options['count'] - * @param string $options['pattern'] - * @param int $options['limit'] limit selection - * @param string $options['order'] - * @return array -""" - return opts - - @dojson('usergroup.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get UserGroup ID by UserGroup name. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * - * $group_data = array( - * *string 'name' => 'UserGroup name' - * ); - * - * - * @param array $group_data - * @return string|boolean -""" - return opts - - @dojson('usergroup.add') - @checkauth - def add(self,**opts): - """ * Create UserGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * - * $groups = array( array( - * *string 'name' => null, - * string 'users_status' => GROUP_STATUS_DISABLED, - * string 'gui_access' => 0, - * string 'api_access' => 0 - * )); - * - * - * @param array $groups multidimensional array with UserGroups data - * @return boolean -""" - return opts - - @dojson('usergroup.update') - @checkauth - def update(self,**opts): - """ * Update UserGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $groups multidimensional array with UserGroups data - * @return boolean -""" - return opts - - @dojson('usergroup.updateRights') - @checkauth - def updateRights(self,**opts): - """ * Update UserGroup rights to HostGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * - * $rights = array( - * *string 'groupid' => 'UserGroup ID', - * array 'rights' => array( array('id' => 'HostGroup ID', 'permission' => 'permission'), ..) - * ) - * - * - * @param array $rights multidimensional array with rights data - * @return boolean -""" - return opts - - @dojson('usergroup.addRights') - @checkauth - def addRights(self,**opts): - """ * Add rights for UserGroup to HostGroups. Existing rights are updated, new ones added. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * - * $rights = array( - * *string 'groupid' => 'UserGroup ID', - * array 'rights' => array( array('id' => 'HostGroup ID', 'permission' => 'permission'), ..) - * ) - * - * - * @param array $rights multidimensional array with rights data - * @return boolean -""" - return opts - - @dojson('usergroup.updateUsers') - @checkauth - def updateUsers(self,**opts): - """ * Add Users to UserGroup. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * - * @param $usrgrps[0,...]['usrgrpids'] - * @param $users[0,...]['userids'] - * - * - * @param array $data - * @return boolean -""" - return opts - - @dojson('usergroup.removeUsers') - @checkauth - def removeUsers(self,**opts): - """ * Remove users from UserGroup. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param $usrgrps[0,...]['usrgrps'] - * @param $users[0,...]['users'] - * - * @param array $data - * @return boolean -""" - return opts - - @dojson('usergroup.delete') - @checkauth - def delete(self,**opts): - """ * Delete UserGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $groupids - * @param array $groupids['usrgrpids'] - * @return boolean -""" - -class ZabbixAPIHostGroup(ZabbixAPISubClass): - - @dojson('hostgroup.get') - @checkauth - def get(self,**opts): - """ * Get HostGroups - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $params - * @return array -""" - - @dojson('hostgroup.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get HostGroup ID by name - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['name'] - * @return string|boolean HostGroup ID or false if error -""" - return opts - - @dojson('hostgroup.create') - @checkauth - def create(self,**opts): - """ * Add HostGroups - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $groups array with HostGroup names - * @param array $groups['name'] - * @return array -""" - - @dojson('hostgroup.update') - @checkauth - def update(self,**opts): - """ * Update HostGroup - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $groups - * @param array $groups[0]['name'], ... - * @param array $groups[0]['groupid'], ... - * @return boolean -""" - return opts - - @dojson('hostgroup.delete') - @checkauth - def delete(self,**opts): - """ * Delete HostGroups - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $groups - * @param array $groups[0,..]['groupid'] - * @return boolean -""" - - @dojson('hostgroup.massAdd') - @checkauth - def massAdd(self,**opts): - """ * Add Hosts to HostGroups. All Hosts are added to all HostGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['groups'] - * @param array $data['hosts'] - * @param array $data['templates'] - * @return boolean -""" - return opts - - @dojson('hostgroup.massRemove') - @checkauth - def massRemove(self,**opts): - """ * Remove Hosts from HostGroups - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['groups'] - * @param array $data['hosts'] - * @param array $data['templates'] - * @return boolean -""" - - @dojson('hostgroup.massUpdate') - @checkauth - def massUpdate(self,**opts): - """ * Update HostGroups with new Hosts (rewrite) - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['groups'] - * @param array $data['hosts'] - * @param array $data['templates'] - * @return boolean -""" - return opts - -class ZabbixAPIApplication(ZabbixAPISubClass): - - @dojson('application.get') - @checkauth - def get(self,**opts): - """ * Get Applications data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['triggerids'] - * @param array $options['applicationids'] - * @param boolean $options['status'] - * @param boolean $options['editable'] - * @param boolean $options['count'] - * @param string $options['pattern'] - * @param int $options['limit'] - * @param string $options['order'] - * @return array|int item data as array or false if error -""" - - @dojson('application.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get Application ID by host.name and item.key - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $app_data - * @param array $app_data['name'] - * @param array $app_data['hostid'] - * @return int|boolean -""" - return opts - - @dojson('application.create') - @checkauth - def create(self,**opts): - """ * Add Applications - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $applications - * @param array $app_data['name'] - * @param array $app_data['hostid'] - * @return boolean -""" - - @dojson('application.update') - @checkauth - def update(self,**opts): - """ * Update Applications - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $applications - * @param array $app_data['name'] - * @param array $app_data['hostid'] - * @return boolean -""" - return opts - - @dojson('application.delete') - @checkauth - def delete(self,**opts): - """ * Delete Applications - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $applications - * @param array $applications[0,...]['applicationid'] - * @return boolean -""" - - @dojson('application.addItems') - @checkauth - def addItems(self,**opts): - """ * Add Items to applications - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['applications'] - * @param array $data['items'] - * @return boolean -""" - return opts - -class ZabbixAPITrigger(ZabbixAPISubClass): - - @dojson('trigger.get') - @checkauth - def get(self,**opts): - """ * Get Triggers data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['triggerids'] - * @param array $options['applicationids'] - * @param array $options['status'] - * @param array $options['editable'] - * @param array $options['extendoutput'] - * @param array $options['count'] - * @param array $options['pattern'] - * @param array $options['limit'] - * @param array $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('trigger.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get triggerid by host.host and trigger.expression - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggers multidimensional array with trigger objects - * @param array $triggers[0,...]['expression'] - * @param array $triggers[0,...]['host'] - * @param array $triggers[0,...]['hostid'] OPTIONAL - * @param array $triggers[0,...]['description'] OPTIONAL -""" - return opts - - @dojson('trigger.create') - @checkauth - def create(self,**opts): - """ * Add triggers - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggers multidimensional array with triggers data - * @param array $triggers[0,...]['expression'] - * @param array $triggers[0,...]['description'] - * @param array $triggers[0,...]['type'] OPTIONAL - * @param array $triggers[0,...]['priority'] OPTIONAL - * @param array $triggers[0,...]['status'] OPTIONAL - * @param array $triggers[0,...]['comments'] OPTIONAL - * @param array $triggers[0,...]['url'] OPTIONAL - * @param array $triggers[0,...]['templateid'] OPTIONAL - * @return boolean -""" - return opts - - @dojson('trigger.update') - @checkauth - def update(self,**opts): - """ * Update triggers - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggers multidimensional array with triggers data - * @param array $triggers[0,...]['expression'] - * @param array $triggers[0,...]['description'] OPTIONAL - * @param array $triggers[0,...]['type'] OPTIONAL - * @param array $triggers[0,...]['priority'] OPTIONAL - * @param array $triggers[0,...]['status'] OPTIONAL - * @param array $triggers[0,...]['comments'] OPTIONAL - * @param array $triggers[0,...]['url'] OPTIONAL - * @param array $triggers[0,...]['templateid'] OPTIONAL - * @return boolean -""" - return opts - - @dojson('trigger.delete') - @checkauth - def delete(self,**opts): - """ * Delete triggers - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggers multidimensional array with trigger objects - * @param array $triggers[0,...]['triggerid'] - * @return deleted triggers -""" - return opts - - @dojson('trigger.addDependencies') - @checkauth - def addDependencies(self,**opts): - """ * Add dependency for trigger - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggers_data - * @param array $triggers_data['triggerid] - * @param array $triggers_data['depends_on_triggerid'] - * @return boolean -""" - return opts - - @dojson('trigger.deleteDependencies') - @checkauth - def deleteDependencies(self,**opts): - """ * Delete trigger dependencis - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggers multidimensional array with trigger objects - * @param array $triggers[0,...]['triggerid'] - * @return boolean -""" - return opts - -class ZabbixAPISysMap(ZabbixAPISubClass): - - @dojson('map.get') - @checkauth - def get(self,**opts): - """ * Get Map data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] Node IDs - * @param array $options['groupids'] HostGroup IDs - * @param array $options['hostids'] Host IDs - * @param boolean $options['monitored_hosts'] only monitored Hosts - * @param boolean $options['templated_hosts'] include templates in result - * @param boolean $options['with_items'] only with items - * @param boolean $options['with_monitored_items'] only with monitored items - * @param boolean $options['with_historical_items'] only with historical items - * @param boolean $options['with_triggers'] only with triggers - * @param boolean $options['with_monitored_triggers'] only with monitored triggers - * @param boolean $options['with_httptests'] only with http tests - * @param boolean $options['with_monitored_httptests'] only with monitored http tests - * @param boolean $options['with_graphs'] only with graphs - * @param boolean $options['editable'] only with read-write permission. Ignored for SuperAdmins - * @param int $options['extendoutput'] return all fields for Hosts - * @param int $options['count'] count Hosts, returned column name is rowscount - * @param string $options['pattern'] search hosts by pattern in host names - * @param int $options['limit'] limit selection - * @param string $options['sortorder'] - * @param string $options['sortfield'] - * @return array|boolean Host data as array or false if error -""" - return opts - - @dojson('map.add') - @checkauth - def add(self,**opts): - """ * Add Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maps - * @param string $maps['name'] - * @param array $maps['width'] - * @param int $maps['height'] - * @param string $maps['backgroundid'] - * @param string $maps['highlight'] - * @param array $maps['label_type'] - * @param int $maps['label_location'] - * @return boolean | array -""" - return opts - - @dojson('map.update') - @checkauth - def update(self,**opts): - """ * Update Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maps multidimensional array with Hosts data - * @param string $maps['sysmapid'] - * @param string $maps['name'] - * @param array $maps['width'] - * @param int $maps['height'] - * @param string $maps['backgroundid'] - * @param array $maps['label_type'] - * @param int $maps['label_location'] - * @return boolean -""" - return opts - - @dojson('map.delete') - @checkauth - def delete(self,**opts): - """ * Delete Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $sysmaps - * @param array $sysmaps['sysmapid'] - * @return boolean -""" - return opts - - @dojson('map.addLinks') - @checkauth - def addLinks(self,**opts): - """ * addLinks Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $links - * @param array $links[0,...]['sysmapid'] - * @param array $links[0,...]['selementid1'] - * @param array $links[0,...]['selementid2'] - * @param array $links[0,...]['drawtype'] - * @param array $links[0,...]['color'] - * @return boolean -""" - return opts - - @dojson('map.addElements') - @checkauth - def addElements(self,**opts): - """ * Add Element to Sysmap - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $elements[0,...]['sysmapid'] - * @param array $elements[0,...]['elementid'] - * @param array $elements[0,...]['elementtype'] - * @param array $elements[0,...]['label'] - * @param array $elements[0,...]['x'] - * @param array $elements[0,...]['y'] - * @param array $elements[0,...]['iconid_off'] - * @param array $elements[0,...]['iconid_unknown'] - * @param array $elements[0,...]['iconid_on'] - * @param array $elements[0,...]['iconid_disabled'] - * @param array $elements[0,...]['url'] - * @param array $elements[0,...]['label_location'] -""" - return opts - - @dojson('map.addLinkTrigger') - @checkauth - def addLinkTrigger(self,**opts): - """ * Add link trigger to link (Sysmap) - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $links[0,...]['linkid'] - * @param array $links[0,...]['triggerid'] - * @param array $links[0,...]['drawtype'] - * @param array $links[0,...]['color'] -""" - return opts - -class ZabbixAPITemplate(ZabbixAPISubClass): - - @dojson('template.get') - @checkauth - def get(self,**opts): - """ * Get Template data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @static - * @param array $options - * @return array|boolean Template data as array or false if error -""" - return opts -# -# @dojson('template.getObjects') -# @checkauth -# def get(self,**opts): -# """ * Get Template ID by Template name -# * -# * {@source} -# * @access public -# * @static -# * @since 1.8 -# * @version 1 -# * -# * @param array $template_data -# * @param array $template_data['host'] -# * @return string templateid -#""" -# return opts - - @dojson('template.create') - @checkauth - def create(self,**opts): - """ * Add Template - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $templates multidimensional array with templates data - * @param string $templates['host'] - * @param string $templates['port'] - * @param string $templates['status'] - * @param string $templates['useip'] - * @param string $templates['dns'] - * @param string $templates['ip'] - * @param string $templates['proxy_hostid'] - * @param string $templates['useipmi'] - * @param string $templates['ipmi_ip'] - * @param string $templates['ipmi_port'] - * @param string $templates['ipmi_authtype'] - * @param string $templates['ipmi_privilege'] - * @param string $templates['ipmi_username'] - * @param string $templates['ipmi_password'] - * @return boolean -""" - return opts - - @dojson('template.update') - @checkauth - def update(self,**opts): - """ * Update Template - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $templates multidimensional array with templates data - * @return boolean -""" - return opts - - @dojson('template.delete') - @checkauth - def delete(self,**opts): - """ * Delete Template - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $templateids - * @param array $templateids['templateids'] - * @return boolean -""" - return opts - - @dojson('template.massUpdate') - @checkauth - def massUpdate(self,**opts): - """ * Mass update hosts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $hosts multidimensional array with Hosts data - * @param array $hosts['hosts'] Array of Host objects to update - * @param string $hosts['fields']['host'] Host name. - * @param array $hosts['fields']['groupids'] HostGroup IDs add Host to. - * @param int $hosts['fields']['port'] Port. OPTIONAL - * @param int $hosts['fields']['status'] Host Status. OPTIONAL - * @param int $hosts['fields']['useip'] Use IP. OPTIONAL - * @param string $hosts['fields']['dns'] DNS. OPTIONAL - * @param string $hosts['fields']['ip'] IP. OPTIONAL - * @param int $hosts['fields']['proxy_hostid'] Proxy Host ID. OPTIONAL - * @param int $hosts['fields']['useipmi'] Use IPMI. OPTIONAL - * @param string $hosts['fields']['ipmi_ip'] IPMAI IP. OPTIONAL - * @param int $hosts['fields']['ipmi_port'] IPMI port. OPTIONAL - * @param int $hosts['fields']['ipmi_authtype'] IPMI authentication type. OPTIONAL - * @param int $hosts['fields']['ipmi_privilege'] IPMI privilege. OPTIONAL - * @param string $hosts['fields']['ipmi_username'] IPMI username. OPTIONAL - * @param string $hosts['fields']['ipmi_password'] IPMI password. OPTIONAL - * @return boolean -""" - return opts - - @dojson('template.massAdd') - @checkauth - def massAdd(self,**opts): - """ * Link Template to Hosts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param string $data['templates'] - * @param string $data['hosts'] - * @param string $data['groups'] - * @param string $data['templates_link'] - * @return boolean -""" - return opts - - @dojson('template.massRemove') - @checkauth - def massRemove(self,**opts): - """ * remove Hosts to HostGroups. All Hosts are added to all HostGroups. - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param array $data['templates'] - * @param array $data['groups'] - * @param array $data['hosts'] - * @return boolean -""" - return opts - - @dojson('template.linkTemplates') - @checkauth - def linkTemplates(self,**opts): - """ * Link Host to Templates - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $data - * @param string $data['hosts'] - * @param array $data['templats'] - * @return boolean -""" - return opts - -class ZabbixAPIAction(ZabbixAPISubClass): - @dojson('action.get') - @checkauth - def get(self,**opts): - """ * Get Actions data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['actionids'] - * @param array $options['applicationids'] - * @param array $options['status'] - * @param array $options['templated_items'] - * @param array $options['editable'] - * @param array $options['extendoutput'] - * @param array $options['count'] - * @param array $options['pattern'] - * @param array $options['limit'] - * @param array $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('action.create') - @checkauth - def create(self,**opts): - """ * Add actions - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $actions multidimensional array with actions data - * @param array $actions[0,...]['expression'] - * @param array $actions[0,...]['description'] - * @param array $actions[0,...]['type'] OPTIONAL - * @param array $actions[0,...]['priority'] OPTIONAL - * @param array $actions[0,...]['status'] OPTIONAL - * @param array $actions[0,...]['comments'] OPTIONAL - * @param array $actions[0,...]['url'] OPTIONAL - * @return boolean -""" - return opts - - @dojson('action.update') - @checkauth - def update(self,**opts): - """ * Update actions - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $actions multidimensional array with actions data - * @param array $actions[0,...]['actionid'] - * @param array $actions[0,...]['expression'] - * @param array $actions[0,...]['description'] - * @param array $actions[0,...]['type'] OPTIONAL - * @param array $actions[0,...]['priority'] OPTIONAL - * @param array $actions[0,...]['status'] OPTIONAL - * @param array $actions[0,...]['comments'] OPTIONAL - * @param array $actions[0,...]['url'] OPTIONAL - * @return boolean -""" - return opts - - @dojson('action.addConditions') - @checkauth - def addConditions(self,**opts): - """ * add conditions - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $conditions multidimensional array with conditions data - * @param array $conditions[0,...]['actionid'] - * @param array $conditions[0,...]['type'] - * @param array $conditions[0,...]['value'] - * @param array $conditions[0,...]['operator'] - * @return boolean -""" - return opts - - @dojson('action.addOperations') - @checkauth - def addOperations(self,**opts): - """ * add operations - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $operations multidimensional array with operations data - * @param array $operations[0,...]['actionid'] - * @param array $operations[0,...]['operationtype'] - * @param array $operations[0,...]['object'] - * @param array $operations[0,...]['objectid'] - * @param array $operations[0,...]['shortdata'] - * @param array $operations[0,...]['longdata'] - * @param array $operations[0,...]['esc_period'] - * @param array $operations[0,...]['esc_step_from'] - * @param array $operations[0,...]['esc_step_to'] - * @param array $operations[0,...]['default_msg'] - * @param array $operations[0,...]['evaltype'] - * @param array $operations[0,...]['mediatypeid'] - * @param array $operations[0,...]['opconditions'] - * @param array $operations[0,...]['opconditions']['conditiontype'] - * @param array $operations[0,...]['opconditions']['operator'] - * @param array $operations[0,...]['opconditions']['value'] - * @return boolean -""" - return opts - - @dojson('action.delete') - @checkauth - def delete(self,**opts): - """ * Delete actions - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $actionids - * @param array $actionids['actionids'] - * @return boolean -""" - return opts - -class ZabbixAPIAlert(ZabbixAPISubClass): - @dojson('alert.get') - @checkauth - def get(self,**opts): - """ * Get Alerts data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['alertids'] - * @param array $options['applicationids'] - * @param array $options['status'] - * @param array $options['templated_items'] - * @param array $options['editable'] - * @param array $options['extendoutput'] - * @param array $options['count'] - * @param array $options['pattern'] - * @param array $options['limit'] - * @param array $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('alert.add') - @checkauth - def add(self,**opts): - """ * Add alerts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $alerts multidimensional array with alerts data - * @param array $alerts[0,...]['expression'] - * @param array $alerts[0,...]['description'] - * @param array $alerts[0,...]['type'] OPTIONAL - * @param array $alerts[0,...]['priority'] OPTIONAL - * @param array $alerts[0,...]['status'] OPTIONAL - * @param array $alerts[0,...]['comments'] OPTIONAL - * @param array $alerts[0,...]['url'] OPTIONAL - * @return boolean -""" - return opts - - @dojson('alert.delete') - @checkauth - def delete(self,**opts): - """ * Delete alerts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $alertids - * @param array $alertids['alertids'] - * @return boolean -""" - return opts - -class ZabbixAPIInfo(ZabbixAPISubClass): - @dojson('apiinfo.version') - @checkauth - def version(self,**opts): - """ * Get API version - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @return string -""" - return opts - -class ZabbixAPIEvent(ZabbixAPISubClass): - @dojson('event.get') - @checkauth - def get(self,**opts): - """ * Get events data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['eventids'] - * @param array $options['applicationids'] - * @param array $options['status'] - * @param array $options['templated_items'] - * @param array $options['editable'] - * @param array $options['extendoutput'] - * @param array $options['count'] - * @param array $options['pattern'] - * @param array $options['limit'] - * @param array $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('event.add') - @checkauth - def add(self,**opts): - """ * Add events ( without alerts ) - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $events multidimensional array with events data - * @param array $events[0,...]['source'] - * @param array $events[0,...]['object'] - * @param array $events[0,...]['objectid'] - * @param array $events[0,...]['clock'] OPTIONAL - * @param array $events[0,...]['value'] OPTIONAL - * @param array $events[0,...]['acknowledged'] OPTIONAL - * @return boolean -""" - return opts - - @dojson('event.delete') - @checkauth - def delete(self,**opts): - """ * Delete events by eventids - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $eventids - * @param array $eventids['eventids'] - * @return boolean -""" - return opts - - @dojson('event.deleteByTriggerIDs') - @checkauth - def deleteByTriggerIDs(self,**opts): - """ * Delete events by triggerids - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $triggerids - * @return boolean -""" - return opts - - @dojson('event.acknowledge') - @checkauth - def acknowledge(self,**opts): - """ - events - eventids - triggers - triggerids - message -""" - return opts - -class ZabbixAPIGraph(ZabbixAPISubClass): - @dojson('graph.get') - @checkauth - def get(self,**opts): - """ * Get graph data -* -* -* $options = array( -* array 'graphids' => array(graphid1, graphid2, ...), -* array 'itemids' => array(itemid1, itemid2, ...), -* array 'hostids' => array(hostid1, hostid2, ...), -* int 'type' => 'graph type, chart/pie' -* boolean 'templated_graphs' => 'only templated graphs', -* int 'count' => 'count', -* string 'pattern' => 'search hosts by pattern in graph names', -* integer 'limit' => 'limit selection', -* string 'order' => 'deprecated parameter (for now)' -* ); -* -* -* @static -* @param array $options -* @return array|boolean host data as array or false if error -""" - return opts - - @dojson('graph.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get graphid by graph name - * - * - * $graph_data = array( - * *string 'graph' => 'graph name' - * ); - * - * - * @static - * @param array $graph_data - * @return string|boolean graphid -""" - return opts - - @dojson('graph.add') - @checkauth - def add(self,**opts): - """ * Add graph - * - * - * $graphs = array( - * *string 'name' => null, - * int 'width' => 900, - * int 'height' => 200, - * int 'ymin_type' => 0, - * int 'ymax_type' => 0, - * int 'yaxismin' => 0, - * int 'yaxismax' => 100, - * int 'ymin_itemid' => 0, - * int 'ymax_itemid' => 0, - * int 'show_work_period' => 1, - * int 'show_triggers' => 1, - * int 'graphtype' => 0, - * int 'show_legend' => 0, - * int 'show_3d' => 0, - * int 'percent_left' => 0, - * int 'percent_right' => 0 - * ); - * - * - * @static - * @param array $graphs multidimensional array with graphs data - * @return boolean -""" - return opts - - @dojson('graph.update') - @checkauth - def update(self,**opts): - """ * Update graphs - * - * @static - * @param array $graphs multidimensional array with graphs data - * @return boolean -""" - return opts - - @dojson('graph.delete') - @checkauth - def delete(self,**opts): - """ * Delete graphs - * - * @static - * @param _array $graphs - * @param array $graphs['graphids'] - * @return boolean -""" - return opts - - @dojson('graph.addItems') - @checkauth - def addItems(self,**opts): - """ * Add items to graph - * - * - * $items = array( - * *string 'graphid' => null, - * array 'items' => ( - * 'item1' => array( - * *int 'itemid' => null, - * int 'color' => '000000', - * int 'drawtype' => 0, - * int 'sortorder' => 0, - * int 'yaxisside' => 1, - * int 'calc_fnc' => 2, - * int 'type' => 0, - * int 'periods_cnt' => 5, - * ), ... ) - * ); - * - * - * @static - * @param array $items multidimensional array with items data - * @return boolean -""" - return opts - - @dojson('graph.deleteItems') - @checkauth - def deleteItems(self,**opts): - """ /** - * Delete graph items - * - * @static - * @param array $items - * @return boolean - */ -""" - return opts - -class ZabbixAPIGraphItem(ZabbixAPISubClass): - @dojson('graphitem.get') - @checkauth - def get(self,**opts): - """ * Get GraphItems data -* -* @static -* @param array $options -* @return array|boolean -""" - return opts - - @dojson('graphitem.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get graph items by graph id and graph item id - * - * @static - * @param _array $gitem_data - * @param array $gitem_data['itemid'] - * @param array $gitem_data['graphid'] - * @return string|boolean graphid -""" - return opts - - @dojson('maintenance.get') - @checkauth - def get(self,**opts): - """ * Get maintenances data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['triggerids'] - * @param array $options['maintenanceids'] - * @param boolean $options['status'] - * @param boolean $options['templated_items'] - * @param boolean $options['editable'] - * @param boolean $options['count'] - * @param string $options['pattern'] - * @param int $options['limit'] - * @param string $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('maintenance.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get Maintenance ID by host.name and item.key - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $maintenance - * @param array $maintenance['name'] - * @param array $maintenance['hostid'] - * @return int|boolean -""" - return opts - - @dojson('maintenance.add') - @checkauth - def add(self,**opts): - """ * Add maintenances - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maintenances - * @param array $maintenance['name'] - * @param array $maintenance['hostid'] - * @return boolean -""" - return opts - - @dojson('maintenance.update') - @checkauth - def update(self,**opts): - """ * Update maintenances - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maintenances - * @param array $maintenance['name'] - * @param array $maintenance['hostid'] - * @return boolean -""" - return opts - - @dojson('maintenance.delete') - @checkauth - def delete(self,**opts): - """ * Delete maintenances - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maintenanceids - * @param _array $maintenanceids['maintenanceids'] - * @return boolean -""" - return opts - -class ZabbixAPIMap(ZabbixAPISubClass): - @dojson('map.get') - @checkauth - def get(self,**opts): - """ * Get Map data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] Node IDs - * @param array $options['groupids'] HostGroup IDs - * @param array $options['hostids'] Host IDs - * @param boolean $options['monitored_hosts'] only monitored Hosts - * @param boolean $options['templated_hosts'] include templates in result - * @param boolean $options['with_items'] only with items - * @param boolean $options['with_monitored_items'] only with monitored items - * @param boolean $options['with_historical_items'] only with historical items - * @param boolean $options['with_triggers'] only with triggers - * @param boolean $options['with_monitored_triggers'] only with monitored triggers - * @param boolean $options['with_httptests'] only with http tests - * @param boolean $options['with_monitored_httptests'] only with monitored http tests - * @param boolean $options['with_graphs'] only with graphs - * @param boolean $options['editable'] only with read-write permission. Ignored for SuperAdmins - * @param int $options['extendoutput'] return all fields for Hosts - * @param int $options['count'] count Hosts, returned column name is rowscount - * @param string $options['pattern'] search hosts by pattern in host names - * @param int $options['limit'] limit selection - * @param string $options['sortorder'] - * @param string $options['sortfield'] - * @return array|boolean Host data as array or false if error -""" - return opts - - @dojson('map.add') - @checkauth - def add(self,**opts): - """ * Add Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maps - * @param string $maps['name'] - * @param array $maps['width'] - * @param int $maps['height'] - * @param string $maps['backgroundid'] - * @param string $maps['highlight'] - * @param array $maps['label_type'] - * @param int $maps['label_location'] - * @return boolean | array -""" - return opts - - @dojson('update.') - @checkauth - def update(self,**opts): - """ * Update Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $maps multidimensional array with Hosts data - * @param string $maps['sysmapid'] - * @param string $maps['name'] - * @param array $maps['width'] - * @param int $maps['height'] - * @param string $maps['backgroundid'] - * @param array $maps['label_type'] - * @param int $maps['label_location'] - * @return boolean -""" - return opts - - @dojson('map.delete') - @checkauth - def delete(self,**opts): - """ * Delete Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $sysmaps - * @param array $sysmaps['sysmapid'] - * @return boolean -""" - return opts - - @dojson('map.addLinks') - @checkauth - def addLinks(self,**opts): - """ * addLinks Map - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $links - * @param array $links[0,...]['sysmapid'] - * @param array $links[0,...]['selementid1'] - * @param array $links[0,...]['selementid2'] - * @param array $links[0,...]['drawtype'] - * @param array $links[0,...]['color'] - * @return boolean -""" - return opts - - @dojson('map.addElements') - @checkauth - def addElements(self,**opts): - """ * Add Element to Sysmap - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $elements[0,...]['sysmapid'] - * @param array $elements[0,...]['elementid'] - * @param array $elements[0,...]['elementtype'] - * @param array $elements[0,...]['label'] - * @param array $elements[0,...]['x'] - * @param array $elements[0,...]['y'] - * @param array $elements[0,...]['iconid_off'] - * @param array $elements[0,...]['iconid_unknown'] - * @param array $elements[0,...]['iconid_on'] - * @param array $elements[0,...]['iconid_disabled'] - * @param array $elements[0,...]['url'] - * @param array $elements[0,...]['label_location'] -""" - return opts - - @dojson('map.addLinkTrigger') - @checkauth - def addLinkTrigger(self,**opts): - """ * Add link trigger to link (Sysmap) - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $links[0,...]['linkid'] - * @param array $links[0,...]['triggerid'] - * @param array $links[0,...]['drawtype'] - * @param array $links[0,...]['color'] -""" - return opts - -class ZabbixAPIScreen(ZabbixAPISubClass): - @dojson('screen.get') - @checkauth - def get(self,**opts): - """ * Get Screen data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] Node IDs - * @param boolean $options['with_items'] only with items - * @param boolean $options['editable'] only with read-write permission. Ignored for SuperAdmins - * @param int $options['extendoutput'] return all fields for Hosts - * @param int $options['count'] count Hosts, returned column name is rowscount - * @param string $options['pattern'] search hosts by pattern in host names - * @param int $options['limit'] limit selection - * @param string $options['order'] deprecated parameter (for now) - * @return array|boolean Host data as array or false if error -""" - return opts - - @dojson('screen.add') - @checkauth - def add(self,**opts): - """ * Add Screen - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $screens - * @param string $screens['name'] - * @param array $screens['hsize'] - * @param int $screens['vsize'] - * @return boolean | array -""" - return opts - - @dojson('screen.update') - @checkauth - def update(self,**opts): - """ * Update Screen - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $screens multidimensional array with Hosts data - * @param string $screens['screenid'] - * @param int $screens['name'] - * @param int $screens['hsize'] - * @param int $screens['vsize'] - * @return boolean -""" - return opts - - @dojson('screen.delete') - @checkauth - def delete(self,**opts): - """ * Delete Screen - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $screens - * @param array $screens[0,...]['screenid'] - * @return boolean -""" - return opts - - @dojson('screen.setItems') - @checkauth - def setItems(self,**opts): - """ * add ScreenItem - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $screen_items - * @param int $screen_items['screenid'] - * @param int $screen_items['resourcetype'] - * @param int $screen_items['x'] - * @param int $screen_items['y'] - * @param int $screen_items['resourceid'] - * @param int $screen_items['width'] - * @param int $screen_items['height'] - * @param int $screen_items['colspan'] - * @param int $screen_items['rowspan'] - * @param int $screen_items['elements'] - * @param int $screen_items['valign'] - * @param int $screen_items['halign'] - * @param int $screen_items['style'] - * @param int $screen_items['url'] - * @param int $screen_items['dynamic'] - * @return boolean -""" - return opts - - @dojson('screen.deleteItems') - @checkauth - def deleteItems(self,**opts): - """ * delete ScreenItem - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $screen_itemids - * @return boolean -""" - return opts - -class ZabbixAPIScript(ZabbixAPISubClass): - @dojson('script.get') - @checkauth - def get(self,**opts): - """ * Get Scripts data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $options - * @param array $options['itemids'] - * @param array $options['hostids'] - * @param array $options['groupids'] - * @param array $options['triggerids'] - * @param array $options['scriptids'] - * @param boolean $options['status'] - * @param boolean $options['templated_items'] - * @param boolean $options['editable'] - * @param boolean $options['count'] - * @param string $options['pattern'] - * @param int $options['limit'] - * @param string $options['order'] - * @return array|int item data as array or false if error -""" - return opts - - @dojson('script.getObjects') - @checkauth - def getObjects(self,**opts): - """ * Get Script ID by host.name and item.key - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $script - * @param array $script['name'] - * @param array $script['hostid'] - * @return int|boolean -""" - return opts - - @dojson('script.add') - @checkauth - def add(self,**opts): - """ * Add Scripts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $scripts - * @param array $script['name'] - * @param array $script['hostid'] - * @return boolean -""" - return opts - - @dojson('script.update') - @checkauth - def update(self,**opts): - """ * Update Scripts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $scripts - * @param array $script['name'] - * @param array $script['hostid'] - * @return boolean -""" - return opts - - @dojson('script.delete') - @checkauth - def delete(self,**opts): - """ * Delete Scripts - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $scriptids - * @param array $scriptids - * @return boolean -""" - return opts - - @dojson('script.execute') - @checkauth - def execute(self,**opts): - """ -""" - return opts - - @dojson('script.getCommand') - @checkauth - def getCommand(self,**opts): - """ -""" - return opts - - @dojson('script.getScriptsByHosts') - @checkauth - def getScriptsByHosts(self,**opts): - """ -""" - return opts - - -class ZabbixAPIDRule(ZabbixAPISubClass): - @dojson('drule.create') - @checkauth - def create(self,**opts): - return opts - @dojson('drule.get') - @checkauth - def get(self,**opts): - return opts - -class ZabbixAPIUserMacro(ZabbixAPISubClass): - @dojson('usermacro.get') - @checkauth - def get(self,**opts): - """ * Get UserMacros data - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $options - * @param array $options['nodeids'] Node IDs - * @param array $options['groupids'] UserMacrosGroup IDs - * @param array $options['macroids'] UserMacros IDs - * @param boolean $options['monitored_macros'] only monitored UserMacros - * @param boolean $options['templated_macros'] include templates in result - * @param boolean $options['with_items'] only with items - * @param boolean $options['with_monitored_items'] only with monitored items - * @param boolean $options['with_historical_items'] only with historical items - * @param boolean $options['with_triggers'] only with triggers - * @param boolean $options['with_monitored_triggers'] only with monitored triggers - * @param boolean $options['with_httptests'] only with http tests - * @param boolean $options['with_monitored_httptests'] only with monitored http tests - * @param boolean $options['with_graphs'] only with graphs - * @param boolean $options['editable'] only with read-write permission. Ignored for SuperAdmins - * @param int $options['extendoutput'] return all fields for UserMacros - * @param int $options['count'] count UserMacros, returned column name is rowscount - * @param string $options['pattern'] search macros by pattern in macro names - * @param int $options['limit'] limit selection - * @param string $options['order'] deprecated parameter (for now) - * @return array|boolean UserMacros data as array or false if error -""" - return opts - - @dojson('usermacro.getHostMacroObjects') - @checkauth - def getHostMacroObjects(self,**opts): - """ * Gets all UserMacros data from DB by UserMacros ID - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macro_data - * @param string $macro_data['macroid'] - * @return array|boolean UserMacros data as array or false if error -""" - return opts - - @dojson('usermacro.add') - @checkauth - def add(self,**opts): - """ * add Host Macro - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macros - * @param string $macros[0..]['hostid'] - * @param string $macros[0..]['macro'] - * @param string $macros[0..]['value'] - * @return array of object macros -""" - return opts - - @dojson('usermacro.update') - @checkauth - def update(self,**opts): - """ * Update host macros, replace all with new ones - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macros - * @param string $macros['hostid'] - * @param string $macros['macros'][0..]['macro'] - * @param string $macros['macros'][0..]['value'] - * @return array|boolean -""" - return opts - - @dojson('usermacro.updateValue') - @checkauth - def updateValue(self,**opts): - """ * Update macros values - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macros - * @param string $macros['hostid'] - * @param string $macros['macros'][0..]['macro'] - * @param string $macros['macros'][0..]['value'] - * @return array|boolean -""" - return opts - - @dojson('usermacro.deleteHostMacro') - @checkauth - def deleteHostMacro(self,**opts): - """ * Delete UserMacros - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $hostmacroids - * @param array $hostmacroids['hostmacroids'] - * @return boolean -""" - return opts - - @dojson('usermacro.addGlobal') - @checkauth - def addGlobal(self,**opts): - """ * Add global macros - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macros - - * @param string $macros[0..]['macro'] - * @param string $macros[0..]['value'] - * @return array|boolean -""" - return opts - - @dojson('usermacro.deleteGlobalMacro') - @checkauth - def deleteGlobalMacro(self,**opts): - """ * Delete UserMacros - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param array $globalmacroids - * @param array $globalmacroids['globalmacroids'] - * @return boolean -""" - return opts - - @dojson('usermacro.validate') - @checkauth - def validate(self,**opts): - """ * Validates macros expression - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macros array with macros expressions - * @return array|boolean -""" - return opts - - @dojson('usermacro.getGlobalMacroObjects') - @checkauth - def getGlobalMacroObjects(self,**opts): - """ * Gets all UserMacros data from DB by UserMacros ID - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macro_data - * @param string $macro_data['macroid'] - * @return array|boolean UserMacros data as array or false if error -""" - return opts - - @dojson('usermacro.getHostMacroId') - @checkauth - def getHostMacroId(self,**opts): - """ * Get UserMacros ID by UserMacros name - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macro_data - * @param string $macro_data['macro'] - * @param string $macro_data['hostid'] - * @return int|boolean -""" - return opts - - @dojson('usermacro.getGlobalMacroId') - @checkauth - def getGlobalMacroId(self,**opts): - """ * Get UserMacros ID by UserMacros name - * - * {@source} - * @access public - * @static - * @since 1.8 - * @version 1 - * - * @param _array $macro_data - * @param string $macro_data['macro'] - * @return int|boolean -""" - return opts - - @dojson('usermacro.getMacros') - @checkauth - def getMacros(self,**opts): - """ -""" - return opts - - @dojson('usermacro.resolveTrigger') - @checkauth - def resolveTrigger(self,**opts): - """ -""" - return opts - - @dojson('usermacro.resolveItem') - @checkauth - def resolveItem(self,**opts): - """ -""" - return opts +# This is a port of the ruby zabbix api found here: +# http://trac.red-tux.net/browser/ruby/api/zbx_api.rb +# +# LGPL 2.1 http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html +# Zabbix API Python Library. +# Original Ruby Library is Copyright (C) 2009 Andrew Nelson nelsonab(at)red-tux(dot)net +# Python Library is Copyright (C) 2009 Brett Lentz brett.lentz(at)gmail(dot)com +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +# NOTES: +# The API requires zabbix 1.8 or later. +# Currently, not all of the API is implemented, and some functionality is +# broken. This is a work in progress. + +import base64 +import hashlib +import logging +import string +import sys +import ssl +import socket +try: + import urllib2 +except ImportError: + import urllib.request as urllib2 # python3 +import re +from collections import deque + +try: + from ssl import _create_unverified_context + HAS_SSLCONTEXT = True +except ImportError: + HAS_SSLCONTEXT = False + + +default_log_handler = logging.StreamHandler(sys.stdout) +__logger = logging.getLogger("zabbix_api") +__logger.addHandler(default_log_handler) +__logger.log(10, "Starting logging") + +try: + # Separate module or Python <2.6 + import simplejson as json + __logger.log(15, "Using simplejson library") +except ImportError: + # Python >=2.6 + import json + __logger.log(15, "Using native json library") + + +def checkauth(fn): + """ Decorator to check authentication of the decorated method """ + + def ret(self, *args): + self.__checkauth__() + return fn(self, args) + return ret + + +def dojson(fn): + def wrapper(self, method, opts): + self.logger.log(logging.DEBUG, + "Going to do_request for %s with opts %s" + % (repr(fn), repr(opts))) + return self.do_request(self.json_obj(method, opts))['result'] + return wrapper + + +def version_compare(v1, v2): + """ + The result is 0 if v1 == v2, -1 if v1 < v2, and +1 if v1 > v2 + """ + for v1_part, v2_part in zip(v1.split("."), v2.split(".")): + if v1_part.isdecimal() and v2_part.isdecimal(): + if int(v1_part) > int(v2_part): + return 1 + elif int(v1_part) < int(v2_part): + return -1 + else: + if v1 > v2: + return 1 + elif v1 < v2: + return -1 + return 0 + + +class ZabbixAPIException(Exception): + + """ generic zabbix api exception + code list: + -32602 - Invalid params (eg already exists) + -32500 - no permissions + """ + pass + + +class Already_Exists(ZabbixAPIException): + pass + + +class InvalidProtoError(ZabbixAPIException): + + """ Recived an invalid proto """ + pass + + +class APITimeout(ZabbixAPIException): + pass + + +class ZabbixAPI(object): + __username__ = '' + __password__ = '' + __tokenauth__ = False + + auth = '' + url = '/api_jsonrpc.php' + params = None + method = None + # HTTP or HTTPS + proto = 'http' + # HTTP authentication + httpuser = None + httppasswd = None + timeout = 10 + validate_certs = None + # sub-class instances. + # Constructor Params: + # server: Server to connect to + # path: Path leading to the zabbix install + # proto: Protocol to use. http or https + # We're going to use proto://server/path to find the JSON-RPC api. + # + # user: HTTP auth username + # passwd: HTTP auth password + # log_level: logging level + # r_query_len: max len query history + # **kwargs: Data to pass to each api module + + def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httppasswd, + log_level=logging.WARNING, timeout=10, r_query_len=10, validate_certs=True, **kwargs): + """ Create an API object. """ + self._setuplogging() + self.set_log_level(log_level) + self.server = server + self.url = server + '/api_jsonrpc.php' + self.proto = self.server.split("://")[0] + # self.proto=proto + self.httpuser = user + self.httppasswd = passwd + self.timeout = timeout + self.kwargs = kwargs + self.id = 0 + self.r_query = deque([], maxlen=r_query_len) + self.validate_certs = validate_certs + self.debug(logging.INFO, "url: " + self.url) + + def _setuplogging(self): + self.logger = logging.getLogger("zabbix_api.%s" % self.__class__.__name__) + + def set_log_level(self, level): + self.debug(logging.INFO, "Set logging level to %d" % level) + self.logger.setLevel(level) + + def recent_query(self): + """ + return recent query + """ + return list(self.r_query) + + def debug(self, level, var="", msg=None): + strval = str(level) + ": " + if msg: + strval = strval + str(msg) + if var != "": + strval = strval + str(var) + + self.logger.log(level, strval) + + def json_obj(self, method, params={}, auth=True): + obj = {'jsonrpc': '2.0', + 'method': method, + 'params': params, + 'auth': self.auth, + 'id': self.id} + if not auth: + del obj['auth'] + + self.debug(logging.DEBUG, "json_obj: " + str(obj)) + + return json.dumps(obj) + + def login(self, user='', password='', save=True, api_token=None): + if api_token is not None: + # due to ZBX-21688 we are unable to check if the token is valid + # obj = self.json_obj('user.checkAuthentication', {'sessionid': api_token}, auth=False) + # result = self.do_request(obj) + self.debug(logging.DEBUG, "Using API Token for auth") + self.auth=api_token + self.__tokenauth__ = True + return + + if user != '': + l_user = user + l_password = password + + if save: + self.__username__ = user + self.__password__ = password + elif self.__username__ != '': + l_user = self.__username__ + l_password = self.__password__ + else: + raise ZabbixAPIException("No authentication information available.") + + # don't print the raw password. + hashed_pw_string = "md5(" + hashlib.md5(l_password.encode('utf-8')).hexdigest() + ")" + self.debug(logging.DEBUG, "Trying to login with %s:%s" % + (repr(l_user), repr(hashed_pw_string))) + if version_compare(self.api_version(), '5.4') >= 0: + login_arg = {'username': l_user, 'password': l_password} + else: + login_arg = {'user': l_user, 'password': l_password} + obj = self.json_obj('user.login', login_arg, auth=False) + result = self.do_request(obj) + self.auth = result['result'] + + def logout(self): + if self.__tokenauth__: + # Do nothing for logout for API tokens. + self.debug(logging.DEBUG, "Clearing auth information due to use of API Token") + self.auth = '' + self.__username__ = '' + self.__password__ = '' + self.__tokenauth__ = False + return + if self.auth == '': + raise ZabbixAPIException("No authentication information available.") + self.debug(logging.DEBUG, "Trying to logout user: %s." % self.__username__) + obj = self.json_obj('user.logout', auth=True) + result = self.do_request(obj) + if result['result']: + self.auth = '' + self.__username__ = '' + self.__password__ = '' + + def test_login(self): + if self.auth != '': + obj = self.json_obj('user.checkAuthentication', {'sessionid': self.auth}) + result = self.do_request(obj) + + if not result['result']: + self.auth = '' + return False # auth hash bad + return True # auth hash good + else: + return False + + def do_request(self, json_obj): + headers = {'Content-Type': 'application/json-rpc', + 'User-Agent': 'python/zabbix_api'} + + if self.httpuser: + self.debug(logging.INFO, "HTTP Auth enabled") + credentials = (self.httpuser + ':' + self.httppasswd).encode('ascii') + auth = 'Basic ' + base64.b64encode(credentials).decode("ascii") + headers['Authorization'] = auth + self.r_query.append(str(json_obj)) + self.debug(logging.INFO, "Sending: " + str(json_obj)) + self.debug(logging.DEBUG, "Sending headers: " + str(headers)) + + request = urllib2.Request(url=self.url, data=json_obj.encode('utf-8'), headers=headers) + if self.proto == "https": + if HAS_SSLCONTEXT and not self.validate_certs: + https_handler = urllib2.HTTPSHandler(debuglevel=0, context=_create_unverified_context()) + else: + https_handler = urllib2.HTTPSHandler(debuglevel=0) + opener = urllib2.build_opener(https_handler) + elif self.proto == "http": + http_handler = urllib2.HTTPHandler(debuglevel=0) + opener = urllib2.build_opener(http_handler) + else: + raise ZabbixAPIException("Unknow protocol %s" % self.proto) + + urllib2.install_opener(opener) + try: + response = opener.open(request, timeout=self.timeout) + except ssl.SSLError as e: + if hasattr(e, 'message'): + e = e.message + raise ZabbixAPIException("ssl.SSLError - %s" % e) + except socket.timeout as e: + raise APITimeout("HTTP read timeout",) + except urllib2.URLError as e: + if hasattr(e, 'message') and e.message: + e = e.message + elif hasattr(e, 'reason'): + e = e.reason + raise ZabbixAPIException("urllib2.URLError - %s" % e) + self.debug(logging.INFO, "Response Code: " + str(response.code)) + + # NOTE: Getting a 412 response code means the headers are not in the + # list of allowed headers. + if response.code != 200: + raise ZabbixAPIException("HTTP ERROR %s: %s" + % (response.status, response.reason)) + reads = response.read() + if len(reads) == 0: + raise ZabbixAPIException("Received zero answer") + try: + jobj = json.loads(reads.decode('utf-8')) + except ValueError as msg: + print ("unable to decode. returned string: %s" % reads) + sys.exit(-1) + self.debug(logging.DEBUG, "Response Body: " + str(jobj)) + + self.id += 1 + + if 'error' in jobj: # some exception + msg = "Error %s: %s, %s while sending %s" % (jobj['error']['code'], + jobj['error']['message'], jobj['error']['data'], str(json_obj)) + if re.search(".*already\sexists.*", jobj["error"]["data"], re.I): # already exists + raise Already_Exists(msg, jobj['error']['code']) + else: + raise ZabbixAPIException(msg, jobj['error']['code']) + return jobj + + def logged_in(self): + if self.auth != '': + return True + return False + + def api_version(self, **options): + obj = self.do_request(self.json_obj('apiinfo.version', options, auth=False)) + return obj['result'] + + def __checkauth__(self): + if not self.logged_in(): + raise ZabbixAPIException("Not logged in.") + + def __getattr__(self, name): + return ZabbixAPISubClass(self, dict({"prefix": name}, **self.kwargs)) + + +class ZabbixAPISubClass(ZabbixAPI): + + """ wrapper class to ensure all calls go through the parent object """ + parent = None + data = None + + def __init__(self, parent, data, **kwargs): + self._setuplogging() + self.debug(logging.INFO, "Creating %s" % self.__class__.__name__) + self.data = data + self.parent = parent + + # Save any extra info passed in + for key, val in kwargs.items(): + setattr(self, key, val) + self.debug(logging.WARNING, "Set %s:%s" % (repr(key), repr(val))) + + def __getattr__(self, name): + if self.data["prefix"] == "configuration" and name == "import_": # workaround for "import" method + name = "import" + + def method(*opts): + return self.universal("%s.%s" % (self.data["prefix"], name), opts[0]) + return method + + def __checkauth__(self): + self.parent.__checkauth__() + + def do_request(self, req): + return self.parent.do_request(req) + + def json_obj(self, method, param): + return self.parent.json_obj(method, param) + + @dojson + @checkauth + def universal(self, **opts): + return opts