zabbix提供了丰富的API接口来供使用者调用,我们通过对zabbix的url接口发送post数据请求来获取zabbix信息.zabbix的API接口地址为
http://IP/zabbix/api_jsonrpc.php
在脚本中我们使用了requests模块来发送post请求并获取返回的信息。
使用json模块来格式化数据,time模块生成当前时间秒数和打印日志时间。
pickle模块来本地持久化服务器的状态信息,记录服务器信息可以让我们判断在什么时候触发自动扩容脚本。
os模块来判断文件是否存在,文件大小。
zabbix官方API接口文档
https://www.zabbix.com/documentation/3.2/manual/api/reference/trigger/get
脚本思路:
首先我们获取zabbixAPI接口,并可以通过接口获取token进行登陆,登陆后通过发送post请求来返回我们需要的服务器监控项和触发器的信息,我们把触发器状态为已触发的服务器筛选出来,然后将这些服务器的名称、触发时间、当前状态记录下来。通过记录这些信息我们可以判定在什么情景下调用阿里云自动扩容脚本。
触发情景:
- 触发器首次触发,等待30s,若30s后触发器依然为触发状态则调用扩容脚本。
- 触发器在30s后调用扩容脚本后会继续监控服务器,若10小时后触发器状态依然异常则第二次调用扩容脚本。
- 脚本第二扩容后触发器状态会强制转换为正常,在下次监控扫描时若仍未异常则按照首次触发处理。
import requests, json, time, pickle, os
def getcurrenttime(arg):
if arg == 's':
t = time.time()
elif arg == 'd':
t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
else:
print(arg+'时间获取出错')
return t
headers = {'Content-Type': 'application/json-rpc'}
url = 'http://zabbix.puhuijia.com/zabbix/api_jsonrpc.php'
#url = 'http://10.2.2.19/pxzabbix/api_jsonrpc.php' '''测试环境地址'''
'''获取验证zabbix身份信息的token,返回token值'''
def getToken(username='zhaoliang', passwd='zhaoliang123'):
'''获取登陆zabbixapi的token信息,返回token的值'''
data = {
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": username,
"password": passwd
},
"id": 1
}
request = requests.post(url=url, headers=headers,data=json.dumps(data))
dict = json.loads(request.text)
return dict['result']
'''获取某个服务器的某个触发器的状态信息,返回0或者1,0表示状态正常,1表示状态异常'''
def getstatus(token,hostid,triggerid):
'''获取服务器监控项item的状态,即是否被触发,被触发返回1,没被触发返回0'''
data = {
"jsonrpc": "2.0",
"method": "trigger.get",
"params": {
"triggerids": triggerid,
"hostids": hostid,
"output": "extend",
"selectFunctions": "extend"
},
"id": 1,
"auth": token,
}
request = requests.post(url=url, headers=headers, data=json.dumps(data))
dict = json.loads(request.text)
return dict['result'][0]['value']
'''要监控的zabbix服务器信息'''
def monitoredhost(token=getToken()):
'''通过myhost和triggername两个列表来生成一个字典,它包含了我们所有需要监控的服务器的监控项,返回所有服务器信息字典'''
myhost = ['dubbo1','dubbo2','dubbo3','dubbo4','dubbo5','dubbo6','dubbo7','dubbo8','dubbo9','dubbo10','web-mobile1','web-mobile2','web_back1','web_back2']
triggername = ["{HOST.NAME}服务器可用内存不足","{HOST.NAME}处理器负载过高","本机tomcat已3分钟不可用"]
data = {
"jsonrpc": "2.0",
"method": "host.get",
"params": {
"output": ["host","hostid"],
},
"id": 1,
"auth": token
}
request = requests.post(url=url, headers=headers, data=json.dumps(data))
hosts = json.loads(request.text)
items = {}
for i in hosts['result']:
hostid = i['hostid']
hostname = i['host']
if hostname in myhost:
items[hostname] = {"id":hostid, "triggers":{}}
data = {
"jsonrpc": "2.0",
"method": "trigger.get",
"params": {
'hostids': hostid
},
"id": 1,
"auth": token
}
request = requests.post(url=url, headers=headers, data=json.dumps(data))
dict = json.loads(request.text)
for m in dict['result']:
if m["description"] == triggername[0]:
items[hostname]["triggers"]["mem"] = m["triggerid"]
elif m["description"] == triggername[1]:
items[hostname]["triggers"]["cpu"] = m["triggerid"]
elif m["description"] == triggername[2]:
items[hostname]["triggers"]["heap"] = m["triggerid"]
else:
continue
return items
def findall():
'''返回异常服务器信息的字典,若无异常则返回0'''
excep = {}
error = 0
items = monitoredhost()
for host in items:
excep[host] = {}
for trigger in items[host]['triggers']:
hostid = items[host]['id']
triggerid = items[host]['triggers'][trigger]
status = getstatus(token=getToken(),hostid=hostid,triggerid=triggerid)
if status == str(0):
'''状态正常error=0'''
print('{time} INFO:主机---> {0} 的触发器 {1} 状态为 {2} 正常'.format(host, trigger, status,time=getcurrenttime('d')))
elif status == str(1):
'''状态异常error=1,随后返回异常服务器信息的字典'''
error = 1
print('{time} INFO:主机---> {0} 的触发器 {1} 状态为 {2} 发生异常'.format(host, trigger, status,time=getcurrenttime('d')))
excep[host][trigger] = triggerid
else:
return 1
if error == 1:
return excep
else:
return 0
def createcheck(hostname,hoststatus=1):
'''检查服务器当前状态是否需要创建新的服务器,返回0表示需要进行服务器创建,返回1表示无需创建服务器'''
status = 1
if os.path.isfile('hoststatus.pkl'):
'''文件已存在'''
pass
else:
'''新建pkl文件'''
f = open('hoststatus.pkl', 'w')
f.close()
if os.path.getsize('hoststatus.pkl') != 0:
with open('hoststatus.pkl', 'rb') as fr:
s = pickle.load(fr)
s1 = s.copy()
with open('hoststatus.pkl', 'wb') as f:
if hostname in s1:
s1[hostname]['time2'] = getcurrenttime('s')
timecha = s1[hostname]['time2'] - s1[hostname]['time1']
if timecha >= 30 and s1[hostname]['hoststatus'] == 1:
s1[hostname]['hoststatus'] = 0
print('{time} 首次触发创建服务器 {0}'.format(hostname, time=getcurrenttime('d')))
status = 0
elif timecha >=36000 and s1[hostname]['hoststatus'] == 0:
s1[hostname]['hoststatus'] = 1
s1[hostname]['time1'] = getcurrenttime('s')
print('{time} 异常已持续6小时,再次触发创建服务器 {0}'.format(hostname, time=getcurrenttime('d')))
status = 0
elif timecha < 30 and s1[hostname]['hoststatus'] == 1:
print('{time} 主机 {0} 正在等待30s'.format(hostname, time=getcurrenttime('d')))
status = 1
elif timecha < 30 and s1[hostname]['hoststatus'] == 0:
print('{time} 主机 {0} 出现异常ERROR'.format(hostname, time=getcurrenttime('d')))
status = 1
elif 36000 > timecha >= 30 and s1[hostname]['hoststatus'] == 0:
print('{time} 主机 {0} 状态异常且在监控中, 持续时间为 {1} 分钟, {2} 分钟后若持续保持异常状态则会新建服务器.'.format(hostname,int(timecha/60),int(600-timecha/60),time=getcurrenttime('d')))
status = 1
else:
print('{time} 主机 {0} 首次出现异常,已添加到文件中.'.format(hostname, time=getcurrenttime('d')))
s1[hostname] = {}
s1[hostname]['time1'] = getcurrenttime('s')
s1[hostname]['hoststatus'] = 1
print('{time} 服务器状态异常等待,若持续30s则创建服务器,等待30s......'.format(time=getcurrenttime('d')))
status = 1
pickle.dump(s1, f)
return status
else:
print('pkl文件大小:{0} 为空,初始化pkl文件'.format(os.path.getsize('hoststatus.pkl')))
time = getcurrenttime('s')
info = {}
info[hostname] = {}
info[hostname]['time1'] = time
info[hostname]['hoststatus'] = 0
with open('hoststatus.pkl', 'wb') as f1:
pickle.dump(info, f1)
print('{time} 服务器状态异常等待,若持续30s则创建服务器,等待30s......'.format(time=getcurrenttime('d')))
return 1
def dubboapi():
'''调用阿里云自动扩容dubbo服务器的url'''
requests.get('http://localhost:7777/create_ecs_instance?instance_type=1')
print('{time} 创建新的dubbo服务器完毕!'.format(time=getcurrenttime('d')))
def webmobileapi():
'''调用阿里云自动扩容web服务器的url'''
requests.get('http://localhost:7777/create_ecs_instance?instance_type=2')
print('{time} 创建新的web服务器完毕!'.format(time=getcurrenttime('d')))
def createserver():
'''主体函数,用来将所有函数串联起来'''
result = findall()
if result == 0:
print('{time} 本次状态检查没有发现有异常.'.format(time=getcurrenttime('d')))
elif result == 1:
print('{time} 本次状态检查没有发现有异常,返回值为1.'.format(time=getcurrenttime('d')))
else:
for i in result:
if 'dubbo' in i:
if createcheck(i, hoststatus=1) == 0:
for j in result[i]:
print('{time} {i} 服务器 {j} 参数值超过阈值,准备新建服务器.'.format(time=getcurrenttime('d'), j=j, i=i))
dubboapi()
else:
continue
elif 'mobile' in i:
if createcheck(i, hoststatus=1) == 0:
for j in result[i]:
print('{time} {i} 服务器 {j} 参数值超过阈值,准备新建服务器.'.format(time=getcurrenttime('d'), j=j, i=i))
webmobileapi()
else:
continue
elif 'web_back' in i:
pass
createserver()