前段时间,公司扩张机器,一下来了几十台,虽然可以利用zabbix自动发现来添加监控项目,但是并不是每个监控项都可以实现自动添加,需要手动一台一台去添加,相当蛋疼麻烦,好在前段时间就已经发现这个问题了,于是自己写了个CLI 模式的添加工具,好记性不如烂笔头,现在是深有体会,脚本是基于python 2.6 的,代码如下
zabbix.py
-
#!/usr/bin/python
-
#coding:utf-8
-
#@desc A Simple Zabbix CLI Tool
-
#@author luma
-
#@email 825244020@qq.com
-
#@date 2015.6.30
-
-
-
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] howge1
-
'''
-
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 howge12 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} {howge12: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)
zbx_cli.py
-
#!/usr/bin/python
-
#coding:utf8
-
from zabbix import Worker
-
-
#实例化自己的zabbix连接
-
worker = Worker('http://192.168.120.221/zabbix')
-
-
(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 howge111 -G 'Zabbix servers',wanghao -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=howge1
-
-
添加触发器
-
./zbx_cli.py -X add -O trigger -N 'Test Disk I/O is overloaded on {HOST.NAME}' --trigger-exp='{howge12: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] howge1
-
-
-
批量导入HOST
-
./zbx_cli.py -X add -O host --file=imp.txt
-
文件格式(Tab 分隔)
-
-
192.168.120.100 howge1 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} {howge12:system.cpu.util[,iowait].avg(5m)}>30 5
总结:由于其他原因,我仅仅只做了添加操作,希望借此抛砖引玉,转载请标明出处
阅读(2068) | 评论(0) | 转发(0) |