#!/usr/bin/python
#coding:utf-8
from functools import wraps
import sys
import json
import requests
import sys
from optparse import OptionParser
def CheckLogin(func):
def wrapper(self,*args,**kwargs):
if not self.__checkauth__():
sys.exit('Not Login!')
return func(self,*args,**kwargs)
return wrapper
class Zabbix(object):
""" A Zabbix Simple Python API on v2.6 """
uri = '/api_jsonrpc.php'
def __init__(self,ipaddr,timeout=300):
self.ipaddr = ipaddr
self.url = self.ipaddr+self.uri
self.timeout = timeout
self.auth=''
def Login(self,user,passwd):
obj = self.DoJSON('user.login',{'user':user, 'password': passwd},auth=False)
self.auth = self.DoRequest(obj)
def __checkauth__(self):
if self.auth:
return True
return False
def DoJSON(self,method,params={},auth=True):
obj = {
'jsonrpc': '2.0',
'method': method,
'params': params,
'auth': self.auth,
'id': 1
}
if not auth:del obj['auth']
return json.dumps(obj)
def DoRequest(self,params):
headers = {"Content-Type": "application/json;charset=utf-8"}
try:
response = requests.post(self.url,data=params,headers=headers,timeout=self.timeout)
except Exception, e:
print 'exception:'+e
else:
if response.status_code != 200:
print 'request error %s' % response.status_code
try:
#print response.text
rsp = json.loads(response.text)
if rsp.has_key('error'):
print rsp['error']
else:
return rsp['result']
except Exception,e:
print e
@CheckLogin
def DoAction(self,method,params):
o = self.DoJSON(method,params)
return self.DoRequest(o)
'''check item exists'''
def CheckExist(method):
item = method.split('.')[0].capitalize()
def decorator(fn):
@wraps(fn)
def wrapper(self,*args,**kwargs):
kw = args[0]
_index = ['host','name','expression','_key']
for i in _index:
if kw.has_key(i):
if self.universal(method,{'name':kw.get(i)}):
if item == 'Item':
print "ERROR::[\033[40;32m%s\033[0m:\033[40;31m%s\033[0m] is already exists" % (kw.get('host'),kw.get('key'))
else:
print "ERROR::[\033[40;32m%s\033[0m:\033[40;31m%s\033[0m] is already exists" % (item,kw.get(i))
else:
fn(self,*args,**kwargs)
break
return wrapper
return decorator
'''import from file '''
def ImportObject(idx,tag):
def decorator(fn):
@wraps(fn)
def wrapper(self,*args,**kwargs):
file = args[0].get('file')
m = fn(self,*args,**kwargs)
with open(file) as f:
hosts = [ x.strip('\n') for x in f.readlines()]
if tag == 'host':
for h in hosts:
if len(h):L = h.split('\t')
L[0] = dict(self.ifcfg,ip=L[0])
L[2] = L[2].split(',')
L[3] = L[3].split(',')
m(dict(zip(idx,L)))
else:
for h in hosts:
if len(h):L = h.split('\t') #tab 分割符号
m(dict(zip(idx,L)))
return wrapper
return decorator
class Worker():
"""A Zabbix Worker Class"""
def __init__(self, url,user='Admin',password='zabbix',**kw):
self.zbx = Zabbix(url)
self.zbx.Login(user,password)
self.ifcfg = {
"type": 1,
"main": 1,
"useip":1,
"dns": "",
"port": "10050"
}
if kw.has_key('ifcfg'):self.ifcfg = kw['ifcfg']
def getTemplateIdByName(self,tname,grep):
#qc = 'query' if sort else ['name','templateid'] python 三目操作
'''tname 可以是多个'''
params = {'output':grep,'filter':{'host':tname}}
return self.zbx.DoAction('template.get',params),
def getGroupIdByName(self,grpname,grep):
params = {'output':grep,'filter':{'name':grpname}}
return self.zbx.DoAction('hostgroup.get',params)
def getHostIdByName(self,name,grep):
params = {'output':grep,'filter':{'host':name}}
return self.zbx.DoAction('host.get',params)
def getAppIdByName(self,**kwargs):
#@kwargs => groupids,hostids,itemids
#params = {'output':'query','filter'}
pass
def getItemIdByHost(self,hosts=[],search={},grep=['query']):
hostid = self.getHostIdByName(hosts,['hostid'])
L = [ x['hostid'] for x in hostid]
params = { 'output':grep,'hostids':L,'search':search}
return self.zbx.DoAction('item.get',params)
def getInterfaceIdByHost(self,hostnames,grep):
hostids = self.getHostIdByName(hostnames,['query'])
params = {
'output':grep,
'hostids':hostids[0]['hostid']
}
return self.zbx.DoAction('hostinterface.get',params)
@CheckExist('host.exists')
def createHost(self,obj,**kwargs):
'''@name 主机名称
@groups 隶属组
@interfaces 接口配置
@templates 隶属模板
'''
groupids = self.getGroupIdByName(obj.get('groups'),['groupid'])
templateids = self.getTemplateIdByName(obj.get('templates'),['templateid'])
params = {
'host':obj.get('host'),
'interfaces':[obj.get('interfaces')], ##可以考虑默认属性
'groups':groupids,
'templates':templateids[0]
}
v = self.zbx.DoAction('host.create',dict(params,**kwargs))
print '%s created ' % obj.get('host')
return v
@ImportObject(['interfaces','host','groups','templates'],'host')
def importHosts(self,obj):
print '''
import file must be contains these fields desc,expression,host
and no blank lines,Notice each field separate as Tab,eg:
just a test system.cpu.load[all,avg1] machine1
'''
str = raw_input("Are you sure you file format is right?(y/Y): ")
if str in ['y','Y']:
return self.createHost
else:
sys.exit('Answer Y or y !')
@CheckExist('hostgroup.exists')
def createGroup(self,obj):
'''@name 组名 '''
v = self.zbx.DoAction('hostgroup.create',obj)
print 'Hostgroup %s Created!' % obj.get('name')
return v
@CheckExist('template.exists')
def createTemplate(self,obj):
'''@groups 隶属组名
@hosts 主机成员
'''
groupids = self.getGroupIdByName(obj['groups'],['groupid'])
hostids = self.getHostIdByName(obj['hosts'],['hostid'])
params = {
'host':obj['host'],
'groups':groupids,
'hosts':hostids
}
return self.zbx.DoAction(params)
@CheckExist('item.exists')
def createItems(self,obj,type_v=0,value_type=3,delay=60,**kwargs):
'''@itemname item名称
@key item 键值
@hostname 主机名称
'''
hostid = self.getHostIdByName(obj['host'],['hostid'])
ifaceid = self.getInterfaceIdByHost(obj['host'],['query'])
params = {
'name' : obj.get('name'),
'key_' : obj.get('key'),
'hostid' : hostid[0]['hostid'],
'type' : type_v,
'value_type' : value_type,
'interfaceid' : ifaceid[0]['interfaceid'],
'delay' : delay
}
return self.zbx.DoAction('item.create',params)
@ImportObject(['name','key','host'],'items')
def importItems(self,obj):
print '''
import file must be contains these fields ip,hostname,groups,templates
and no blank lines,Notice each field separate as Tab,but groups and templates are
separated as ',' eg:
192.168.120.100 machine12 wanghao Zabbix servers,Template OS Linux
'''
str = raw_input("Are you sure you file format is right?(y/Y): ")
if str in ['y','Y']:
return self.createItems
else:
sys.exit()
@CheckExist('trigger.exists')
def createTrigger(self,obj,**kwargs):
'''@desc 触发器描述
@exp 表达式
'''
params = {
'description':obj.get('desc'),
'expression':obj.get('expression'),
'priority' : obj.get('level')
}
return self.zbx.DoAction('trigger.create',dict(params,**kwargs))
@ImportObject(['desc','expression','level'],'trigger')
def importTrigger(self,obj):
print '''
import file must be contains these fields name,expression,notice level and no blank lines
eg:Test Disk I/O is overloaded on {HOST.NAME} {machine12:system.cpu.util[,iowait].avg(5m)}>30 5
'''
str = raw_input("Are you sure you file format is right?(y/Y): ")
if str in ['y','Y']:
return self.createTrigger
else:
sys.exit('Answer Y or y')
def createAPP(self,name='',hostname=''):
'''@name 应用名称
@hostname 隶属于主机
'''
hostid = self.getHostIdByName(hostname,['hostid'])
params = {
'name':name,
'hostid':hostid
}
ext = self.universal('application.exists',params)
if not ext:
return self.zbx.DoAction('application.create',params)
else:
print "Application: %s is already exists on host %s" % (name,hostname)
def universal(self,method,params):
return self.zbx.DoAction(method,params)
@staticmethod
def getCLIOpts():
parser = OptionParser()
parser.add_option("-X","--action",dest="action",type='choice',action='store',choices=['add','query','del','import'],help="choose a Action in [query,add,del,import] ")
parser.add_option("-O","--object",dest="object",type='choice',action='store',choices=['host','temp','group','app','item','trigger'],help="add a host,group,tmplate,application or an item ")
parser.add_option("-H","--host",dest="host",help="hostname",action='append')
parser.add_option("-T","--template",dest="template",help='Add a Template,some groups within this Template!',action='append')
parser.add_option("-I","--item",dest="item",help='item must have a key and a host ')
parser.add_option("-N","--name",dest="name",help='names of object ')
parser.add_option("-G","--group",dest="group",help='group name ',action='append')
parser.add_option("--file",dest="file",help='import object from file ,specially this option only support Host object')
parser.add_option("--ipddr",dest="ipaddr",help='ip address')
parser.add_option("--item-key",dest="ikey",help='item key')
parser.add_option("--trigger-exp",dest="texp",help='trigger expression')
parser.add_option("--trigger-level",dest="tlevel",help='trigger notice level')
parser.add_option("--ifcfg",dest="ifcfg",help='default value is {"type": 1,"main": 1,"useip": 1,"dns": "","port": "10050"}',default={"type": 1,"main": 1,"useip": 1,"dns": "","port": "10050"})
parser.add_option("--filter",dest="filter",help='get filter field,referrence to Zabbix API doc',action='append')
(options, args) = parser.parse_args()
return (options,parser)
####################
#!/usr/bin/python
#coding:utf8
from zabbix import Worker
#实例化zabbix连接
worker = Worker('')
(options,parser) = Worker.getCLIOpts()
###添加操作######
if options.action == 'add':
if options.object == 'host':
if options.file:
worker.importHosts({'file':options.file,'ifcfg':options.ifcfg})
else:
if not (options.name and options.group and options.template and options.ipaddr):
parser.error('hostname groups templates ipaddr are required!')
else:
G = (options.group)[0].split(',')
T = (options.template)[0].split(',')
#worker.createHost(options.name,groups=G,interfaces=dict(options.ifcfg,ip=options.ipaddr),templates=T)
worker.createHost({'host':options.name,'groups':G,'interfaces':dict(options.ifcfg,ip=options.ipaddr),'templates':T})
elif options.object == 'group':
if not options.name:
parser.error('group name is required!')
else:
worker.createGroup({'name':options.name})
elif options.object == 'temp':
if not (options.name and options.group and options.host):
parser.error('templatename and group and hosts are required!')
else:
G = (options.group)[0].split(',')
H = (options.host)[0].split(',')
worker.createTemplate({'host':options.name,'groups':G,'hosts':H})
elif options.object == 'item':
if options.file:
worker.importItems({'file':options.file})
else:
if not (options.name and options.host and options.ikey):
parser.error('item name,host must be specify and only one host allowed,item key expression required!')
else:
#如果需要添加额外的参数,请参考zabbix API,默认是60s
worker.createItems({'name':options.name,'key':options.ikey,'host':options.host})
elif options.object == 'trigger':
if options.file:
worker.importTrigger({'file':options.file})
else:
if not (options.name and options.texp and options.tlevel):
parser.error('trigger name and expression,trigger level are required!')
else:
#如果需要添加额外的参数,请参考zabbix API
worker.createTrigger({'desc':options.name,'expression':options.texp,'level':options.tlevel})
##查询操作###
elif options.action == 'query':
if options.object == 'host':
pass
###更新操作###
elif options.action == 'update':
if options.object == 'host':
pass
###删除操作##
elif options.action == 'delete':
if options.object == 'host':
pass
用法:
添加单台主机
./zbx_cli.py -X add -O host -N server111 -G 'Zabbix servers',web -T 'Template OS Linux' --ipddr=172.16.3.13
添加item
./zbx_cli.py -X add -O item -N JUST A TEST --item-key='system.cpu.load[all,avg1]' --host=server1
添加触发器
./zbx_cli.py -X add -O trigger -N 'Test Disk I/O is overloaded on {HOST.NAME}' --trigger-exp='{server12:system.cpu.util[,iowait].avg(5m)}>30' --trigger-level=4
添加Template
./zbx_cli.py -X add -O temp -N test_temp -G huhu,wanghao -H huhu,master,node1
批量导入Item
./zbx_cli.py -X add -O item --file=item.txt
文件格式
just a test system.cpu.load[all,avg1] server1
批量导入HOST
./zbx_cli.py -X add -O host --file=imp.txt
文件格式(Tab 分隔)
192.168.120.100 server1 wanghao Zabbix servers,Template OS Linux
批量导入Trigger
./zbx_cli.py -X add -O trigger --file=trig.txt
文件格式
Test Disk I/O is overloaded on {HOST.NAME} {server12:system.cpu.util[,iowait].avg(5m)}>30 5