From 8a1963f6101175104d07b494720a482186b40b0f Mon Sep 17 00:00:00 2001 From: gescheit Date: Wed, 2 Feb 2011 11:35:42 +0300 Subject: [PATCH 01/84] add ZabbixAPIHistory class with history.get and history.delete functions --- zabbix/zabbix_api.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 6ab9e56..bd86b00 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -130,8 +130,9 @@ def __init__( self, server='http://localhost/zabbix',user=None,passwd=None, log_ self.script = ZabbixAPIScript(self,**kwargs) self.usermacro = ZabbixAPIUserMacro(self,**kwargs) self.map = ZabbixAPIMap(self,**kwargs) - self.map = ZabbixAPIMap(self,**kwargs) + #self.map = ZabbixAPIMap(self,**kwargs) self.drule = ZabbixAPIDRule(self,**kwargs) + self.history = ZabbixAPIHistory(self,**kwargs) self.id = 0 self.debug(logging.INFO, "url: "+ self.url) @@ -3119,3 +3120,13 @@ def resolveItem(self,**opts): """ """ return opts + +class ZabbixAPIHistory(ZabbixAPISubClass): + @dojson('history.get') + @checkauth + def get(self,**opts): + return opts + @dojson('history.delete') + @checkauth + def delete(self,**opts): + return opts From 04f85b2fe41459d2eca402e4a66541a20b5e2d65 Mon Sep 17 00:00:00 2001 From: gescheit Date: Tue, 15 Feb 2011 09:52:28 +0300 Subject: [PATCH 02/84] update usergroup functions to current --- zabbix/zabbix_api.py | 146 ++++++------------------------------------- 1 file changed, 19 insertions(+), 127 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index bd86b00..d480e71 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -929,140 +929,35 @@ def get(self,**opts): """ return opts - @dojson('usergroup.getObjects') + @dojson('usergroup.create') @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 -""" + def create(self,**opts): return opts - - @dojson('usergroup.add') + + @dojson('usergroup.exists') @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 -""" + def exists(self,**opts): return opts - - @dojson('usergroup.update') + + @dojson('usergroup.massAdd') @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 -""" + def massAdd(self,**opts): return opts - - @dojson('usergroup.updateRights') + + @dojson('usergroup.massRemove') @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 -""" + def massRemove(self,**opts): return opts - - @dojson('usergroup.addRights') + + @dojson('usergroup.massUpdate') @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 -""" + def massUpdate(self,**opts): 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') + @dojson('usergroup.update') @checkauth - def removeUsers(self,**opts): - """ * Remove users from UserGroup. + def update(self,**opts): + """ * Update UserGroups. * * {@source} * @access public @@ -1070,14 +965,11 @@ def removeUsers(self,**opts): * @since 1.8 * @version 1 * - * @param $usrgrps[0,...]['usrgrps'] - * @param $users[0,...]['users'] - * - * @param array $data + * @param array $groups multidimensional array with UserGroups data * @return boolean """ return opts - + @dojson('usergroup.delete') @checkauth def delete(self,**opts): From 203ae7bbbb47c38a88b00944746cf92ee4f4f74e Mon Sep 17 00:00:00 2001 From: gescheit Date: Wed, 6 Apr 2011 10:35:35 +0400 Subject: [PATCH 03/84] added Already_Exists exception --- zabbix/zabbix_api.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index d480e71..709b856 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -58,6 +58,9 @@ class ZabbixAPIException(Exception): """ pass +class Already_Exists(ZabbixAPIException): + pass + class InvalidProtoError(ZabbixAPIException): """ Recived an invalid proto """ pass @@ -245,10 +248,13 @@ def do_request(self, json_obj): self.id += 1 - if 'error' in jobj: + if 'error' in jobj: # some exception msg = "Error %s: %s, %s" % (jobj['error']['code'], jobj['error']['message'], jobj['error']['data']) - raise ZabbixAPIException(msg,jobj['error']['code']) + if int(jobj["error"]["code"]) == -32602: # already exists + raise Already_Exists(msg,jobj['error']['code']) + else: + raise ZabbixAPIException(msg,jobj['error']['code']) return jobj def logged_in(self): From bfcf2a15ab9594f4e38d31e30db3d3308c8bb565 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Thu, 5 May 2011 14:06:55 +0400 Subject: [PATCH 04/84] added timeout variable for urllib2 added "maintenance" "screen" improved --- zabbix/zabbix_api.py | 115 +++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 74 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 709b856..ee1bc37 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -28,13 +28,12 @@ import base64 import hashlib -import httplib import logging import string import sys import urllib2 -import urllib import json +import re from socket import gaierror default_log_handler = logging.StreamHandler(sys.stdout) @@ -54,7 +53,8 @@ class ZabbixAPIException(Exception): """ generic zabbix api exception code list: - -32602 - already exists + -32602 - Invalid params (eg already exists) + -32500 - no permissions """ pass @@ -79,7 +79,7 @@ class ZabbixAPI(object): # HTTP authentication httpuser = None httppasswd = None - + timeout = 10 # sub-class instances. user = None usergroup = None @@ -101,11 +101,10 @@ class ZabbixAPI(object): # 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): + def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, log_level = logging.WARNING, timeout = 10, **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] @@ -136,12 +135,13 @@ def __init__( self, server='http://localhost/zabbix',user=None,passwd=None, log_ #self.map = ZabbixAPIMap(self,**kwargs) self.drule = ZabbixAPIDRule(self,**kwargs) self.history = ZabbixAPIHistory(self,**kwargs) + self.maintenance = ZabbixAPIMaintenance(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__) + 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) @@ -216,7 +216,6 @@ def do_request(self, 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) @@ -227,7 +226,7 @@ def do_request(self, json_obj): raise ZabbixAPIException("Unknow protocol %s"%self.proto) urllib2.install_opener(opener) - response=opener.open(request,timeout=50) + response=opener.open(request, timeout = self.timeout) self.debug(logging.INFO, "Response Code: " + str(response.code)) @@ -249,9 +248,9 @@ def do_request(self, json_obj): self.id += 1 if 'error' in jobj: # some exception - msg = "Error %s: %s, %s" % (jobj['error']['code'], - jobj['error']['message'], jobj['error']['data']) - if int(jobj["error"]["code"]) == -32602: # already exists + 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']) @@ -2532,23 +2531,14 @@ def get(self,**opts): """ return opts - @dojson('screen.add') + @dojson('screen.create') @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 -""" + def create(self,**opts): + return opts + + @dojson('screen.exists') + @checkauth + def exists(self,**opts): return opts @dojson('screen.update') @@ -2588,52 +2578,6 @@ def delete(self,**opts): """ 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') @@ -3028,3 +2972,26 @@ def get(self,**opts): @checkauth def delete(self,**opts): return opts + +class ZabbixAPIMaintenance(ZabbixAPISubClass): + @dojson('maintenance.create') + @checkauth + def create(self,**opts): + return opts + + @dojson('maintenance.delete') + @checkauth + def delete(self,**opts): + return opts + @dojson('maintenance.exists') + @checkauth + def exists(self,**opts): + return opts + @dojson('maintenance.get') + @checkauth + def get(self,**opts): + return opts + @dojson('maintenance.update') + @checkauth + def update(self,**opts): + return opts \ No newline at end of file From 840afd414a2346350055e3399d693218c4412c3f Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sat, 13 Aug 2011 19:10:52 +0400 Subject: [PATCH 05/84] urllib2 socket timeout fixed --- zabbix/zabbix_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index ee1bc37..aa8bfdf 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -111,7 +111,7 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, log #self.proto=proto self.httpuser=user self.httppasswd=passwd - + self.timeout = timeout self.user = ZabbixAPIUser(self,**kwargs) self.usergroup = ZabbixAPIUserGroup(self,**kwargs) self.host = ZabbixAPIHost(self,**kwargs) From 2e8e7bdb5d59223501d087fa096b1cd5bca28ea3 Mon Sep 17 00:00:00 2001 From: "Stanislav A. Kraev" Date: Thu, 18 Aug 2011 11:30:05 +0700 Subject: [PATCH 06/84] graph.add method renamed to graph.create In current api version no graph.add method defined http://www.zabbix.com/documentation/1.8/api/graph/create --- zabbix/zabbix_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index aa8bfdf..153d3d6 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -2121,9 +2121,9 @@ def getObjects(self,**opts): """ return opts - @dojson('graph.add') + @dojson('graph.create') @checkauth - def add(self,**opts): + def create(self,**opts): """ * Add graph * * @@ -2994,4 +2994,4 @@ def get(self,**opts): @dojson('maintenance.update') @checkauth def update(self,**opts): - return opts \ No newline at end of file + return opts From 6b6ddfd1b83cacfa68d7d4b812d7c65dbc589a96 Mon Sep 17 00:00:00 2001 From: Ryan Day Date: Tue, 23 Aug 2011 17:47:37 -0400 Subject: [PATCH 07/84] Add hostgroup exists call --- zabbix/zabbix_api.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index aa8bfdf..e1164d9 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -1131,6 +1131,27 @@ def massUpdate(self,**opts): """ return opts + @dojson('hostgroup.exists') + @checkauth + def exists(self,**opts): + """ * Check if HostGroups exists + * + * {@source} + * @access public + * @static + * @since 1.8.3 + * @version 1 + * + * @param array $data + * @param array $data['nodeids'] + * @param array $data['groupid'] + * @param array $data['name'] + * @return boolean +""" + print "Got RESULT" + print opts + return opts + class ZabbixAPIApplication(ZabbixAPISubClass): @dojson('application.get') @@ -2994,4 +3015,4 @@ def get(self,**opts): @dojson('maintenance.update') @checkauth def update(self,**opts): - return opts \ No newline at end of file + return opts From 195184aed9fc562f506a6b8344fe32b8f6824d70 Mon Sep 17 00:00:00 2001 From: Ryan Day Date: Tue, 23 Aug 2011 18:07:52 -0400 Subject: [PATCH 08/84] Add proxy API --- zabbix/zabbix_api.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index e1164d9..bd98261 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -136,6 +136,7 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, log self.drule = ZabbixAPIDRule(self,**kwargs) self.history = ZabbixAPIHistory(self,**kwargs) self.maintenance = ZabbixAPIMaintenance(self,**kwargs) + self.proxy = ZabbixAPIProxy(self,**kwargs) self.id = 0 self.debug(logging.INFO, "url: "+ self.url) @@ -2994,6 +2995,12 @@ def get(self,**opts): def delete(self,**opts): return opts +class ZabbixAPIProxy(ZabbixAPISubClass): + @dojson('proxy.get') + @checkauth + def get(self,**opts): + return opts + class ZabbixAPIMaintenance(ZabbixAPISubClass): @dojson('maintenance.create') @checkauth From 9b886a951aad7c2dedd9aa257b95826147544d6f Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 28 Aug 2011 02:51:22 +0400 Subject: [PATCH 09/84] added recent_query() function. this function return last query, depends on variable r_query_len. default 10 --- zabbix/zabbix_api.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index aa8bfdf..c33e838 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -35,6 +35,7 @@ import json import re from socket import gaierror +from collections import deque default_log_handler = logging.StreamHandler(sys.stdout) __logger = logging.getLogger("zabbix_api") @@ -100,8 +101,10 @@ class ZabbixAPI(object): # 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=None, passwd=None, log_level = logging.WARNING, timeout = 10, **kwargs): + def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, + log_level = logging.WARNING, timeout = 10, r_query_len = 10, **kwargs): """ Create an API object. """ self._setuplogging() self.set_log_level(log_level) @@ -137,9 +140,8 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, log self.history = ZabbixAPIHistory(self,**kwargs) self.maintenance = ZabbixAPIMaintenance(self,**kwargs) self.id = 0 - + self.r_query = deque([], maxlen = r_query_len) self.debug(logging.INFO, "url: "+ self.url) - def _setuplogging(self): self.logger = logging.getLogger("zabbix_api.%s" % self.__class__.__name__) @@ -147,6 +149,11 @@ 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: @@ -211,7 +218,7 @@ def do_request(self, json_obj): self.debug(logging.INFO,"HTTP Auth enabled") auth='Basic ' + string.strip(base64.encodestring(self.httpuser + ':' + self.httppasswd)) 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)) From 39951dfa6fa08eb266764ca69c80e47b9c36e275 Mon Sep 17 00:00:00 2001 From: Dale Bewley Date: Sat, 15 Oct 2011 08:32:09 -0700 Subject: [PATCH 10/84] remove scripts unrelated to Zabbix Python API --- cobbler/cobbler_mass_update.py | 237 --------------- ldap/parse_sudoers.py | 537 --------------------------------- yum_repo/libupdate.py | 202 ------------- yum_repo/trickle.py | 78 ----- 4 files changed, 1054 deletions(-) delete mode 100755 cobbler/cobbler_mass_update.py delete mode 100755 ldap/parse_sudoers.py delete mode 100644 yum_repo/libupdate.py delete mode 100755 yum_repo/trickle.py 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) - From 893ddc76be31714a8ff97db4a710a76ad0fd03cf Mon Sep 17 00:00:00 2001 From: Dale Bewley Date: Sat, 15 Oct 2011 08:46:41 -0700 Subject: [PATCH 11/84] brief intro and links to zabbix docs --- zabbix/README | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 zabbix/README diff --git a/zabbix/README b/zabbix/README new file mode 100644 index 0000000..1349d53 --- /dev/null +++ b/zabbix/README @@ -0,0 +1,11 @@ +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. + +See also: +* http://www.zabbix.com/wiki/doc/api +* http://www.zabbix.com/documentation/1.8/api +* http://www.zabbix.com/forum/showthread.php?t=15218 From 19f1834def2d0990c5b7417ac5e4ca5272ad5e45 Mon Sep 17 00:00:00 2001 From: Ewoud Kohl van Wijngaarden Date: Tue, 15 Nov 2011 12:36:42 +0100 Subject: [PATCH 12/84] Prefer simplejson over json Simplejson is faster so it should be prefered. --- zabbix/zabbix_api.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 306ae28..3be67bd 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -43,13 +43,13 @@ __logger.log(10,"Starting logging") try: - # Python 2.5+ - import json - __logger.log(15,"Using native json library") -except ImportError: - # Python 2.4 + # 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") class ZabbixAPIException(Exception): """ generic zabbix api exception From 9672cea28a1844a4ffb6ba2d0fb85bcfd0d6808e Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 20 Nov 2011 07:44:27 +0400 Subject: [PATCH 13/84] fixed usermacro functions --- zabbix/zabbix_api.py | 237 +++---------------------------------------- 1 file changed, 13 insertions(+), 224 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 306ae28..1de4a11 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -2744,253 +2744,42 @@ 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') + @dojson('usermacro.massAdd') @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 -""" + def massAdd(self,**opts): return opts - @dojson('usermacro.updateValue') + @dojson('usermacro.massUpdate') @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 -""" + def massUpdate(self,**opts): 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') + @dojson('usermacro.createGlobal') @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 -""" + def createGlobal(self,**opts): return opts - @dojson('usermacro.getMacros') + @dojson('usermacro.deleteGlobal') @checkauth - def getMacros(self,**opts): - """ -""" + def deleteGlobal(self,**opts): return opts - @dojson('usermacro.resolveTrigger') + @dojson('usermacro.massRemove') @checkauth - def resolveTrigger(self,**opts): - """ -""" + def massRemove(self,**opts): return opts - @dojson('usermacro.resolveItem') + @dojson('usermacro.updateGlobal') @checkauth - def resolveItem(self,**opts): - """ -""" - return opts + def updateGlobal(self,**opts): + return opts class ZabbixAPIHistory(ZabbixAPISubClass): @dojson('history.get') From e4686402a26136852aad82188a8b09321a99dcf1 Mon Sep 17 00:00:00 2001 From: romeotheriault Date: Tue, 22 Nov 2011 15:10:51 -1000 Subject: [PATCH 14/84] Change user.add api method to user.create since the api method is now user.create. --- zabbix/zabbix_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 1de4a11..db4a60e 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -388,9 +388,9 @@ def getObjects(self,**opts): * @return string|boolean """ return opts - @dojson('user.add') + @dojson('user.create') @checkauth - def add(self,**opts): + def create(self,**opts): """ * Add Users * * {@source} From 0b216bdcdeae056bd6552ffa47682e8406d4a1f4 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Thu, 1 Dec 2011 15:50:43 +0400 Subject: [PATCH 15/84] Introduced new schema with one function for all methods in class. Instead of implementing all API's calls in dedicated functions, one function will call API's method. So don't need write function for each API function. Used only in item API --- zabbix/zabbix_api.py | 144 +++++-------------------------------------- 1 file changed, 16 insertions(+), 128 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 78466de..c354b18 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -318,6 +318,14 @@ def wrapper(self,opts): return wrapper return decorator +def dojson2(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 + class ZabbixAPIUser(ZabbixAPISubClass): @dojson('user.get') @checkauth @@ -782,136 +790,16 @@ def delete(self,**opts): 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 + def __getattr__(self, name): + def method(*opts): + self.universal("item.%s" % name, opts) + return method - @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') + @dojson2 @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 - + def universal(self,**opts): + return opt + class ZabbixAPIUserGroup(ZabbixAPISubClass): @dojson('usergroup.get') From 4ff1238296d7f5de9684ccc6ebd5c70b21ec2e5e Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Thu, 1 Dec 2011 16:49:53 +0400 Subject: [PATCH 16/84] fixed result not returned in item calls --- zabbix/zabbix_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index c354b18..e39f086 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -792,7 +792,7 @@ def delete(self,**opts): class ZabbixAPIItem(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): - self.universal("item.%s" % name, opts) + return self.universal("item.%s" % name, opts) return method @dojson2 From c7ededdc05f8e1c24330a60de8069af3c762b3ce Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Thu, 1 Dec 2011 19:07:34 +0400 Subject: [PATCH 17/84] fixed list instead of dictionary in opts in API item --- zabbix/zabbix_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index e39f086..a029a0d 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -792,7 +792,7 @@ def delete(self,**opts): class ZabbixAPIItem(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): - return self.universal("item.%s" % name, opts) + return self.universal("item.%s" % name, opts[0]) return method @dojson2 From 7b854d9865068a3ce2e0f9ed85fd55ae544e7b3b Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Thu, 1 Dec 2011 22:27:54 +0400 Subject: [PATCH 18/84] added new universal method in API Host --- zabbix/zabbix_api.py | 63 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index a029a0d..f361d1f 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -51,6 +51,31 @@ 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(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 + +def dojson2(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 + class ZabbixAPIException(Exception): """ generic zabbix api exception code list: @@ -301,30 +326,13 @@ def do_request(self, 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 + @dojson2 + @checkauth + def universal(self, **opts): + return opt + -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 -def dojson2(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 class ZabbixAPIUser(ZabbixAPISubClass): @dojson('user.get') @@ -580,6 +588,11 @@ def updateMedia(self,**opts): class ZabbixAPIHost(ZabbixAPISubClass): + def __getattr__(self, name): + def method(*opts): + return self.universal("item.%s" % name, opts[0]) + return method + @dojson('host.get') @checkauth def get(self,**opts): @@ -795,11 +808,7 @@ def method(*opts): return self.universal("item.%s" % name, opts[0]) return method - @dojson2 - @checkauth - def universal(self,**opts): - return opt - +# class ZabbixAPIUserGroup(ZabbixAPISubClass): @dojson('usergroup.get') From 207d33bd3eccea2e0ff16371082cdb298cd03c9b Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 4 Dec 2011 10:52:50 +0400 Subject: [PATCH 19/84] chaned all ZabbixAPI classes to new style remove unused class systemmap --- zabbix/zabbix_api.py | 2423 ++---------------------------------------- 1 file changed, 84 insertions(+), 2339 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index f361d1f..e70fa37 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -147,7 +147,6 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, 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) @@ -160,7 +159,6 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, 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.history = ZabbixAPIHistory(self,**kwargs) self.maintenance = ZabbixAPIMaintenance(self,**kwargs) @@ -332,2387 +330,134 @@ def universal(self, **opts): return opt - - 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.create') - @checkauth - def create(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 + def __getattr__(self, name): + def method(*opts): + return self.universal("user.%s" % name, opts[0]) + return method class ZabbixAPIHost(ZabbixAPISubClass): - def __getattr__(self, name): def method(*opts): - return self.universal("item.%s" % name, opts[0]) + return self.universal("host.%s" % name, opts[0]) return method - @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): def __getattr__(self, name): def method(*opts): return self.universal("item.%s" % name, opts[0]) return method -# 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.create') - @checkauth - def create(self,**opts): - return opts - - @dojson('usergroup.exists') - @checkauth - def exists(self,**opts): - return opts - - @dojson('usergroup.massAdd') - @checkauth - def massAdd(self,**opts): - return opts - - @dojson('usergroup.massRemove') - @checkauth - def massRemove(self,**opts): - return opts - - @dojson('usergroup.massUpdate') - @checkauth - def massUpdate(self,**opts): - 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.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 -""" + def __getattr__(self, name): + def method(*opts): + return self.universal("usergroup.%s" % name, opts[0]) + return method 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 - - @dojson('hostgroup.exists') - @checkauth - def exists(self,**opts): - """ * Check if HostGroups exists - * - * {@source} - * @access public - * @static - * @since 1.8.3 - * @version 1 - * - * @param array $data - * @param array $data['nodeids'] - * @param array $data['groupid'] - * @param array $data['name'] - * @return boolean -""" - print "Got RESULT" - print opts - return opts - + def __getattr__(self, name): + def method(*opts): + return self.universal("hostgroup.%s" % name, opts[0]) + return method + 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("application.%s" % name, opts[0]) + return method class ZabbixAPITrigger(ZabbixAPISubClass): + def __getattr__(self, name): + def method(*opts): + return self.universal("trigger.%s" % name, opts[0]) + return method - @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 ZabbixAPIMap(ZabbixAPISubClass): + def __getattr__(self, name): + def method(*opts): + return self.universal("map.%s" % name, opts[0]) + return method 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("template.%s" % name, opts[0]) + return method 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("action.%s" % name, opts[0]) + return method 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("alert.%s" % name, opts[0]) + return method 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("apiinfo.%s" % name, opts[0]) + return method 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("event.%s" % name, opts[0]) + return method 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.create') - @checkauth - def create(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 + def __getattr__(self, name): + def method(*opts): + return self.universal("graph.%s" % name, opts[0]) + return method 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 + def __getattr__(self, name): + def method(*opts): + return self.universal("graphitem.%s" % name, opts[0]) + return method 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.create') - @checkauth - def create(self,**opts): - return opts - - @dojson('screen.exists') - @checkauth - def exists(self,**opts): - 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 - + def __getattr__(self, name): + def method(*opts): + return self.universal("screen.%s" % name, opts[0]) + return method 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 - + def __getattr__(self, name): + def method(*opts): + return self.universal("script.%s" % name, opts[0]) + return method 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): - return opts - - @dojson('usermacro.massAdd') - @checkauth - def massAdd(self,**opts): - return opts - - @dojson('usermacro.massUpdate') - @checkauth - def massUpdate(self,**opts): - return opts - - @dojson('usermacro.deleteHostMacro') - @checkauth - def deleteHostMacro(self,**opts): - return opts - - @dojson('usermacro.createGlobal') - @checkauth - def createGlobal(self,**opts): - return opts - - @dojson('usermacro.deleteGlobal') - @checkauth - def deleteGlobal(self,**opts): - return opts + def __getattr__(self, name): + def method(*opts): + return self.universal("drule.%s" % name, opts[0]) + return method - @dojson('usermacro.massRemove') - @checkauth - def massRemove(self,**opts): - return opts +class ZabbixAPIUserMacro(ZabbixAPISubClass): + def __getattr__(self, name): + def method(*opts): + return self.universal("usermacro.%s" % name, opts[0]) + return method - @dojson('usermacro.updateGlobal') - @checkauth - def updateGlobal(self,**opts): - return opts - class ZabbixAPIHistory(ZabbixAPISubClass): - @dojson('history.get') - @checkauth - def get(self,**opts): - return opts - @dojson('history.delete') - @checkauth - def delete(self,**opts): - return opts + def __getattr__(self, name): + def method(*opts): + return self.universal("history.%s" % name, opts[0]) + return method class ZabbixAPIProxy(ZabbixAPISubClass): - @dojson('proxy.get') - @checkauth - def get(self,**opts): - return opts + def __getattr__(self, name): + def method(*opts): + return self.universal("proxy.%s" % name, opts[0]) + return method class ZabbixAPIMaintenance(ZabbixAPISubClass): - @dojson('maintenance.create') - @checkauth - def create(self,**opts): - return opts - - @dojson('maintenance.delete') - @checkauth - def delete(self,**opts): - return opts - @dojson('maintenance.exists') - @checkauth - def exists(self,**opts): - return opts - @dojson('maintenance.get') - @checkauth - def get(self,**opts): - return opts - @dojson('maintenance.update') - @checkauth - def update(self,**opts): - return opts + def __getattr__(self, name): + def method(*opts): + return self.universal("maintenance.%s" % name, opts[0]) + return method From b393d81ff706e1161894a1bb922bf70fd2c6b79b Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 4 Dec 2011 12:31:25 +0400 Subject: [PATCH 20/84] pep8 compliant --- zabbix/zabbix_api.py | 203 +++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 86 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index e70fa37..786d222 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -40,42 +40,46 @@ default_log_handler = logging.StreamHandler(sys.stdout) __logger = logging.getLogger("zabbix_api") __logger.addHandler(default_log_handler) -__logger.log(10,"Starting logging") +__logger.log(10, "Starting logging") try: # Separate module or Python <2.6 import simplejson as json - __logger.log(15,"Using simplejson library") + __logger.log(15, "Using simplejson library") except ImportError: # Python >=2.6 import json - __logger.log(15,"Using native json library") + __logger.log(15, "Using native json library") + def checkauth(fn): """ Decorator to check authentication of the decorated method """ - def ret(self,*args): + def ret(self, *args): self.__checkauth__() - return fn(self,args) + return fn(self, args) return ret + def dojson(name): def decorator(fn): - def wrapper(self,opts): + 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'] + % (repr(fn), repr(opts))) + return self.do_request(self.json_obj(name, opts))['result'] return wrapper return decorator + def dojson2(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'] + % (repr(fn), repr(opts))) + return self.do_request(self.json_obj(method, opts))['result'] return wrapper + class ZabbixAPIException(Exception): """ generic zabbix api exception code list: @@ -84,13 +88,16 @@ class ZabbixAPIException(Exception): """ pass + class Already_Exists(ZabbixAPIException): pass + class InvalidProtoError(ZabbixAPIException): """ Recived an invalid proto """ pass + class ZabbixAPI(object): __username__ = '' __password__ = '' @@ -128,44 +135,46 @@ class ZabbixAPI(object): # 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=None, passwd=None, - log_level = logging.WARNING, timeout = 10, r_query_len = 10, **kwargs): + + def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, + log_level=logging.WARNING, timeout=10, r_query_len=10, **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.server = server + self.url = server + '/api_jsonrpc.php' + self.proto = self.server.split("://")[0] #self.proto=proto - self.httpuser=user - self.httppasswd=passwd + self.httpuser = user + self.httppasswd = passwd self.timeout = timeout - 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.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.drule = ZabbixAPIDRule(self,**kwargs) - self.history = ZabbixAPIHistory(self,**kwargs) - self.maintenance = ZabbixAPIMaintenance(self,**kwargs) - self.proxy = ZabbixAPIProxy(self,**kwargs) + 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.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.drule = ZabbixAPIDRule(self, **kwargs) + self.history = ZabbixAPIHistory(self, **kwargs) + self.maintenance = ZabbixAPIMaintenance(self, **kwargs) + self.proxy = ZabbixAPIProxy(self, **kwargs) self.id = 0 - self.r_query = deque([], maxlen = r_query_len) - self.debug(logging.INFO, "url: "+ self.url) + self.r_query = deque([], maxlen=r_query_len) + self.debug(logging.INFO, "url: " + self.url) + def _setuplogging(self): self.logger = logging.getLogger("zabbix_api.%s" % self.__class__.__name__) @@ -176,8 +185,9 @@ def set_log_level(self, 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: @@ -185,14 +195,14 @@ def debug(self, level, var="", msg=None): if var != "": strval = strval + str(var) - self.logger.log(level,strval) + 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 + obj = {'jsonrpc' : '2.0', + 'method' : method, + 'params' : params, + 'auth' : self.auth, + 'id' : self.id } self.debug(logging.DEBUG, "json_obj: " + str(obj)) @@ -215,50 +225,49 @@ def login(self, user='', password='', save=True): # 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, + 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}) + 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 + 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' } + 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)) + self.debug(logging.INFO, "HTTP Auth enabled") + auth = 'Basic ' + string.strip(base64.encodestring(self.httpuser + ':' + self.httppasswd)) 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,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) + 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) - + raise ZabbixAPIException("Unknow protocol %s" % self.proto) + urllib2.install_opener(opener) - response=opener.open(request, timeout = self.timeout) - + response = opener.open(request, timeout=self.timeout) self.debug(logging.INFO, "Response Code: " + str(response.code)) # NOTE: Getting a 412 response code means the headers are not in the @@ -266,13 +275,13 @@ def do_request(self, json_obj): if response.code != 200: raise ZabbixAPIException("HTTP ERROR %s: %s" % (response.status, response.reason)) - reads=response.read() - if len(reads)==0: + 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 + except ValueError, msg: + print "unable to decode. returned string: %s" % reads sys.exit(-1) self.debug(logging.DEBUG, "Response Body: " + str(jobj)) @@ -280,11 +289,11 @@ def do_request(self, json_obj): 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']) + 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']) + raise ZabbixAPIException(msg, jobj['error']['code']) return jobj def logged_in(self): @@ -301,19 +310,20 @@ 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.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))) + # 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__() @@ -328,7 +338,7 @@ def json_obj(self, method, param): @checkauth def universal(self, **opts): return opt - + class ZabbixAPIUser(ZabbixAPISubClass): def __getattr__(self, name): @@ -336,126 +346,147 @@ def method(*opts): return self.universal("user.%s" % name, opts[0]) return method + class ZabbixAPIHost(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("host.%s" % name, opts[0]) return method + class ZabbixAPIItem(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("item.%s" % name, opts[0]) return method - + + class ZabbixAPIUserGroup(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("usergroup.%s" % name, opts[0]) return method + class ZabbixAPIHostGroup(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("hostgroup.%s" % name, opts[0]) return method - + + class ZabbixAPIApplication(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("application.%s" % name, opts[0]) return method + class ZabbixAPITrigger(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("trigger.%s" % name, opts[0]) return method + class ZabbixAPIMap(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("map.%s" % name, opts[0]) return method + class ZabbixAPITemplate(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("template.%s" % name, opts[0]) return method + class ZabbixAPIAction(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("action.%s" % name, opts[0]) return method + class ZabbixAPIAlert(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("alert.%s" % name, opts[0]) return method + class ZabbixAPIInfo(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("apiinfo.%s" % name, opts[0]) return method + class ZabbixAPIEvent(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("event.%s" % name, opts[0]) return method + class ZabbixAPIGraph(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("graph.%s" % name, opts[0]) return method + class ZabbixAPIGraphItem(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("graphitem.%s" % name, opts[0]) return method + class ZabbixAPIScreen(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("screen.%s" % name, opts[0]) return method + class ZabbixAPIScript(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("script.%s" % name, opts[0]) return method + class ZabbixAPIDRule(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("drule.%s" % name, opts[0]) return method + class ZabbixAPIUserMacro(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("usermacro.%s" % name, opts[0]) return method + class ZabbixAPIHistory(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("history.%s" % name, opts[0]) return method + class ZabbixAPIProxy(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): return self.universal("proxy.%s" % name, opts[0]) return method + class ZabbixAPIMaintenance(ZabbixAPISubClass): def __getattr__(self, name): def method(*opts): From 02ce3f515f5cb9910a87e60b169f8f94e746fb3d Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Wed, 28 Dec 2011 17:44:56 +0400 Subject: [PATCH 21/84] initial support of python3 --- zabbix/zabbix_api.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 786d222..3261f08 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -31,10 +31,11 @@ import logging import string import sys -import urllib2 -import json +try: + import urllib2 +except ImportError: + import urllib.request as urllib2 # python3 import re -from socket import gaierror from collections import deque default_log_handler = logging.StreamHandler(sys.stdout) @@ -103,7 +104,6 @@ class ZabbixAPI(object): __password__ = '' auth = '' - id = 0 url = '/api_jsonrpc.php' params = None method = None @@ -224,7 +224,7 @@ def login(self, user='', password='', save=True): raise ZabbixAPIException("No authentication information available.") # don't print the raw password. - hashed_pw_string = "md5(" + hashlib.md5(l_password).hexdigest() + ")" + 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))) obj = self.json_obj('user.authenticate', {'user': l_user, @@ -256,7 +256,7 @@ def do_request(self, 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, headers=headers) + request = urllib2.Request(url=self.url, data=json_obj.encode('utf-8'), headers=headers) if self.proto == "https": https_handler = urllib2.HTTPSHandler(debuglevel=0) opener = urllib2.build_opener(https_handler) @@ -279,9 +279,9 @@ def do_request(self, json_obj): 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 + 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)) @@ -337,7 +337,7 @@ def json_obj(self, method, param): @dojson2 @checkauth def universal(self, **opts): - return opt + return opts class ZabbixAPIUser(ZabbixAPISubClass): From f602004ba1c7ad4698fd4d9937ef868bce757aba Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Fri, 6 Jan 2012 19:42:38 +0400 Subject: [PATCH 22/84] __getattr__ moved to parent class --- zabbix/zabbix_api.py | 105 +++++++++++-------------------------------- 1 file changed, 25 insertions(+), 80 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 3261f08..33cd71c 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -325,6 +325,11 @@ def __init__(self, parent, **kwargs): setattr(self, key, val) self.debug(logging.WARNING, "Set %s:%s" % (repr(key), repr(val))) + def __getattr__(self, name): + def method(*opts): + return self.universal("%s.%s" % (self.prefix, name), opts[0]) + return method + def __checkauth__(self): self.parent.__checkauth__() @@ -355,140 +360,80 @@ def method(*opts): class ZabbixAPIItem(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("item.%s" % name, opts[0]) - return method + prefix = "item" class ZabbixAPIUserGroup(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("usergroup.%s" % name, opts[0]) - return method + prefix = "usergroup" class ZabbixAPIHostGroup(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("hostgroup.%s" % name, opts[0]) - return method + prefix = "hostgroup" class ZabbixAPIApplication(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("application.%s" % name, opts[0]) - return method + prefix = "application" class ZabbixAPITrigger(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("trigger.%s" % name, opts[0]) - return method + prefix = "trigger" class ZabbixAPIMap(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("map.%s" % name, opts[0]) - return method + prefix = "map" class ZabbixAPITemplate(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("template.%s" % name, opts[0]) - return method + prefix = "template" class ZabbixAPIAction(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("action.%s" % name, opts[0]) - return method + prefix = "action" class ZabbixAPIAlert(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("alert.%s" % name, opts[0]) - return method + prefix = "alert" class ZabbixAPIInfo(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("apiinfo.%s" % name, opts[0]) - return method + prefix = "apiinfo" class ZabbixAPIEvent(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("event.%s" % name, opts[0]) - return method + prefix = "event" class ZabbixAPIGraph(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("graph.%s" % name, opts[0]) - return method + prefix = "graph" class ZabbixAPIGraphItem(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("graphitem.%s" % name, opts[0]) - return method + prefix = "graphitem" class ZabbixAPIScreen(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("screen.%s" % name, opts[0]) - return method + prefix = "screen" class ZabbixAPIScript(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("script.%s" % name, opts[0]) - return method + prefix = "script" class ZabbixAPIDRule(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("drule.%s" % name, opts[0]) - return method + prefix = "drule" class ZabbixAPIUserMacro(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("usermacro.%s" % name, opts[0]) - return method + prefix = "usermacro" class ZabbixAPIHistory(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("history.%s" % name, opts[0]) - return method + prefix = "history" class ZabbixAPIProxy(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("proxy.%s" % name, opts[0]) - return method + prefix = "proxy" class ZabbixAPIMaintenance(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("maintenance.%s" % name, opts[0]) - return method + prefix = "maintenance" From bc8b63f479934ef80e81f17cf495d408adbc6ca4 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sat, 7 Jan 2012 01:09:42 +0400 Subject: [PATCH 23/84] use ZabbixAPISubClass with parameters instead inheritance --- zabbix/zabbix_api.py | 149 ++++++++----------------------------------- 1 file changed, 28 insertions(+), 121 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 33cd71c..8aa16fe 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -148,29 +148,29 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, self.httpuser = user self.httppasswd = passwd self.timeout = timeout - 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.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.drule = ZabbixAPIDRule(self, **kwargs) - self.history = ZabbixAPIHistory(self, **kwargs) - self.maintenance = ZabbixAPIMaintenance(self, **kwargs) - self.proxy = ZabbixAPIProxy(self, **kwargs) + self.usergroup = ZabbixAPISubClass(self, dict({"prefix":"usergroup"}, **kwargs)) + self.user = ZabbixAPISubClass(self, dict({"prefix":"user"}, **kwargs)) + self.host = ZabbixAPISubClass(self, dict({"prefix":"host"}, **kwargs)) + self.item = ZabbixAPISubClass(self, dict({"prefix":"item"}, **kwargs)) + self.hostgroup = ZabbixAPISubClass(self, dict({"prefix":"hostgroup"}, **kwargs)) + self.application = ZabbixAPISubClass(self, dict({"prefix":"application"}, **kwargs)) + self.trigger = ZabbixAPISubClass(self, dict({"prefix":"trigger"}, **kwargs)) + self.template = ZabbixAPISubClass(self, dict({"prefix":"template"}, **kwargs)) + self.action = ZabbixAPISubClass(self, dict({"prefix":"action"}, **kwargs)) + self.alert = ZabbixAPISubClass(self, dict({"prefix":"alert"}, **kwargs)) + self.info = ZabbixAPISubClass(self, dict({"prefix":"info"}, **kwargs)) + self.event = ZabbixAPISubClass(self, dict({"prefix":"event"}, **kwargs)) + self.graph = ZabbixAPISubClass(self, dict({"prefix":"graph"}, **kwargs)) + self.graphitem = ZabbixAPISubClass(self, dict({"prefix":"graphitem"}, **kwargs)) + self.map = ZabbixAPISubClass(self, dict({"prefix":"map"}, **kwargs)) + self.screen = ZabbixAPISubClass(self, dict({"prefix":"screen"}, **kwargs)) + self.script = ZabbixAPISubClass(self, dict({"prefix":"script"}, **kwargs)) + self.usermacro = ZabbixAPISubClass(self, dict({"prefix":"usermacro"}, **kwargs)) + self.map = ZabbixAPISubClass(self, dict({"prefix":"map"}, **kwargs)) + self.drule = ZabbixAPISubClass(self, dict({"prefix":"drule"}, **kwargs)) + self.history = ZabbixAPISubClass(self, dict({"prefix":"history"}, **kwargs)) + self.maintenance = ZabbixAPISubClass(self, dict({"prefix":"maintenance"}, **kwargs)) + self.proxy = ZabbixAPISubClass(self, dict({"prefix":"proxy"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) @@ -314,12 +314,13 @@ def __checkauth__(self): class ZabbixAPISubClass(ZabbixAPI): """ wrapper class to ensure all calls go through the parent object """ parent = None - - def __init__(self, parent, **kwargs): + 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) @@ -327,7 +328,7 @@ def __init__(self, parent, **kwargs): def __getattr__(self, name): def method(*opts): - return self.universal("%s.%s" % (self.prefix, name), opts[0]) + return self.universal("%s.%s" % (self.data["prefix"], name), opts[0]) return method def __checkauth__(self): @@ -343,97 +344,3 @@ def json_obj(self, method, param): @checkauth def universal(self, **opts): return opts - - -class ZabbixAPIUser(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("user.%s" % name, opts[0]) - return method - - -class ZabbixAPIHost(ZabbixAPISubClass): - def __getattr__(self, name): - def method(*opts): - return self.universal("host.%s" % name, opts[0]) - return method - - -class ZabbixAPIItem(ZabbixAPISubClass): - prefix = "item" - - -class ZabbixAPIUserGroup(ZabbixAPISubClass): - prefix = "usergroup" - - -class ZabbixAPIHostGroup(ZabbixAPISubClass): - prefix = "hostgroup" - - -class ZabbixAPIApplication(ZabbixAPISubClass): - prefix = "application" - - -class ZabbixAPITrigger(ZabbixAPISubClass): - prefix = "trigger" - - -class ZabbixAPIMap(ZabbixAPISubClass): - prefix = "map" - - -class ZabbixAPITemplate(ZabbixAPISubClass): - prefix = "template" - - -class ZabbixAPIAction(ZabbixAPISubClass): - prefix = "action" - - -class ZabbixAPIAlert(ZabbixAPISubClass): - prefix = "alert" - - -class ZabbixAPIInfo(ZabbixAPISubClass): - prefix = "apiinfo" - - -class ZabbixAPIEvent(ZabbixAPISubClass): - prefix = "event" - - -class ZabbixAPIGraph(ZabbixAPISubClass): - prefix = "graph" - - -class ZabbixAPIGraphItem(ZabbixAPISubClass): - prefix = "graphitem" - - -class ZabbixAPIScreen(ZabbixAPISubClass): - prefix = "screen" - - -class ZabbixAPIScript(ZabbixAPISubClass): - prefix = "script" - - -class ZabbixAPIDRule(ZabbixAPISubClass): - prefix = "drule" - - -class ZabbixAPIUserMacro(ZabbixAPISubClass): - prefix = "usermacro" - - -class ZabbixAPIHistory(ZabbixAPISubClass): - prefix = "history" - - -class ZabbixAPIProxy(ZabbixAPISubClass): - prefix = "proxy" - - -class ZabbixAPIMaintenance(ZabbixAPISubClass): - prefix = "maintenance" From d38ad49a801e601cf80cf36abc36928a0224ec2f Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sat, 7 Jan 2012 01:16:52 +0400 Subject: [PATCH 24/84] cleanup and PEP8 complaint --- zabbix/zabbix_api.py | 69 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 8aa16fe..87424a7 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -148,29 +148,29 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, self.httpuser = user self.httppasswd = passwd self.timeout = timeout - self.usergroup = ZabbixAPISubClass(self, dict({"prefix":"usergroup"}, **kwargs)) - self.user = ZabbixAPISubClass(self, dict({"prefix":"user"}, **kwargs)) - self.host = ZabbixAPISubClass(self, dict({"prefix":"host"}, **kwargs)) - self.item = ZabbixAPISubClass(self, dict({"prefix":"item"}, **kwargs)) - self.hostgroup = ZabbixAPISubClass(self, dict({"prefix":"hostgroup"}, **kwargs)) - self.application = ZabbixAPISubClass(self, dict({"prefix":"application"}, **kwargs)) - self.trigger = ZabbixAPISubClass(self, dict({"prefix":"trigger"}, **kwargs)) - self.template = ZabbixAPISubClass(self, dict({"prefix":"template"}, **kwargs)) - self.action = ZabbixAPISubClass(self, dict({"prefix":"action"}, **kwargs)) - self.alert = ZabbixAPISubClass(self, dict({"prefix":"alert"}, **kwargs)) - self.info = ZabbixAPISubClass(self, dict({"prefix":"info"}, **kwargs)) - self.event = ZabbixAPISubClass(self, dict({"prefix":"event"}, **kwargs)) - self.graph = ZabbixAPISubClass(self, dict({"prefix":"graph"}, **kwargs)) - self.graphitem = ZabbixAPISubClass(self, dict({"prefix":"graphitem"}, **kwargs)) - self.map = ZabbixAPISubClass(self, dict({"prefix":"map"}, **kwargs)) - self.screen = ZabbixAPISubClass(self, dict({"prefix":"screen"}, **kwargs)) - self.script = ZabbixAPISubClass(self, dict({"prefix":"script"}, **kwargs)) - self.usermacro = ZabbixAPISubClass(self, dict({"prefix":"usermacro"}, **kwargs)) - self.map = ZabbixAPISubClass(self, dict({"prefix":"map"}, **kwargs)) - self.drule = ZabbixAPISubClass(self, dict({"prefix":"drule"}, **kwargs)) - self.history = ZabbixAPISubClass(self, dict({"prefix":"history"}, **kwargs)) - self.maintenance = ZabbixAPISubClass(self, dict({"prefix":"maintenance"}, **kwargs)) - self.proxy = ZabbixAPISubClass(self, dict({"prefix":"proxy"}, **kwargs)) + self.usergroup = ZabbixAPISubClass(self, dict({"prefix": "usergroup"}, **kwargs)) + self.user = ZabbixAPISubClass(self, dict({"prefix": "user"}, **kwargs)) + self.host = ZabbixAPISubClass(self, dict({"prefix": "host"}, **kwargs)) + self.item = ZabbixAPISubClass(self, dict({"prefix": "item"}, **kwargs)) + self.hostgroup = ZabbixAPISubClass(self, dict({"prefix": "hostgroup"}, **kwargs)) + self.application = ZabbixAPISubClass(self, dict({"prefix": "application"}, **kwargs)) + self.trigger = ZabbixAPISubClass(self, dict({"prefix": "trigger"}, **kwargs)) + self.template = ZabbixAPISubClass(self, dict({"prefix": "template"}, **kwargs)) + self.action = ZabbixAPISubClass(self, dict({"prefix": "action"}, **kwargs)) + self.alert = ZabbixAPISubClass(self, dict({"prefix": "alert"}, **kwargs)) + self.info = ZabbixAPISubClass(self, dict({"prefix": "info"}, **kwargs)) + self.event = ZabbixAPISubClass(self, dict({"prefix": "event"}, **kwargs)) + self.graph = ZabbixAPISubClass(self, dict({"prefix": "graph"}, **kwargs)) + self.graphitem = ZabbixAPISubClass(self, dict({"prefix": "graphitem"}, **kwargs)) + self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) + self.screen = ZabbixAPISubClass(self, dict({"prefix": "screen"}, **kwargs)) + self.script = ZabbixAPISubClass(self, dict({"prefix": "script"}, **kwargs)) + self.usermacro = ZabbixAPISubClass(self, dict({"prefix": "usermacro"}, **kwargs)) + self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) + self.drule = ZabbixAPISubClass(self, dict({"prefix": "drule"}, **kwargs)) + self.history = ZabbixAPISubClass(self, dict({"prefix": "history"}, **kwargs)) + self.maintenance = ZabbixAPISubClass(self, dict({"prefix": "maintenance"}, **kwargs)) + self.proxy = ZabbixAPISubClass(self, dict({"prefix": "proxy"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) @@ -198,11 +198,11 @@ def debug(self, level, var="", msg=None): 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 + obj = {'jsonrpc': '2.0', + 'method': method, + 'params': params, + 'auth': self.auth, + 'id': self.id } self.debug(logging.DEBUG, "json_obj: " + str(obj)) @@ -228,7 +228,7 @@ def login(self, user='', password='', save=True): 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 }) + 'password': l_password}) result = self.do_request(obj) self.auth = result['result'] @@ -245,8 +245,8 @@ def test_login(self): return False def do_request(self, json_obj): - headers = {'Content-Type' : 'application/json-rpc', - 'User-Agent' : 'python/zabbix_api' } + headers = {'Content-Type': 'application/json-rpc', + 'User-Agent': 'python/zabbix_api'} if self.httpuser: self.debug(logging.INFO, "HTTP Auth enabled") @@ -315,12 +315,13 @@ class ZabbixAPISubClass(ZabbixAPI): """ wrapper class to ensure all calls go through the parent object """ parent = None data = None - def __init__(self, parent, data, **kwargs): + + def __init__(self, parent, data, **kwargs): self._setuplogging() self.debug(logging.INFO, "Creating %s" % self.__class__.__name__) - self.data = data + self.data = data self.parent = parent - + # Save any extra info passed in for key, val in kwargs.items(): setattr(self, key, val) From eb8c420ecc2697a738c71490632da462331f5080 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Tue, 26 Jun 2012 11:05:35 +0400 Subject: [PATCH 25/84] add apiinfo method --- zabbix/zabbix_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 87424a7..f4cd613 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -171,6 +171,7 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, self.history = ZabbixAPISubClass(self, dict({"prefix": "history"}, **kwargs)) self.maintenance = ZabbixAPISubClass(self, dict({"prefix": "maintenance"}, **kwargs)) self.proxy = ZabbixAPISubClass(self, dict({"prefix": "proxy"}, **kwargs)) + self.apiinfo = ZabbixAPISubClass(self, dict({"prefix": "apiinfo"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) From ca2b621bfdb972602ae6023119119d675f6b8ae3 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Thu, 28 Jun 2012 17:17:07 +0400 Subject: [PATCH 26/84] add new methods from zabbix 2 --- zabbix/zabbix_api.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index f4cd613..f17ec0b 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -166,12 +166,22 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, self.screen = ZabbixAPISubClass(self, dict({"prefix": "screen"}, **kwargs)) self.script = ZabbixAPISubClass(self, dict({"prefix": "script"}, **kwargs)) self.usermacro = ZabbixAPISubClass(self, dict({"prefix": "usermacro"}, **kwargs)) - self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) self.drule = ZabbixAPISubClass(self, dict({"prefix": "drule"}, **kwargs)) self.history = ZabbixAPISubClass(self, dict({"prefix": "history"}, **kwargs)) self.maintenance = ZabbixAPISubClass(self, dict({"prefix": "maintenance"}, **kwargs)) self.proxy = ZabbixAPISubClass(self, dict({"prefix": "proxy"}, **kwargs)) self.apiinfo = ZabbixAPISubClass(self, dict({"prefix": "apiinfo"}, **kwargs)) + self.configuration = ZabbixAPISubClass(self, dict({"prefix": "configuration"}, **kwargs)) + self.dcheck = ZabbixAPISubClass(self, dict({"prefix": "dcheck"}, **kwargs)) + self.dhost = ZabbixAPISubClass(self, dict({"prefix": "dhost"}, **kwargs)) + self.discoveryrule = ZabbixAPISubClass(self, dict({"prefix": "discoveryrule"}, **kwargs)) + self.dservice = ZabbixAPISubClass(self, dict({"prefix": "dservice"}, **kwargs)) + self.iconmap = ZabbixAPISubClass(self, dict({"prefix": "iconmap"}, **kwargs)) + self.image = ZabbixAPISubClass(self, dict({"prefix": "image"}, **kwargs)) + self.mediatype = ZabbixAPISubClass(self, dict({"prefix": "mediatype"}, **kwargs)) + self.service = ZabbixAPISubClass(self, dict({"prefix": "service"}, **kwargs)) + self.templatescreen = ZabbixAPISubClass(self, dict({"prefix": "templatescreen"}, **kwargs)) + self.usermedia = ZabbixAPISubClass(self, dict({"prefix": "usermedia"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) From 5c6bb283b61bb8adaaf24fc2b468c51e13c27e0c Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Fri, 6 Jul 2012 16:14:00 +0400 Subject: [PATCH 27/84] added workaround for import function in configuration method. --- zabbix/zabbix_api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index f17ec0b..5f13e6c 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -339,6 +339,9 @@ def __init__(self, parent, data, **kwargs): 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 From 9ef9b5a15911609284077a3eb62eab92e52de3b9 Mon Sep 17 00:00:00 2001 From: Alessio Ababilov Date: Thu, 23 Aug 2012 12:48:06 +0300 Subject: [PATCH 28/84] add setup.py and .gitignore --- .gitignore | 7 +++++++ zabbix/setup.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 .gitignore create mode 100755 zabbix/setup.py 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/zabbix/setup.py b/zabbix/setup.py new file mode 100755 index 0000000..783fd35 --- /dev/null +++ b/zabbix/setup.py @@ -0,0 +1,28 @@ +#!/usr/bin/python2 +# -*- coding: utf-8 -*- + +""" +Zabbix API +""" +import os +from setuptools import setup, find_packages, findall + + +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + + +setup( + name='zabbix-api', + url='https://github.com/gescheit/scripts', + version='0.1', + license='GNU LGPL 2.1', + author='Aleksandr Balezin', + author_email='gescheit@list.ru', + description='Zabbix API', + long_description=read('README'), + py_modules=['zabbix_api'], + include_package_data=True, + zip_safe=False, + platforms='any', +) From 70c5f810bc2b9407db6d49ad9ac38d6bd4f5a253 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Wed, 12 Sep 2012 17:37:53 +0400 Subject: [PATCH 29/84] refresh documentation --- zabbix/README | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zabbix/README b/zabbix/README index 1349d53..1d3f4bf 100644 --- a/zabbix/README +++ b/zabbix/README @@ -5,7 +5,9 @@ and subject to change. Implementations of the Zabbix API in other languages may be found on the wiki. +Zabbix 1.8 and 2.0 are supported. + See also: * http://www.zabbix.com/wiki/doc/api -* http://www.zabbix.com/documentation/1.8/api +* http://www.zabbix.com/documentation/2.0/manual/appendix/api/api * http://www.zabbix.com/forum/showthread.php?t=15218 From 29aca39898b4a9fe3b05a79b2bc91ed841abb4d3 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Wed, 12 Sep 2012 18:12:29 +0400 Subject: [PATCH 30/84] fix server path in example --- zabbix/zabbix_item_add_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/zabbix_item_add_example.py b/zabbix/zabbix_item_add_example.py index 9aa5f0e..ce18554 100644 --- a/zabbix/zabbix_item_add_example.py +++ b/zabbix/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" From bc369cd0f7338dda7bb6d427b26317ed8972651d Mon Sep 17 00:00:00 2001 From: Aaron Mildenstein Date: Tue, 6 Nov 2012 18:32:17 -0600 Subject: [PATCH 31/84] Added the hostinterface API call. --- zabbix/zabbix_api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 5f13e6c..d05d183 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -119,6 +119,7 @@ class ZabbixAPI(object): host = None item = None hostgroup = None + hostinterface = None application = None trigger = None sysmap = None @@ -153,6 +154,7 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, self.host = ZabbixAPISubClass(self, dict({"prefix": "host"}, **kwargs)) self.item = ZabbixAPISubClass(self, dict({"prefix": "item"}, **kwargs)) self.hostgroup = ZabbixAPISubClass(self, dict({"prefix": "hostgroup"}, **kwargs)) + self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) self.application = ZabbixAPISubClass(self, dict({"prefix": "application"}, **kwargs)) self.trigger = ZabbixAPISubClass(self, dict({"prefix": "trigger"}, **kwargs)) self.template = ZabbixAPISubClass(self, dict({"prefix": "template"}, **kwargs)) From 61768cdbeb8501a5c11e3c228d7375ea9fe571c6 Mon Sep 17 00:00:00 2001 From: caraconan Date: Tue, 4 Dec 2012 12:03:48 +0100 Subject: [PATCH 32/84] Update zabbix/zabbix_api.py 1. It fixes a bug when Basic HTTP authentication is needed (was ignored by ZabbixAPI.__init__ 2. It captures the exception raised when Basic HTTP authentication is needed a no 'httpuser','httppasswd' variables are set up under class ZabbixAPI --- zabbix/zabbix_api.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index d05d183..5a69910 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -137,7 +137,7 @@ class ZabbixAPI(object): # r_query_len: max len query history # **kwargs: Data to pass to each api module - def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, + def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httppasswd, log_level=logging.WARNING, timeout=10, r_query_len=10, **kwargs): """ Create an API object. """ self._setuplogging() @@ -280,7 +280,11 @@ def do_request(self, json_obj): raise ZabbixAPIException("Unknow protocol %s" % self.proto) urllib2.install_opener(opener) - response = opener.open(request, timeout=self.timeout) + try: + response = opener.open(request, timeout=self.timeout) + except Exception as e: + self.debug(logging.ERROR, "Site needs HTTP authentication. Error: "+str(e)) + sys.exit(-1) self.debug(logging.INFO, "Response Code: " + str(response.code)) # NOTE: Getting a 412 response code means the headers are not in the From 8cdeb754e64e83f04ef116444cfa85c378d1b72f Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Wed, 5 Dec 2012 12:53:08 +0400 Subject: [PATCH 33/84] add hostinterface class --- zabbix/zabbix_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 5f13e6c..ca16a96 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -182,6 +182,7 @@ def __init__(self, server='http://localhost/zabbix', user=None, passwd=None, self.service = ZabbixAPISubClass(self, dict({"prefix": "service"}, **kwargs)) self.templatescreen = ZabbixAPISubClass(self, dict({"prefix": "templatescreen"}, **kwargs)) self.usermedia = ZabbixAPISubClass(self, dict({"prefix": "usermedia"}, **kwargs)) + self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) From 15514b2ecea464fee7682dc796e90442affceebf Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Tue, 25 Dec 2012 14:43:52 +0400 Subject: [PATCH 34/84] add itemprototype, graphprototype, triggerprototype add itemprototype, graphprototype, triggerprototype methods --- zabbix/zabbix_api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 5013d85..c7637dc 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -185,6 +185,9 @@ def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httpp self.templatescreen = ZabbixAPISubClass(self, dict({"prefix": "templatescreen"}, **kwargs)) self.usermedia = ZabbixAPISubClass(self, dict({"prefix": "usermedia"}, **kwargs)) self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) + self.triggerprototype = ZabbixAPISubClass(self, dict({"prefix": "triggerprototype"}, **kwargs)) + self.graphprototype = ZabbixAPISubClass(self, dict({"prefix": "graphprototype"}, **kwargs)) + self.itemprototype = ZabbixAPISubClass(self, dict({"prefix": "itemprototype"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) From 86526bc63fa4aa1f3568a4eae129874e42410f61 Mon Sep 17 00:00:00 2001 From: "Sebastian J. Bronner" Date: Wed, 20 Mar 2013 14:22:49 +0100 Subject: [PATCH 35/84] Add support for the webcheck method. --- zabbix/zabbix_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index c7637dc..6ef3071 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -188,6 +188,7 @@ def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httpp self.triggerprototype = ZabbixAPISubClass(self, dict({"prefix": "triggerprototype"}, **kwargs)) self.graphprototype = ZabbixAPISubClass(self, dict({"prefix": "graphprototype"}, **kwargs)) self.itemprototype = ZabbixAPISubClass(self, dict({"prefix": "itemprototype"}, **kwargs)) + self.webcheck = ZabbixAPISubClass(self, dict({"prefix": "webcheck"}, **kwargs)) self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) From 403780bb20ede66ecd92689d1f7d1ad1a7f50d29 Mon Sep 17 00:00:00 2001 From: Yongzhi Pan Date: Wed, 27 Mar 2013 19:11:59 +0800 Subject: [PATCH 36/84] Raise exception on API request error. --- zabbix/zabbix_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 6ef3071..879287a 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -288,8 +288,7 @@ def do_request(self, json_obj): try: response = opener.open(request, timeout=self.timeout) except Exception as e: - self.debug(logging.ERROR, "Site needs HTTP authentication. Error: "+str(e)) - sys.exit(-1) + raise ZabbixAPIException("Site needs HTTP authentication. Error: "+str(e)) self.debug(logging.INFO, "Response Code: " + str(response.code)) # NOTE: Getting a 412 response code means the headers are not in the From d668e1bd9b2b6723e0a7c7f07a7c4569f2869eac Mon Sep 17 00:00:00 2001 From: somsak Date: Thu, 18 Jul 2013 23:36:31 +0700 Subject: [PATCH 37/84] Add zabbix screenitem --- zabbix/zabbix_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 879287a..f34550d 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -166,6 +166,7 @@ def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httpp self.graphitem = ZabbixAPISubClass(self, dict({"prefix": "graphitem"}, **kwargs)) self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) self.screen = ZabbixAPISubClass(self, dict({"prefix": "screen"}, **kwargs)) + self.screenitem = ZabbixAPISubClass(self, dict({"prefix": "screenitem"}, **kwargs)) self.script = ZabbixAPISubClass(self, dict({"prefix": "script"}, **kwargs)) self.usermacro = ZabbixAPISubClass(self, dict({"prefix": "usermacro"}, **kwargs)) self.drule = ZabbixAPISubClass(self, dict({"prefix": "drule"}, **kwargs)) From f024fbfd88e27cc5110eeae2333649924d24f918 Mon Sep 17 00:00:00 2001 From: somsak Date: Thu, 18 Jul 2013 23:38:15 +0700 Subject: [PATCH 38/84] Example script for automatic screen creation --- zabbix/examples/zabbix_screen.py | 138 +++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100755 zabbix/examples/zabbix_screen.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) + From c59c6d32e52e43258c3b402567f482c7b01b9f95 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 13 Oct 2013 21:59:31 +0400 Subject: [PATCH 39/84] Create README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 README.md 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 + From 5994df73df7e94c41af82a52f435f0678eff05e1 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 13 Oct 2013 22:41:48 +0400 Subject: [PATCH 40/84] initial --- checks/functions.sh | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 checks/functions.sh 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 +} From a665a96703f794d1fd6d29dc032766aa34e14ffa Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 13 Oct 2013 22:41:53 +0400 Subject: [PATCH 41/84] initial --- checks/disksmart.sh | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 checks/disksmart.sh diff --git a/checks/disksmart.sh b/checks/disksmart.sh new file mode 100755 index 0000000..a12156d --- /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 + SMARTSTR="ton of errors in log" + 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 + 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" From 5b247d1c901fcacbc9d7f2b378b57ae91a785f59 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 13 Oct 2013 22:55:53 +0400 Subject: [PATCH 42/84] fix error message --- checks/disksmart.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checks/disksmart.sh b/checks/disksmart.sh index a12156d..39fcdb5 100755 --- a/checks/disksmart.sh +++ b/checks/disksmart.sh @@ -69,14 +69,14 @@ if [ -z "$CACHE" ]; then fi fi if [ $((${SMARTSTATUS} & 1<<6)) -gt 0 ]; then - SMARTSTR="ton of errors in log" 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}" From b92600ffcce0dbc25e2c04f8bd8eae9352f6b6f8 Mon Sep 17 00:00:00 2001 From: Balezin Aleksandr Date: Sun, 13 Oct 2013 23:03:28 +0400 Subject: [PATCH 43/84] add readme --- checks/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 checks/README.md diff --git a/checks/README.md b/checks/README.md new file mode 100644 index 0000000..df87427 --- /dev/null +++ b/checks/README.md @@ -0,0 +1,2 @@ +disksmart.sh - check SMART of all disks in system +functions.sh - functions for locking and caching From 35dce54ccad58cab4e80cdb8bc167970a5f1f962 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 13 Oct 2013 23:13:49 +0400 Subject: [PATCH 44/84] Update and rename README.md to README --- checks/README | 2 ++ checks/README.md | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 checks/README delete mode 100644 checks/README.md diff --git a/checks/README b/checks/README new file mode 100644 index 0000000..8138295 --- /dev/null +++ b/checks/README @@ -0,0 +1,2 @@ +disksmart.sh - check SMART of all disks in system
+functions.sh - functions for locking and caching diff --git a/checks/README.md b/checks/README.md deleted file mode 100644 index df87427..0000000 --- a/checks/README.md +++ /dev/null @@ -1,2 +0,0 @@ -disksmart.sh - check SMART of all disks in system -functions.sh - functions for locking and caching From a89fd4840f44ad5c9b0f24205d2ec3f0b286a9bf Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 13 Oct 2013 23:14:08 +0400 Subject: [PATCH 45/84] Update README --- checks/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checks/README b/checks/README index 8138295..df87427 100644 --- a/checks/README +++ b/checks/README @@ -1,2 +1,2 @@ -disksmart.sh - check SMART of all disks in system
+disksmart.sh - check SMART of all disks in system functions.sh - functions for locking and caching From 2b22dfaa475980f2ec7f101ac9c55beb0737efcc Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 13 Oct 2013 23:27:18 +0400 Subject: [PATCH 46/84] Update and rename README to README.md --- checks/{README => README.md} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename checks/{README => README.md} (61%) diff --git a/checks/README b/checks/README.md similarity index 61% rename from checks/README rename to checks/README.md index df87427..48d9fad 100644 --- a/checks/README +++ b/checks/README.md @@ -1,2 +1,4 @@ -disksmart.sh - check SMART of all disks in system 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 From 2ecc4fa5fe4d5c4f2233215018d37d5821153613 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 13 Oct 2013 23:30:43 +0400 Subject: [PATCH 47/84] Update README.md --- checks/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/checks/README.md b/checks/README.md index 48d9fad..a6cf552 100644 --- a/checks/README.md +++ b/checks/README.md @@ -1,4 +1,4 @@ -functions.sh - functions for locking and caching +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 +- Work under FreeBSD and linux +- Use caching and locking From 65def1aaddbc4ac7caea75a0413717ff37b22ba7 Mon Sep 17 00:00:00 2001 From: Evgenii Terechkov Date: Wed, 1 Oct 2014 15:56:03 +0800 Subject: [PATCH 48/84] Update code and README to work with zabbix-2.4 --- zabbix/README | 4 ++-- zabbix/zabbix_api.py | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/zabbix/README b/zabbix/README index 1d3f4bf..19c4ac7 100644 --- a/zabbix/README +++ b/zabbix/README @@ -5,9 +5,9 @@ and subject to change. Implementations of the Zabbix API in other languages may be found on the wiki. -Zabbix 1.8 and 2.0 are supported. +Zabbix 1.8, 2.0, 2.2, 2.4 are supported. See also: * http://www.zabbix.com/wiki/doc/api -* http://www.zabbix.com/documentation/2.0/manual/appendix/api/api +* https://www.zabbix.com/documentation/2.4/manual/api * http://www.zabbix.com/forum/showthread.php?t=15218 diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index f34550d..5c85827 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -216,13 +216,14 @@ def debug(self, level, var="", msg=None): self.logger.log(level, strval) - def json_obj(self, method, params={}): + 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)) @@ -246,8 +247,8 @@ def login(self, user='', password='', save=True): 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))) - obj = self.json_obj('user.authenticate', {'user': l_user, - 'password': l_password}) + obj = self.json_obj('user.login', {'user': l_user, + 'password': l_password},auth=False) result = self.do_request(obj) self.auth = result['result'] @@ -325,7 +326,7 @@ def logged_in(self): def api_version(self, **options): self.__checkauth__() - obj = self.do_request(self.json_obj('APIInfo.version', options)) + obj = self.do_request(self.json_obj('APIInfo.version', options,auth=False)) return obj['result'] def __checkauth__(self): From e6f50ee4d57391e1eba4db2b1c135599cb33f6b5 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 12:48:44 +0300 Subject: [PATCH 49/84] Fixed crlf issue --- zabbix/zabbix_api.py | 746 +++++++++++++++++++++---------------------- 1 file changed, 373 insertions(+), 373 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 5c85827..2131dc2 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -1,373 +1,373 @@ -# 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 -try: - import urllib2 -except ImportError: - import urllib.request as urllib2 # python3 -import re -from collections import deque - -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(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 - - -def dojson2(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 - - -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 ZabbixAPI(object): - __username__ = '' - __password__ = '' - - auth = '' - url = '/api_jsonrpc.php' - params = None - method = None - # HTTP or HTTPS - proto = 'http' - # HTTP authentication - httpuser = None - httppasswd = None - timeout = 10 - # sub-class instances. - user = None - usergroup = None - host = None - item = None - hostgroup = None - hostinterface = 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 - # 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, **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.usergroup = ZabbixAPISubClass(self, dict({"prefix": "usergroup"}, **kwargs)) - self.user = ZabbixAPISubClass(self, dict({"prefix": "user"}, **kwargs)) - self.host = ZabbixAPISubClass(self, dict({"prefix": "host"}, **kwargs)) - self.item = ZabbixAPISubClass(self, dict({"prefix": "item"}, **kwargs)) - self.hostgroup = ZabbixAPISubClass(self, dict({"prefix": "hostgroup"}, **kwargs)) - self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) - self.application = ZabbixAPISubClass(self, dict({"prefix": "application"}, **kwargs)) - self.trigger = ZabbixAPISubClass(self, dict({"prefix": "trigger"}, **kwargs)) - self.template = ZabbixAPISubClass(self, dict({"prefix": "template"}, **kwargs)) - self.action = ZabbixAPISubClass(self, dict({"prefix": "action"}, **kwargs)) - self.alert = ZabbixAPISubClass(self, dict({"prefix": "alert"}, **kwargs)) - self.info = ZabbixAPISubClass(self, dict({"prefix": "info"}, **kwargs)) - self.event = ZabbixAPISubClass(self, dict({"prefix": "event"}, **kwargs)) - self.graph = ZabbixAPISubClass(self, dict({"prefix": "graph"}, **kwargs)) - self.graphitem = ZabbixAPISubClass(self, dict({"prefix": "graphitem"}, **kwargs)) - self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) - self.screen = ZabbixAPISubClass(self, dict({"prefix": "screen"}, **kwargs)) - self.screenitem = ZabbixAPISubClass(self, dict({"prefix": "screenitem"}, **kwargs)) - self.script = ZabbixAPISubClass(self, dict({"prefix": "script"}, **kwargs)) - self.usermacro = ZabbixAPISubClass(self, dict({"prefix": "usermacro"}, **kwargs)) - self.drule = ZabbixAPISubClass(self, dict({"prefix": "drule"}, **kwargs)) - self.history = ZabbixAPISubClass(self, dict({"prefix": "history"}, **kwargs)) - self.maintenance = ZabbixAPISubClass(self, dict({"prefix": "maintenance"}, **kwargs)) - self.proxy = ZabbixAPISubClass(self, dict({"prefix": "proxy"}, **kwargs)) - self.apiinfo = ZabbixAPISubClass(self, dict({"prefix": "apiinfo"}, **kwargs)) - self.configuration = ZabbixAPISubClass(self, dict({"prefix": "configuration"}, **kwargs)) - self.dcheck = ZabbixAPISubClass(self, dict({"prefix": "dcheck"}, **kwargs)) - self.dhost = ZabbixAPISubClass(self, dict({"prefix": "dhost"}, **kwargs)) - self.discoveryrule = ZabbixAPISubClass(self, dict({"prefix": "discoveryrule"}, **kwargs)) - self.dservice = ZabbixAPISubClass(self, dict({"prefix": "dservice"}, **kwargs)) - self.iconmap = ZabbixAPISubClass(self, dict({"prefix": "iconmap"}, **kwargs)) - self.image = ZabbixAPISubClass(self, dict({"prefix": "image"}, **kwargs)) - self.mediatype = ZabbixAPISubClass(self, dict({"prefix": "mediatype"}, **kwargs)) - self.service = ZabbixAPISubClass(self, dict({"prefix": "service"}, **kwargs)) - self.templatescreen = ZabbixAPISubClass(self, dict({"prefix": "templatescreen"}, **kwargs)) - self.usermedia = ZabbixAPISubClass(self, dict({"prefix": "usermedia"}, **kwargs)) - self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) - self.triggerprototype = ZabbixAPISubClass(self, dict({"prefix": "triggerprototype"}, **kwargs)) - self.graphprototype = ZabbixAPISubClass(self, dict({"prefix": "graphprototype"}, **kwargs)) - self.itemprototype = ZabbixAPISubClass(self, dict({"prefix": "itemprototype"}, **kwargs)) - self.webcheck = ZabbixAPISubClass(self, dict({"prefix": "webcheck"}, **kwargs)) - self.id = 0 - self.r_query = deque([], maxlen=r_query_len) - 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): - 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))) - obj = self.json_obj('user.login', {'user': l_user, - 'password': l_password},auth=False) - 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.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": - 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 Exception as e: - raise ZabbixAPIException("Site needs HTTP authentication. Error: "+str(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): - self.__checkauth__() - 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.") - - -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) - - @dojson2 - @checkauth - def universal(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 +try: + import urllib2 +except ImportError: + import urllib.request as urllib2 # python3 +import re +from collections import deque + +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(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 + + +def dojson2(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 + + +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 ZabbixAPI(object): + __username__ = '' + __password__ = '' + + auth = '' + url = '/api_jsonrpc.php' + params = None + method = None + # HTTP or HTTPS + proto = 'http' + # HTTP authentication + httpuser = None + httppasswd = None + timeout = 10 + # sub-class instances. + user = None + usergroup = None + host = None + item = None + hostgroup = None + hostinterface = 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 + # 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, **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.usergroup = ZabbixAPISubClass(self, dict({"prefix": "usergroup"}, **kwargs)) + self.user = ZabbixAPISubClass(self, dict({"prefix": "user"}, **kwargs)) + self.host = ZabbixAPISubClass(self, dict({"prefix": "host"}, **kwargs)) + self.item = ZabbixAPISubClass(self, dict({"prefix": "item"}, **kwargs)) + self.hostgroup = ZabbixAPISubClass(self, dict({"prefix": "hostgroup"}, **kwargs)) + self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) + self.application = ZabbixAPISubClass(self, dict({"prefix": "application"}, **kwargs)) + self.trigger = ZabbixAPISubClass(self, dict({"prefix": "trigger"}, **kwargs)) + self.template = ZabbixAPISubClass(self, dict({"prefix": "template"}, **kwargs)) + self.action = ZabbixAPISubClass(self, dict({"prefix": "action"}, **kwargs)) + self.alert = ZabbixAPISubClass(self, dict({"prefix": "alert"}, **kwargs)) + self.info = ZabbixAPISubClass(self, dict({"prefix": "info"}, **kwargs)) + self.event = ZabbixAPISubClass(self, dict({"prefix": "event"}, **kwargs)) + self.graph = ZabbixAPISubClass(self, dict({"prefix": "graph"}, **kwargs)) + self.graphitem = ZabbixAPISubClass(self, dict({"prefix": "graphitem"}, **kwargs)) + self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) + self.screen = ZabbixAPISubClass(self, dict({"prefix": "screen"}, **kwargs)) + self.screenitem = ZabbixAPISubClass(self, dict({"prefix": "screenitem"}, **kwargs)) + self.script = ZabbixAPISubClass(self, dict({"prefix": "script"}, **kwargs)) + self.usermacro = ZabbixAPISubClass(self, dict({"prefix": "usermacro"}, **kwargs)) + self.drule = ZabbixAPISubClass(self, dict({"prefix": "drule"}, **kwargs)) + self.history = ZabbixAPISubClass(self, dict({"prefix": "history"}, **kwargs)) + self.maintenance = ZabbixAPISubClass(self, dict({"prefix": "maintenance"}, **kwargs)) + self.proxy = ZabbixAPISubClass(self, dict({"prefix": "proxy"}, **kwargs)) + self.apiinfo = ZabbixAPISubClass(self, dict({"prefix": "apiinfo"}, **kwargs)) + self.configuration = ZabbixAPISubClass(self, dict({"prefix": "configuration"}, **kwargs)) + self.dcheck = ZabbixAPISubClass(self, dict({"prefix": "dcheck"}, **kwargs)) + self.dhost = ZabbixAPISubClass(self, dict({"prefix": "dhost"}, **kwargs)) + self.discoveryrule = ZabbixAPISubClass(self, dict({"prefix": "discoveryrule"}, **kwargs)) + self.dservice = ZabbixAPISubClass(self, dict({"prefix": "dservice"}, **kwargs)) + self.iconmap = ZabbixAPISubClass(self, dict({"prefix": "iconmap"}, **kwargs)) + self.image = ZabbixAPISubClass(self, dict({"prefix": "image"}, **kwargs)) + self.mediatype = ZabbixAPISubClass(self, dict({"prefix": "mediatype"}, **kwargs)) + self.service = ZabbixAPISubClass(self, dict({"prefix": "service"}, **kwargs)) + self.templatescreen = ZabbixAPISubClass(self, dict({"prefix": "templatescreen"}, **kwargs)) + self.usermedia = ZabbixAPISubClass(self, dict({"prefix": "usermedia"}, **kwargs)) + self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) + self.triggerprototype = ZabbixAPISubClass(self, dict({"prefix": "triggerprototype"}, **kwargs)) + self.graphprototype = ZabbixAPISubClass(self, dict({"prefix": "graphprototype"}, **kwargs)) + self.itemprototype = ZabbixAPISubClass(self, dict({"prefix": "itemprototype"}, **kwargs)) + self.webcheck = ZabbixAPISubClass(self, dict({"prefix": "webcheck"}, **kwargs)) + self.id = 0 + self.r_query = deque([], maxlen=r_query_len) + 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): + 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))) + obj = self.json_obj('user.login', {'user': l_user, + 'password': l_password},auth=False) + 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.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": + 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 Exception as e: + raise ZabbixAPIException("Site needs HTTP authentication. Error: "+str(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): + self.__checkauth__() + 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.") + + +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) + + @dojson2 + @checkauth + def universal(self, **opts): + return opts From dcf4e31dd413b3bb0b8db622c3310ccebb45c1e0 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 12:51:27 +0300 Subject: [PATCH 50/84] added APITimeout exception --- zabbix/zabbix_api.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 2131dc2..eef3ecb 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -31,6 +31,8 @@ import logging import string import sys +import ssl +import socket try: import urllib2 except ImportError: @@ -99,6 +101,10 @@ class InvalidProtoError(ZabbixAPIException): pass +class APITimeout(ZabbixAPIException): + pass + + class ZabbixAPI(object): __username__ = '' __password__ = '' @@ -289,8 +295,18 @@ def do_request(self, json_obj): urllib2.install_opener(opener) try: response = opener.open(request, timeout=self.timeout) - except Exception as e: - raise ZabbixAPIException("Site needs HTTP authentication. Error: "+str(e)) + except ssl.SSLError as e: + if e.message == "The read operation timed out": + raise APITimeout("SSL read timeout",) + else: + raise e + except socket.timeout as e: + raise APITimeout("HTTP read timeout",) + except urllib2.URLError as e: + if "Connection timed out" in e.message: + raise APITimeout("HTTP read timeout",) + else: + raise e self.debug(logging.INFO, "Response Code: " + str(response.code)) # NOTE: Getting a 412 response code means the headers are not in the From b433aa3416adacb428d5dea02904a7b12ec0d4ed Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 12:54:17 +0300 Subject: [PATCH 51/84] removed unused dojson() --- zabbix/zabbix_api.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index eef3ecb..967b09a 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -63,17 +63,6 @@ def ret(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 - - def dojson2(fn): def wrapper(self, method, opts): self.logger.log(logging.DEBUG, \ From 995e3217697eefa5d7996f65ab4bd479e620a0ec Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 12:55:40 +0300 Subject: [PATCH 52/84] rename dojson2() to dojson() --- zabbix/zabbix_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 967b09a..03f7c42 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -63,7 +63,7 @@ def ret(self, *args): return ret -def dojson2(fn): +def dojson(fn): def wrapper(self, method, opts): self.logger.log(logging.DEBUG, \ "Going to do_request for %s with opts %s" \ @@ -372,7 +372,7 @@ def do_request(self, req): def json_obj(self, method, param): return self.parent.json_obj(method, param) - @dojson2 + @dojson @checkauth def universal(self, **opts): return opts From e5addb6cd30f3dad08ac988a15b10d8a82be36bb Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 13:36:17 +0300 Subject: [PATCH 53/84] fix indents --- zabbix/zabbix_api.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 03f7c42..395112a 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -211,7 +211,7 @@ def debug(self, level, var="", msg=None): self.logger.log(level, strval) - def json_obj(self, method, params={},auth=True): + def json_obj(self, method, params={}, auth=True): obj = {'jsonrpc': '2.0', 'method': method, 'params': params, @@ -242,8 +242,7 @@ def login(self, user='', password='', save=True): 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))) - obj = self.json_obj('user.login', {'user': l_user, - 'password': l_password},auth=False) + obj = self.json_obj('user.login', {'user': l_user, 'password': l_password}, auth=False) result = self.do_request(obj) self.auth = result['result'] @@ -331,7 +330,7 @@ def logged_in(self): def api_version(self, **options): self.__checkauth__() - obj = self.do_request(self.json_obj('APIInfo.version', options,auth=False)) + obj = self.do_request(self.json_obj('APIInfo.version', options, auth=False)) return obj['result'] def __checkauth__(self): From 6d6413e0d4471b07ec1bf6c4ed5526d25a2ea6e2 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 13:51:39 +0300 Subject: [PATCH 54/84] delete hardcoded API methods make ZabbixAPISubClass through __getitem__ method --- zabbix/zabbix_api.py | 45 ++++---------------------------------------- 1 file changed, 4 insertions(+), 41 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 395112a..7a89a96 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -144,47 +144,7 @@ def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httpp self.httpuser = user self.httppasswd = passwd self.timeout = timeout - self.usergroup = ZabbixAPISubClass(self, dict({"prefix": "usergroup"}, **kwargs)) - self.user = ZabbixAPISubClass(self, dict({"prefix": "user"}, **kwargs)) - self.host = ZabbixAPISubClass(self, dict({"prefix": "host"}, **kwargs)) - self.item = ZabbixAPISubClass(self, dict({"prefix": "item"}, **kwargs)) - self.hostgroup = ZabbixAPISubClass(self, dict({"prefix": "hostgroup"}, **kwargs)) - self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) - self.application = ZabbixAPISubClass(self, dict({"prefix": "application"}, **kwargs)) - self.trigger = ZabbixAPISubClass(self, dict({"prefix": "trigger"}, **kwargs)) - self.template = ZabbixAPISubClass(self, dict({"prefix": "template"}, **kwargs)) - self.action = ZabbixAPISubClass(self, dict({"prefix": "action"}, **kwargs)) - self.alert = ZabbixAPISubClass(self, dict({"prefix": "alert"}, **kwargs)) - self.info = ZabbixAPISubClass(self, dict({"prefix": "info"}, **kwargs)) - self.event = ZabbixAPISubClass(self, dict({"prefix": "event"}, **kwargs)) - self.graph = ZabbixAPISubClass(self, dict({"prefix": "graph"}, **kwargs)) - self.graphitem = ZabbixAPISubClass(self, dict({"prefix": "graphitem"}, **kwargs)) - self.map = ZabbixAPISubClass(self, dict({"prefix": "map"}, **kwargs)) - self.screen = ZabbixAPISubClass(self, dict({"prefix": "screen"}, **kwargs)) - self.screenitem = ZabbixAPISubClass(self, dict({"prefix": "screenitem"}, **kwargs)) - self.script = ZabbixAPISubClass(self, dict({"prefix": "script"}, **kwargs)) - self.usermacro = ZabbixAPISubClass(self, dict({"prefix": "usermacro"}, **kwargs)) - self.drule = ZabbixAPISubClass(self, dict({"prefix": "drule"}, **kwargs)) - self.history = ZabbixAPISubClass(self, dict({"prefix": "history"}, **kwargs)) - self.maintenance = ZabbixAPISubClass(self, dict({"prefix": "maintenance"}, **kwargs)) - self.proxy = ZabbixAPISubClass(self, dict({"prefix": "proxy"}, **kwargs)) - self.apiinfo = ZabbixAPISubClass(self, dict({"prefix": "apiinfo"}, **kwargs)) - self.configuration = ZabbixAPISubClass(self, dict({"prefix": "configuration"}, **kwargs)) - self.dcheck = ZabbixAPISubClass(self, dict({"prefix": "dcheck"}, **kwargs)) - self.dhost = ZabbixAPISubClass(self, dict({"prefix": "dhost"}, **kwargs)) - self.discoveryrule = ZabbixAPISubClass(self, dict({"prefix": "discoveryrule"}, **kwargs)) - self.dservice = ZabbixAPISubClass(self, dict({"prefix": "dservice"}, **kwargs)) - self.iconmap = ZabbixAPISubClass(self, dict({"prefix": "iconmap"}, **kwargs)) - self.image = ZabbixAPISubClass(self, dict({"prefix": "image"}, **kwargs)) - self.mediatype = ZabbixAPISubClass(self, dict({"prefix": "mediatype"}, **kwargs)) - self.service = ZabbixAPISubClass(self, dict({"prefix": "service"}, **kwargs)) - self.templatescreen = ZabbixAPISubClass(self, dict({"prefix": "templatescreen"}, **kwargs)) - self.usermedia = ZabbixAPISubClass(self, dict({"prefix": "usermedia"}, **kwargs)) - self.hostinterface = ZabbixAPISubClass(self, dict({"prefix": "hostinterface"}, **kwargs)) - self.triggerprototype = ZabbixAPISubClass(self, dict({"prefix": "triggerprototype"}, **kwargs)) - self.graphprototype = ZabbixAPISubClass(self, dict({"prefix": "graphprototype"}, **kwargs)) - self.itemprototype = ZabbixAPISubClass(self, dict({"prefix": "itemprototype"}, **kwargs)) - self.webcheck = ZabbixAPISubClass(self, dict({"prefix": "webcheck"}, **kwargs)) + self.kwargs = kwargs self.id = 0 self.r_query = deque([], maxlen=r_query_len) self.debug(logging.INFO, "url: " + self.url) @@ -337,6 +297,9 @@ 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 """ From bd1e9688effa84cd1327b9ac4e7ff1668677a7d1 Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 14:05:17 +0300 Subject: [PATCH 55/84] bump version --- zabbix/setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index 783fd35..8f2dc6c 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2 +#!/usr/bin/python # -*- coding: utf-8 -*- """ @@ -15,10 +15,10 @@ def read(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.1', + version='0.2', license='GNU LGPL 2.1', author='Aleksandr Balezin', - author_email='gescheit@list.ru', + author_email='gescheit12@gmail.com', description='Zabbix API', long_description=read('README'), py_modules=['zabbix_api'], From 20818dc7a0014bf7b586593ed633dcea89bddadd Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 14:55:39 +0300 Subject: [PATCH 56/84] update README --- zabbix/README | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/zabbix/README b/zabbix/README index 19c4ac7..80187b6 100644 --- a/zabbix/README +++ b/zabbix/README @@ -1,11 +1,21 @@ This is an implementation of the Zabbix API in Python. -Please note that the Zabbix API is still in a draft state, +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 are supported. +Python 2 and 3 are supported. + +Future versions must be supported too, if there is no deep changes. + +Short example: + +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 From ae7aef1639c48919e42140fb9531ab5a956b03fa Mon Sep 17 00:00:00 2001 From: gescheit Date: Sun, 1 Feb 2015 15:04:28 +0300 Subject: [PATCH 57/84] move examples to examples dir --- zabbix/{ => examples}/zabbix_item_add_example.py | 0 zabbix/{ => examples}/zabbix_rpc_test.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename zabbix/{ => examples}/zabbix_item_add_example.py (100%) rename zabbix/{ => examples}/zabbix_rpc_test.py (100%) diff --git a/zabbix/zabbix_item_add_example.py b/zabbix/examples/zabbix_item_add_example.py similarity index 100% rename from zabbix/zabbix_item_add_example.py rename to zabbix/examples/zabbix_item_add_example.py 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 From 8e69a8a121ace45a29371705bc9b0ce82b8350bc Mon Sep 17 00:00:00 2001 From: gescheit Date: Tue, 3 Feb 2015 16:28:48 +0300 Subject: [PATCH 58/84] update readme --- zabbix/README | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/zabbix/README b/zabbix/README index 80187b6..1ccd375 100644 --- a/zabbix/README +++ b/zabbix/README @@ -10,12 +10,19 @@ 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: -from zabbix_api import ZabbixAPI -zapi = ZabbixAPI(server="https://server/") -zapi.login("login", "password") -zapi.trigger.get({"expandExpression": "extend", "triggerids": range(0, 100)}) +```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 From d39e25cab926f41474797625110a240584b7c11c Mon Sep 17 00:00:00 2001 From: gescheit Date: Tue, 3 Feb 2015 16:32:18 +0300 Subject: [PATCH 59/84] README -> README.md --- zabbix/README | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 zabbix/README diff --git a/zabbix/README b/zabbix/README deleted file mode 100644 index 1ccd375..0000000 --- a/zabbix/README +++ /dev/null @@ -1,30 +0,0 @@ -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 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 From 0d9f03b31e7896165a9e9cdfe7fcbdf9ce3c7ad8 Mon Sep 17 00:00:00 2001 From: gescheit Date: Tue, 3 Feb 2015 16:33:59 +0300 Subject: [PATCH 60/84] add README.md --- zabbix/README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 zabbix/README.md diff --git a/zabbix/README.md b/zabbix/README.md new file mode 100644 index 0000000..1ccd375 --- /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 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 From cf16b22db8b2dd595b83bf25b0ff23e5e4193923 Mon Sep 17 00:00:00 2001 From: gescheit Date: Thu, 12 Feb 2015 12:47:36 +0300 Subject: [PATCH 61/84] remove unwanted declaration --- zabbix/zabbix_api.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 7a89a96..83f73a9 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -109,17 +109,6 @@ class ZabbixAPI(object): httppasswd = None timeout = 10 # sub-class instances. - user = None - usergroup = None - host = None - item = None - hostgroup = None - hostinterface = 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 From 461947c8b5512f1afae3b02031197f97f6a8e536 Mon Sep 17 00:00:00 2001 From: gescheit Date: Thu, 12 Feb 2015 12:51:19 +0300 Subject: [PATCH 62/84] add classifiers --- zabbix/setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zabbix/setup.py b/zabbix/setup.py index 8f2dc6c..98cae3d 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -25,4 +25,10 @@ def read(fname): 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', + ] ) From 2148ac97e5277dceab5efee14874e90b397256d5 Mon Sep 17 00:00:00 2001 From: gescheit Date: Thu, 12 Feb 2015 12:55:31 +0300 Subject: [PATCH 63/84] update to 0.3 --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index 98cae3d..ab4039b 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -15,7 +15,7 @@ def read(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.2', + version='0.3', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com', From 936a812984215b23736d3db47a436c1440e65f1e Mon Sep 17 00:00:00 2001 From: Evgenii Terechkov Date: Thu, 19 Nov 2015 09:42:07 +0700 Subject: [PATCH 64/84] README is now README.md --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index ab4039b..c5d97b8 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -20,7 +20,7 @@ def read(fname): author='Aleksandr Balezin', author_email='gescheit12@gmail.com', description='Zabbix API', - long_description=read('README'), + long_description=read('README.md'), py_modules=['zabbix_api'], include_package_data=True, zip_safe=False, From 4456158e6a56dd52f23a803c08f280ffa6791477 Mon Sep 17 00:00:00 2001 From: Evgenii Terechkov Date: Thu, 19 Nov 2015 14:15:24 +0700 Subject: [PATCH 65/84] Add support for unverified/selfsigned SSL certificates Pythons (2.7.9/3.4.3 and up) validate SSL connections by default, so there must be way to work with unverified/selfsigned certificates. --- zabbix/zabbix_api.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 83f73a9..87ccae9 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -40,6 +40,13 @@ 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) @@ -108,6 +115,7 @@ class ZabbixAPI(object): httpuser = None httppasswd = None timeout = 10 + validate_certs = None # sub-class instances. # Constructor Params: # server: Server to connect to @@ -122,7 +130,7 @@ class ZabbixAPI(object): # **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, **kwargs): + 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) @@ -136,6 +144,7 @@ def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httpp 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): @@ -221,7 +230,10 @@ def do_request(self, json_obj): request = urllib2.Request(url=self.url, data=json_obj.encode('utf-8'), headers=headers) if self.proto == "https": - https_handler = urllib2.HTTPSHandler(debuglevel=0) + 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) From ef1ee591f6e10fdc8bfd800489b83fdf99e8880f Mon Sep 17 00:00:00 2001 From: Stefano Stella Date: Wed, 1 Feb 2017 14:36:24 +0100 Subject: [PATCH 66/84] raise ZabbixAPIException instead of 'e' --- zabbix/zabbix_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 87ccae9..710980a 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -245,17 +245,17 @@ def do_request(self, json_obj): try: response = opener.open(request, timeout=self.timeout) except ssl.SSLError as e: - if e.message == "The read operation timed out": + if hasattr(e, 'message') and e.message == "The read operation timed out": raise APITimeout("SSL read timeout",) else: - raise e + raise ZabbixAPIException("Unknown error") except socket.timeout as e: raise APITimeout("HTTP read timeout",) except urllib2.URLError as e: - if "Connection timed out" in e.message: + if hasattr(e, 'message') and "Connection timed out" in e.message: raise APITimeout("HTTP read timeout",) else: - raise e + raise ZabbixAPIException("Unknown error") self.debug(logging.INFO, "Response Code: " + str(response.code)) # NOTE: Getting a 412 response code means the headers are not in the From b51b8c613e0b3b9b66155df2b0168ed769977163 Mon Sep 17 00:00:00 2001 From: Stefano Stella Date: Wed, 1 Feb 2017 14:38:33 +0100 Subject: [PATCH 67/84] pep8 compliant --- zabbix/zabbix_api.py | 50 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 710980a..9320f47 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -1,24 +1,24 @@ # 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 +# 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 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. +# 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 +# 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: @@ -64,6 +64,7 @@ def checkauth(fn): """ Decorator to check authentication of the decorated method """ + def ret(self, *args): self.__checkauth__() return fn(self, args) @@ -72,14 +73,15 @@ def ret(self, *args): def dojson(fn): def wrapper(self, method, opts): - self.logger.log(logging.DEBUG, \ - "Going to do_request for %s with opts %s" \ + 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 class ZabbixAPIException(Exception): + """ generic zabbix api exception code list: -32602 - Invalid params (eg already exists) @@ -93,6 +95,7 @@ class Already_Exists(ZabbixAPIException): class InvalidProtoError(ZabbixAPIException): + """ Recived an invalid proto """ pass @@ -137,7 +140,7 @@ def __init__(self, server='http://localhost/zabbix', user=httpuser, passwd=httpp self.server = server self.url = server + '/api_jsonrpc.php' self.proto = self.server.split("://")[0] - #self.proto=proto + # self.proto=proto self.httpuser = user self.httppasswd = passwd self.timeout = timeout @@ -174,9 +177,9 @@ def json_obj(self, method, params={}, auth=True): 'method': method, 'params': params, 'auth': self.auth, - 'id': self.id - } - if not auth: del obj['auth'] + 'id': self.id} + if not auth: + del obj['auth'] self.debug(logging.DEBUG, "json_obj: " + str(obj)) @@ -198,7 +201,7 @@ def login(self, user='', password='', save=True): # 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" % \ + self.debug(logging.DEBUG, "Trying to login with %s:%s" % (repr(l_user), repr(hashed_pw_string))) obj = self.json_obj('user.login', {'user': l_user, 'password': l_password}, auth=False) result = self.do_request(obj) @@ -231,7 +234,7 @@ def do_request(self, json_obj): 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()) + https_handler = urllib2.HTTPSHandler(debuglevel=0, context=_create_unverified_context()) else: https_handler = urllib2.HTTPSHandler(debuglevel=0) opener = urllib2.build_opener(https_handler) @@ -303,6 +306,7 @@ def __getattr__(self, name): class ZabbixAPISubClass(ZabbixAPI): + """ wrapper class to ensure all calls go through the parent object """ parent = None data = None From 7a6f0c6d07ce9efcbf665dba12e67f431b9eae6b Mon Sep 17 00:00:00 2001 From: Stefano Stella Date: Wed, 1 Feb 2017 16:59:15 +0100 Subject: [PATCH 68/84] better exception handling --- zabbix/zabbix_api.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 9320f47..d9f4e3d 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -248,17 +248,15 @@ def do_request(self, json_obj): try: response = opener.open(request, timeout=self.timeout) except ssl.SSLError as e: - if hasattr(e, 'message') and e.message == "The read operation timed out": - raise APITimeout("SSL read timeout",) - else: - raise ZabbixAPIException("Unknown error") + 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 "Connection timed out" in e.message: - raise APITimeout("HTTP read timeout",) - else: - raise ZabbixAPIException("Unknown error") + if hasattr(e, 'message'): + e = e.message + 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 From 8407485ecdd0dabf5072d16ae9782ff1942fc70f Mon Sep 17 00:00:00 2001 From: gescheit Date: Wed, 8 Feb 2017 18:53:43 +0300 Subject: [PATCH 69/84] add 3.0 and 3.2 --- zabbix/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/README.md b/zabbix/README.md index 1ccd375..032253a 100644 --- a/zabbix/README.md +++ b/zabbix/README.md @@ -5,7 +5,7 @@ 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 are supported. +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. From 10c7c73c8e5d909fc115a138dc19b5a93977966d Mon Sep 17 00:00:00 2001 From: Josh Soref Date: Tue, 14 Mar 2017 21:52:19 -0400 Subject: [PATCH 70/84] handle internal server errors --- zabbix/zabbix_api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index d9f4e3d..841763d 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -254,8 +254,10 @@ def do_request(self, json_obj): except socket.timeout as e: raise APITimeout("HTTP read timeout",) except urllib2.URLError as e: - if hasattr(e, 'message'): + if hasattr(e, 'message') and e.message: e = e.message + elsif hasattr(e, 'reason'): + e = e.reason raise ZabbixAPIException("urllib2.URLError - %s" % e) self.debug(logging.INFO, "Response Code: " + str(response.code)) From c1a892f5ecaeac6bd999f4bd461eb8f49783d92f Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 4 May 2017 16:20:48 +0100 Subject: [PATCH 71/84] fixing SyntaxError in line 259, should be elif NOTelsif --- zabbix/zabbix_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 841763d..bfe6799 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -256,7 +256,7 @@ def do_request(self, json_obj): except urllib2.URLError as e: if hasattr(e, 'message') and e.message: e = e.message - elsif hasattr(e, 'reason'): + elif hasattr(e, 'reason'): e = e.reason raise ZabbixAPIException("urllib2.URLError - %s" % e) self.debug(logging.INFO, "Response Code: " + str(response.code)) From a9b320e4bfa51c43df2451c3558943963a53eed7 Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Wed, 12 Jul 2017 15:47:51 +0300 Subject: [PATCH 72/84] fix api_version() --- zabbix/zabbix_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index bfe6799..fbdb2bc 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -293,8 +293,7 @@ def logged_in(self): return False def api_version(self, **options): - self.__checkauth__() - obj = self.do_request(self.json_obj('APIInfo.version', options, auth=False)) + obj = self.do_request(self.json_obj('apiinfo.version', options, auth=False)) return obj['result'] def __checkauth__(self): From 06a7cd7d2fcbd9ad74c0ee3577b586156c3d8ab6 Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Tue, 19 Sep 2017 11:16:12 +0300 Subject: [PATCH 73/84] release 0.5 --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index c5d97b8..f38c82f 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -15,7 +15,7 @@ def read(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.3', + version='0.5', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com', From 45d20e43f5a015a04e39058dc2c67c7c097b3ae8 Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Tue, 19 Sep 2017 12:29:45 +0300 Subject: [PATCH 74/84] fix pypi doc --- zabbix/setup.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index f38c82f..3f99631 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -8,19 +8,26 @@ from setuptools import setup, find_packages, findall -def read(fname): - return open(os.path.join(os.path.dirname(__file__), fname)).read() +def read_descr(fname): + filepath = os.path.join(os.path.dirname(__file__), fname) + try: + import pypandoc + long_description = pypandoc.convert(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', + version='0.5.1', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com', description='Zabbix API', - long_description=read('README.md'), + long_description=read_descr('README.md'), py_modules=['zabbix_api'], include_package_data=True, zip_safe=False, From 386aa22297a659816e6b0071de92fb926c6dc159 Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Wed, 20 Sep 2017 00:04:21 +0300 Subject: [PATCH 75/84] add README.md to MANIFEST Thanks to Steven Foerster! --- zabbix/MANIFEST.in | 1 + zabbix/setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 zabbix/MANIFEST.in 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/setup.py b/zabbix/setup.py index 3f99631..c2434be 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -22,7 +22,7 @@ def read_descr(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.5.1', + version='0.5.3', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com', From fa3bec199a167257d2291b408dd9b2332a1a883b Mon Sep 17 00:00:00 2001 From: robin Date: Tue, 24 Apr 2018 17:21:11 +0800 Subject: [PATCH 76/84] add logout method --- zabbix/zabbix_api.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index fbdb2bc..31fc7df 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -207,6 +207,17 @@ def login(self, user='', password='', save=True): result = self.do_request(obj) self.auth = result['result'] + def logout(self): + 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}) From 9ff96176e9790ea7895290ee70e3c52ef9b8e410 Mon Sep 17 00:00:00 2001 From: Hossein Zolfi Date: Wed, 26 Dec 2018 21:00:55 +0330 Subject: [PATCH 77/84] Fix python3 authorization problem --- zabbix/zabbix_api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index fbdb2bc..b13414c 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -225,7 +225,8 @@ def do_request(self, json_obj): if self.httpuser: self.debug(logging.INFO, "HTTP Auth enabled") - auth = 'Basic ' + string.strip(base64.encodestring(self.httpuser + ':' + self.httppasswd)) + 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)) From 2dddc0fc2ab71e0016128142c459e34f96fcad5b Mon Sep 17 00:00:00 2001 From: Hossein Zolfi Date: Sat, 6 Apr 2019 11:52:16 +0430 Subject: [PATCH 78/84] Update setup version Change version because some patches are merged. --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index c2434be..2165bd6 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -22,7 +22,7 @@ def read_descr(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.5.3', + version='0.5.4', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com', From 13b085e18f08b00b096197b77476b7f930e78273 Mon Sep 17 00:00:00 2001 From: Andrew Nelson Date: Thu, 22 Sep 2022 12:00:59 -0400 Subject: [PATCH 79/84] Added token based authentication --- zabbix/zabbix_api.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 4d4c346..032a173 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -107,6 +107,7 @@ class APITimeout(ZabbixAPIException): class ZabbixAPI(object): __username__ = '' __password__ = '' + __tokenauth__ = False auth = '' url = '/api_jsonrpc.php' @@ -185,7 +186,16 @@ def json_obj(self, method, params={}, auth=True): return json.dumps(obj) - def login(self, user='', password='', save=True): + 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 @@ -208,6 +218,14 @@ def login(self, user='', password='', save=True): 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__) From 4fce6114e0c35a4664bcf87e4dc30ce847c9f370 Mon Sep 17 00:00:00 2001 From: Aleksandr Artemev Date: Mon, 24 Oct 2022 12:11:16 +0200 Subject: [PATCH 80/84] pypandoc call fix --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index 2165bd6..9b8d1b4 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -12,7 +12,7 @@ def read_descr(fname): filepath = os.path.join(os.path.dirname(__file__), fname) try: import pypandoc - long_description = pypandoc.convert(filepath, 'rst') + long_description = pypandoc.convert_file(filepath, 'rst') except(IOError, ImportError): long_description = open(filepath).read() From a3959e9953bdc89078e1473e0df35d3d4c314b71 Mon Sep 17 00:00:00 2001 From: Aleksandr Artemev Date: Fri, 28 Oct 2022 14:32:23 +0200 Subject: [PATCH 81/84] version bump --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index 9b8d1b4..5073bc7 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -22,7 +22,7 @@ def read_descr(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.5.4', + version='0.5.5', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com', From 6d10ab1ea1b641f3967488a910dff7e995c41f95 Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Fri, 28 Apr 2023 17:54:26 +0300 Subject: [PATCH 82/84] fix new username field name --- zabbix/zabbix_api.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index 032a173..acfa86d 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -79,6 +79,8 @@ def wrapper(self, method, opts): return self.do_request(self.json_obj(method, opts))['result'] return wrapper +def versiontuple(v): + return tuple(map(int, (v.split(".")))) class ZabbixAPIException(Exception): @@ -213,7 +215,11 @@ def login(self, user='', password='', save=True, api_token=None): 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))) - obj = self.json_obj('user.login', {'user': l_user, 'password': l_password}, auth=False) + if versiontuple(self.api_version()) >= versiontuple('5.4'): + 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'] From 1cf7abb90c62c0726b101ac4e1dfcd66415d4c6e Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Fri, 28 Apr 2023 19:06:48 +0300 Subject: [PATCH 83/84] fix --- zabbix/zabbix_api.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/zabbix/zabbix_api.py b/zabbix/zabbix_api.py index acfa86d..000f76f 100644 --- a/zabbix/zabbix_api.py +++ b/zabbix/zabbix_api.py @@ -79,8 +79,24 @@ def wrapper(self, method, opts): return self.do_request(self.json_obj(method, opts))['result'] return wrapper -def versiontuple(v): - return tuple(map(int, (v.split(".")))) + +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): @@ -215,7 +231,7 @@ def login(self, user='', password='', save=True, api_token=None): 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 versiontuple(self.api_version()) >= versiontuple('5.4'): + 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} From 99dbb3975c112df0db2b5a61822e981a637f4d29 Mon Sep 17 00:00:00 2001 From: Aleksandr Balezin Date: Fri, 28 Apr 2023 19:18:11 +0300 Subject: [PATCH 84/84] bump version --- zabbix/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zabbix/setup.py b/zabbix/setup.py index 5073bc7..a74d0e2 100755 --- a/zabbix/setup.py +++ b/zabbix/setup.py @@ -22,7 +22,7 @@ def read_descr(fname): setup( name='zabbix-api', url='https://github.com/gescheit/scripts', - version='0.5.5', + version='0.5.6', license='GNU LGPL 2.1', author='Aleksandr Balezin', author_email='gescheit12@gmail.com',