要写这篇博客其实我的内心是纠结的,老实说,我对zabbix的了解实在不多。但新公司的需求不容置疑,当我顶着有两个头大的脑袋懵懵转入运维领域时,面前摆着两百多组、上千台机器等着写入zabbix监控的需求(这种心境你们随意感受下就好),也尝试从网上查各种现成的资料,希望能找到解救自我的一些蛛丝马迹,然而发现大家在使用zabbix的时候都局限在“主机、查询组、模板的增删改查上”,甚至还贴心的封装成“类”以供调用。却不符合我要对Action进行配置的需求。几经挣扎,还是结合官网解释+自我臆测得到了想要的答案。最终实现了几百条action规则的批量创建,完成了自救。
zabbix API简介
为什么要调用zabbix API?
zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案,随着zabbix在企业中被广泛的应用,Zabbix API开始扮演着越来越重要的角色,尤其是在集成第三方软件和自动化日常任务时。很难想象管理数千台服务器而没有自动化是多么的困难。Zabbix API为批量操作、第三方软件集成以及其他作用提供可编程接口。
Zabbix API是在1.8版本中开始引进并且已经被广泛应用。所有的Zabbix移动客户端都是基于API,甚至原生的WEB前端部分也是建立在它之上。Zabbix API 中间件使得架构更加模块化也避免直接对数据库进行操作。它允许你通过JSON
RPC协议来创建、更新和获取Zabbix对象并且做任何你喜欢的操作【当然前提是你拥有认证账户】。
Zabbix API提供两项主要功能:
-
-
远程管理Zabbix配置
-
远程检索配置和历史数据
-
调用zabbix接口基本流程
在zabbix调用zabbix接口的时候,需要带一个auth参数,这个auth参数需要先经过一次登录认证之后返回给客户端,然后客户端在请求的接口数据中需要带上这个auth字符串。具体的流程如下图:
以zabbix Action 开始的API调用旅程
zabbix Action简介
上述简单的介绍一下zabbix API的用途,具体zabbix的架构或者深奥的底层代码在网上已经有很多介绍,但是针对“python调用zabbix接口实现对Action配置的批量操作”的介绍确非常少,而这又是我们在给大批量机器定制策略的时候要迈出的第一步,所以今天我们的重点放在用python实现zabbix接口调用上(代码,代码,代码)。一开始还觉得这篇博客写的内容有些狭隘了,但是谁能说一个姑娘讲述她那条泡泡纱裙子不是一种故事呢?所以最终一拍脑袋就决定这篇了~
zabbix的接口功能非常强大、丰富,我在开篇已经说过现有网上资料的局限性,既然是以zabbix action的创建为题,还是要简单说一下zabbix的action(也就是zabbix报警)支持如下事件:
- Trigger 触发器事件 - 触发器状态在OK和PROBLEM之间变化
- Discovery 发现事件
- Auto Registration 自动注册事件 - 新的客户端注册进来
- Interval 内部事件 - item转变为unsupported状态,触发器转变为unknown状态
调用接口数据格式说明
在官网中已经有创建trigger和discovery action的例子,(zabbix3.0官网API地址:https://www.zabbix.com/documentation/3.0/manual/api/reference),我们今天主要谈谈建立Auto Registration所需要的接口数据,这在官网中并没有明确的列出,需要自己再加工一下,精简后的json数据如下:
{ "jsonrpc": "2.0", "method": "action.create", "params": { "name": name, "eventsource": 2,
"filter": {
"conditions": [ { "conditiontype": 24, "operator":2, "value": condition }, ] }, "operations": [ { "operationtype": 4, "opgroup": [ { "groupid": groupid } ], }, { "operationtype": 6, "optemplate": [ { "templateid":10110 } ], } ] }, "auth": auth, "id": 1 }
下面一行一行来看:
-
"jsonrpc": "2.0"-这是标准的JSON RPC参数以标示协议版本,所有的请求都会保持不变。
-
"method": "action.create",这个参数定义了真实执行的操作(我们这里要进行的就是action的创建)。
-
"params": 这里通过传递JSON对象来作为特定方法的参数。
- name 对应的就是action的name;
- eventsource 条件类型,从官网上看来这是一个必要的条件;
- filter 对应的是conditions中的条件,由于可以有多个条件,所以conditions是一个列表,每一个条件是一个字典;
- operations 对应的就是Action operations也就是告警之后对应的操作,这里的operations也可以定义多条,所以是一个列表,每一个操作对应一个字典。
-
"id":1-这个字段用于绑定JSON请求和响应。响应会跟请求有相同的"id",在一次性发送多个请求时很有用,这些也不需要唯一或者连续。
- "auth": "159121b60d19a9b4b55d49e30cf12b81"-这是一个认证令牌【authentication token】用以鉴别用户、访问API。这也是使用API进行相关操作的前提-获取认证ID。
API 使用
明白了参数,去调用API的就非常简单了,所有不上代码的技术贴都是耍流氓~所以就直接上代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
# - * -coding:utf-8 - * - __author__ = 'Eva_J' import json import urllib2 def login(): data = { "jsonrpc": "2.0", "method": "user.login", "params": { "user": "Eva_J", "password": "~RdzvwqTSf" }, "id": 0 } response = request(data) return response['result'] def request(data): url = "http://monitor.dt.zw.ted/api_jsonrpc.php" header = {"Content-Type": "application/json"} data = json.dumps(data) request = urllib2.Request(url,data) for key in header: request.add_header(key,header[key]) response = {} try: result = urllib2.urlopen(request) except Exception as e: print e else: response = json.loads(result.read()) result.close() return response def getgroupId(auth,groupName): data = { "jsonrpc": "2.0", "method": "hostgroup.get", "params": { "output": "extend", "filter": { "name":groupName } }, "auth": auth, "id": 0 } return request(data) def create(auth): condition = u'codition name' name = u"lottery-zookeeper" groupid = 1 data = { "jsonrpc": "2.0", "method": "action.create", "params": { "name": name, "eventsource": 2, "filter": { "evaltype": 0, "conditions": [ { "conditiontype": 24, "operator":2, "value": condition }, ] }, "operations": [ { "operationtype": 4, "opgroup": [ { "groupid": groupid } ], }, { "operationtype": 6, "optemplate": [ { "templateid":10110 } ], } ] }, "auth": auth, "id": 1 } response = request(data) return response def getGroupDic(): fileObj = open('group.txt','r') groupsDic = {} for line in fileObj: lineLst = line.decode('GB2312').split('\t') groupsDic[lineLst[1].strip('\n')] = lineLst[0] return groupsDic if __name__ == '__main__': auth = login() response = create(auth) print response