Chinaunix首页 | 论坛 | 博客
  • 博客访问: 351985
  • 博文数量: 26
  • 博客积分: 495
  • 博客等级: 下士
  • 技术积分: 562
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-26 13:50
文章分类

全部博文(26)

文章存档

2015年(9)

2014年(6)

2013年(7)

2012年(2)

2011年(2)

分类: 系统运维

2015-09-21 17:46:11

 前段时间,公司扩张机器,一下来了几十台,虽然可以利用zabbix自动发现来添加监控项目,但是并不是每个监控项都可以实现自动添加,需要手动一台一台去添加,相当蛋疼麻烦,好在前段时间就已经发现这个问题了,于是自己写了个CLI 模式的添加工具,好记性不如烂笔头,现在是深有体会,脚本是基于python 2.6 的,代码如下

zabbix.py

点击(此处)折叠或打开

  1. #!/usr/bin/python
  2. #coding:utf-8
  3. #@desc A Simple Zabbix CLI Tool
  4. #@author luma
  5. #@email 825244020@qq.com
  6. #@date 2015.6.30


  7. from functools import wraps
  8. import sys
  9. import json
  10. import requests
  11. import sys
  12. from optparse import OptionParser


  13. def CheckLogin(func):
  14.     def wrapper(self,*args,**kwargs):
  15.         if not self.__checkauth__():
  16.             sys.exit('Not Login!')
  17.         return func(self,*args,**kwargs)
  18.     return wrapper


  19. class Zabbix(object):
  20.     """ A Zabbix Simple Python API on v2.6 """
  21.     uri = '/api_jsonrpc.php'

  22.     def __init__(self,ipaddr,timeout=300):
  23.         self.ipaddr = ipaddr
  24.         self.url = self.ipaddr+self.uri
  25.         self.timeout = timeout
  26.         self.auth=''

  27.     def Login(self,user,passwd):
  28.         obj = self.DoJSON('user.login',{'user':user, 'password': passwd},auth=False)
  29.         self.auth = self.DoRequest(obj)

  30.     def __checkauth__(self):
  31.         if self.auth:
  32.             return True
  33.         return False


  34.     def DoJSON(self,method,params={},auth=True):
  35.         obj = {
  36.             'jsonrpc': '2.0',
  37.             'method': method,
  38.             'params': params,
  39.             'auth': self.auth,
  40.              'id': 1
  41.         }
  42.         if not auth:del obj['auth']

  43.         return json.dumps(obj)


  44.     def DoRequest(self,params):
  45.         headers = {"Content-Type": "application/json;charset=utf-8"}
  46.         try:
  47.             response = requests.post(self.url,data=params,headers=headers,timeout=self.timeout)
  48.         except Exception, e:
  49.             print 'exception:'+e
  50.         else:
  51.             if response.status_code != 200:
  52.                 print 'request error %s' % response.status_code
  53.             try:
  54.                 #print response.text
  55.                 rsp = json.loads(response.text)
  56.                 if rsp.has_key('error'):
  57.                    print rsp['error']
  58.                 else:
  59.                    return rsp['result']
  60.             except Exception,e:
  61.                 print e

  62.     @CheckLogin
  63.     def DoAction(self,method,params):
  64.         o = self.DoJSON(method,params)
  65.         return self.DoRequest(o)


  66. '''check item exists'''
  67. def CheckExist(method):
  68.     item = method.split('.')[0].capitalize()
  69.     def decorator(fn):
  70.         @wraps(fn)
  71.         def wrapper(self,*args,**kwargs):
  72.             kw = args[0]
  73.             _index = ['host','name','expression','_key']
  74.             for i in _index:
  75.                 if kw.has_key(i):
  76.                     if self.universal(method,{'name':kw.get(i)}):
  77.                         if item == 'Item':
  78.                             print "ERROR::[\033[40;32m%s\033[0m:\033[40;31m%s\033[0m] is already exists" % (kw.get('host'),kw.get('key'))
  79.                         else:
  80.                             print "ERROR::[\033[40;32m%s\033[0m:\033[40;31m%s\033[0m] is already exists" % (item,kw.get(i))
  81.                     else:
  82.                         fn(self,*args,**kwargs)
  83.                     break
  84.         return wrapper
  85.     return decorator

  86. '''import from file '''
  87. def ImportObject(idx,tag):
  88.     def decorator(fn):
  89.         @wraps(fn)
  90.         def wrapper(self,*args,**kwargs):
  91.             file = args[0].get('file')
  92.             m = fn(self,*args,**kwargs)
  93.             with open(file) as f:
  94.                 hosts = [ x.strip('\n') for x in f.readlines()]
  95.                 if tag == 'host':
  96.                     for h in hosts:
  97.                         if len(h):L = h.split('\t')
  98.                         L[0] = dict(self.ifcfg,ip=L[0])
  99.                         L[2] = L[2].split(',')
  100.                         L[3] = L[3].split(',')
  101.                         m(dict(zip(idx,L)))
  102.                 else:
  103.                     for h in hosts:
  104.                         if len(h):L = h.split('\t') #tab 分割符号
  105.                         m(dict(zip(idx,L)))
  106.         return wrapper
  107.     return decorator


  108. class Worker():
  109.     """A Zabbix Worker Class"""

  110.     def __init__(self, url,user='Admin',password='zabbix',**kw):
  111.         self.zbx = Zabbix(url)
  112.         self.zbx.Login(user,password)
  113.         self.ifcfg = {
  114.             "type": 1,
  115.             "main": 1,
  116.             "useip":1,
  117.             "dns": "",
  118.             "port": "10050"
  119.         }
  120.         if kw.has_key('ifcfg'):self.ifcfg = kw['ifcfg']


  121.     def getTemplateIdByName(self,tname,grep):
  122.         #qc = 'query' if sort else ['name','templateid'] python 三目操作
  123.         '''tname 可以是多个'''
  124.         params = {'output':grep,'filter':{'host':tname}}
  125.         return self.zbx.DoAction('template.get',params),

  126.     def getGroupIdByName(self,grpname,grep):
  127.         params = {'output':grep,'filter':{'name':grpname}}
  128.         return self.zbx.DoAction('hostgroup.get',params)

  129.     def getHostIdByName(self,name,grep):
  130.         params = {'output':grep,'filter':{'host':name}}
  131.         return self.zbx.DoAction('host.get',params)

  132.     def getAppIdByName(self,**kwargs):
  133.         #@kwargs => groupids,hostids,itemids
  134.         #params = {'output':'query','filter'}
  135.         pass

  136.     def getItemIdByHost(self,hosts=[],search={},grep=['query']):
  137.         hostid = self.getHostIdByName(hosts,['hostid'])
  138.         L = [ x['hostid'] for x in hostid]
  139.         params = { 'output':grep,'hostids':L,'search':search}
  140.         return self.zbx.DoAction('item.get',params)

  141.     def getInterfaceIdByHost(self,hostnames,grep):
  142.         hostids = self.getHostIdByName(hostnames,['query'])
  143.         params = {
  144.             'output':grep,
  145.             'hostids':hostids[0]['hostid']
  146.         }
  147.         return self.zbx.DoAction('hostinterface.get',params)

  148.     @CheckExist('host.exists')
  149.     def createHost(self,obj,**kwargs):
  150.         '''@name 主机名称
  151.            @groups 隶属组
  152.            @interfaces 接口配置
  153.            @templates 隶属模板
  154.         '''
  155.         groupids = self.getGroupIdByName(obj.get('groups'),['groupid'])
  156.         templateids = self.getTemplateIdByName(obj.get('templates'),['templateid'])
  157.         params = {
  158.             'host':obj.get('host'),
  159.             'interfaces':[obj.get('interfaces')], ##可以考虑默认属性
  160.             'groups':groupids,
  161.             'templates':templateids[0]
  162.         }
  163.         v = self.zbx.DoAction('host.create',dict(params,**kwargs))
  164.         print '%s created ' % obj.get('host')
  165.         return v

  166.    
  167.     @ImportObject(['interfaces','host','groups','templates'],'host')
  168.     def importHosts(self,obj):
  169.         print '''
  170.                   import file must be contains these fields desc,expression,host
  171.                   and no blank lines,Notice each field separate as Tab,eg:
  172.                   just a test system.cpu.load[all,avg1] howge1
  173.               '''
  174.         str = raw_input("Are you sure you file format is right?(y/Y): ")
  175.         if str in ['y','Y']:
  176.             return self.createHost
  177.         else:
  178.             sys.exit('Answer Y or y !')
  179.            
  180.     @CheckExist('hostgroup.exists')
  181.     def createGroup(self,obj):
  182.         '''@name 组名 '''
  183.         v = self.zbx.DoAction('hostgroup.create',obj)
  184.         print 'Hostgroup %s Created!' % obj.get('name')
  185.         return v

  186.     @CheckExist('template.exists')
  187.     def createTemplate(self,obj):
  188.         '''@groups 隶属组名
  189.            @hosts 主机成员
  190.         '''
  191.         groupids = self.getGroupIdByName(obj['groups'],['groupid'])
  192.         hostids = self.getHostIdByName(obj['hosts'],['hostid'])
  193.         params = {
  194.            'host':obj['host'],
  195.            'groups':groupids,
  196.            'hosts':hostids
  197.         }
  198.         return self.zbx.DoAction(params)

  199.     @CheckExist('item.exists')
  200.     def createItems(self,obj,type_v=0,value_type=3,delay=60,**kwargs):
  201.         '''@itemname item名称
  202.            @key item 键值
  203.            @hostname 主机名称
  204.         '''
  205.         hostid = self.getHostIdByName(obj['host'],['hostid'])
  206.         ifaceid = self.getInterfaceIdByHost(obj['host'],['query'])
  207.         params = {
  208.             'name' : obj.get('name'),
  209.             'key_' : obj.get('key'),
  210.             'hostid' : hostid[0]['hostid'],
  211.             'type' : type_v,
  212.             'value_type' : value_type,
  213.             'interfaceid' : ifaceid[0]['interfaceid'],
  214.             'delay' : delay
  215.         }
  216.         return self.zbx.DoAction('item.create',params)

  217.     @ImportObject(['name','key','host'],'items')
  218.     def importItems(self,obj):
  219.         print '''
  220.                   import file must be contains these fields ip,hostname,groups,templates
  221.                   and no blank lines,Notice each field separate as Tab,but groups and templates are
  222.                   separated as ',' eg:
  223.                   192.168.120.100 howge12 wanghao Zabbix servers,Template OS Linux
  224.               '''
  225.         str = raw_input("Are you sure you file format is right?(y/Y): ")
  226.         if str in ['y','Y']:
  227.             return self.createItems
  228.         else:
  229.             sys.exit()

  230.     @CheckExist('trigger.exists')
  231.     def createTrigger(self,obj,**kwargs):
  232.         '''@desc 触发器描述
  233.            @exp 表达式
  234.         '''
  235.         params = {
  236.             'description':obj.get('desc'),
  237.             'expression':obj.get('expression'),
  238.             'priority' : obj.get('level')
  239.         }
  240.         return self.zbx.DoAction('trigger.create',dict(params,**kwargs))
  241.     
  242.     @ImportObject(['desc','expression','level'],'trigger')
  243.     def importTrigger(self,obj):
  244.         print '''
  245.                  import file must be contains these fields name,expression,notice level and no blank lines
  246.                  eg:Test Disk I/O is overloaded on {HOST.NAME} {howge12:system.cpu.util[,iowait].avg(5m)}>30 5
  247.               '''
  248.         str = raw_input("Are you sure you file format is right?(y/Y): ")
  249.         if str in ['y','Y']:
  250.             return self.createTrigger
  251.         else:
  252.             sys.exit('Answer Y or y')

  253.     def createAPP(self,name='',hostname=''):
  254.         '''@name 应用名称
  255.            @hostname 隶属于主机
  256.         '''
  257.         hostid = self.getHostIdByName(hostname,['hostid'])
  258.         params = {
  259.             'name':name,
  260.             'hostid':hostid
  261.         }
  262.         ext = self.universal('application.exists',params)
  263.         if not ext:
  264.             return self.zbx.DoAction('application.create',params)
  265.         else:
  266.             print "Application: %s is already exists on host %s" % (name,hostname)

  267.     def universal(self,method,params):
  268.         return self.zbx.DoAction(method,params)
  269.    

  270.     @staticmethod
  271.     def getCLIOpts():
  272.         parser = OptionParser()
  273.         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] ")
  274.         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 ")
  275.         parser.add_option("-H","--host",dest="host",help="hostname",action='append')
  276.         parser.add_option("-T","--template",dest="template",help='Add a Template,some groups within this Template!',action='append')
  277.         parser.add_option("-I","--item",dest="item",help='item must have a key and a host ')
  278.         parser.add_option("-N","--name",dest="name",help='names of object ')
  279.         parser.add_option("-G","--group",dest="group",help='group name ',action='append')
  280.         parser.add_option("--file",dest="file",help='import object from file ,specially this option only support Host object')
  281.         parser.add_option("--ipddr",dest="ipaddr",help='ip address')
  282.         parser.add_option("--item-key",dest="ikey",help='item key')
  283.         parser.add_option("--trigger-exp",dest="texp",help='trigger expression')
  284.         parser.add_option("--trigger-level",dest="tlevel",help='trigger notice level')
  285.         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"})
  286.         parser.add_option("--filter",dest="filter",help='get filter field,referrence to Zabbix API doc',action='append')
  287.         (options, args) = parser.parse_args()
  288.         return (options,parser)

zbx_cli.py

点击(此处)折叠或打开

  1. #!/usr/bin/python
  2. #coding:utf8
  3. from zabbix import Worker

  4. #实例化自己的zabbix连接
  5. worker = Worker('http://192.168.120.221/zabbix')

  6. (options,parser) = Worker.getCLIOpts()

  7. ###添加操作######
  8. if options.action == 'add':
  9.    if options.object == 'host':
  10.        if options.file:
  11.            worker.importHosts({'file':options.file,'ifcfg':options.ifcfg})
  12.        else:
  13.           if not (options.name and options.group and options.template and options.ipaddr):
  14.              parser.error('hostname groups templates ipaddr are required!')
  15.           else:
  16.              G = (options.group)[0].split(',')
  17.              T = (options.template)[0].split(',')
  18.              #worker.createHost(options.name,groups=G,interfaces=dict(options.ifcfg,ip=options.ipaddr),templates=T)
  19.              worker.createHost({'host':options.name,'groups':G,'interfaces':dict(options.ifcfg,ip=options.ipaddr),'templates':T})
  20.    elif options.object == 'group':
  21.       if not options.name:
  22.          parser.error('group name is required!')
  23.       else:
  24.          worker.createGroup({'name':options.name})
  25.    elif options.object == 'temp':
  26.       if not (options.name and options.group and options.host):
  27.          parser.error('templatename and group and hosts are required!')
  28.       else:
  29.          G = (options.group)[0].split(',')
  30.          H = (options.host)[0].split(',')
  31.          worker.createTemplate({'host':options.name,'groups':G,'hosts':H})
  32.    elif options.object == 'item':
  33.       if options.file:
  34.           worker.importItems({'file':options.file})
  35.       else:
  36.           if not (options.name and options.host and options.ikey):
  37.              parser.error('item name,host must be specify and only one host allowed,item key expression required!')
  38.           else:
  39.              #如果需要添加额外的参数,请参考zabbix API,默认是60s
  40.              worker.createItems({'name':options.name,'key':options.ikey,'host':options.host})
  41.    elif options.object == 'trigger':
  42.       if options.file:
  43.           worker.importTrigger({'file':options.file})
  44.       else:
  45.           if not (options.name and options.texp and options.tlevel):
  46.              parser.error('trigger name and expression,trigger level are required!')
  47.           else:
  48.              #如果需要添加额外的参数,请参考zabbix API
  49.              worker.createTrigger({'desc':options.name,'expression':options.texp,'level':options.tlevel})

  50. ##查询操作###
  51. elif options.action == 'query':
  52.    if options.object == 'host':
  53.       pass
  54. ###更新操作###
  55. elif options.action == 'update':
  56.    if options.object == 'host':
  57.       pass
  58. ###删除操作##
  59. elif options.action == 'delete':
  60.    if options.object == 'host':
  61.       pass

使用方法:

点击(此处)折叠或打开

  1. 添加单台主机
  2. ./zbx_cli.py -X add -O host -N howge111 -G 'Zabbix servers',wanghao -T 'Template OS Linux' --ipddr=172.16.3.13
  3. 添加item
  4. ./zbx_cli.py -X add -O item -N JUST A TEST --item-key='system.cpu.load[all,avg1]' --host=howge1
  5. 添加触发器
  6. ./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
  7. 添加Template
  8. ./zbx_cli.py -X add -O temp -N test_temp -G huhu,wanghao -H huhu,master,node1
  9. 批量导入Item
  10. ./zbx_cli.py -X add -O item --file=item.txt
  11. 文件格式
  12. just a test system.cpu.load[all,avg1] howge1
  13. 批量导入HOST
  14. ./zbx_cli.py -X add -O host --file=imp.txt
  15. 文件格式(Tab 分隔)
  16. 192.168.120.100 howge1 wanghao Zabbix servers,Template OS Linux
  17. 批量导入Trigger
  18. ./zbx_cli.py -X add -O trigger --file=trig.txt
  19. 文件格式
  20. Test Disk I/O is overloaded on {HOST.NAME} {howge12:system.cpu.util[,iowait].avg(5m)}>30 5

总结:由于其他原因,我仅仅只做了添加操作,希望借此抛砖引玉,转载请标明出处



阅读(2079) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~