您的位置:首页 > 编程语言 > Python开发

zabbix生成资源性能报表+邮件自动发送

2017-08-01 10:35 281 查看
使用python调去zabbix数据库groups,hosts_groups,hosts,items,trends,trends_uint表格中的数据组个而成的字典形式,并将其写入excel表格中。其实,核心思想就是用了下面这5个sql语句,获取的数据以字典,列表,元组的格式进行组合,最后形成的返回格式:
{u'10.1.12.33': {'vfs.fs.size[/,total]': '188.65', 'vm.memory.size[total]': '7.69', 'system.swap.size[,total]': '8.00', 'net.if.out[eth0]': '69.96', 'system.cpu.util[,idle]': '99.72', 'net.if.in[eth0]': '65.26', 'system.swap.size[,free]': '8.00', 'vfs.fs.size[/,free]': '177.47', 'vm.memory.size[used]': '1.30', 'system.cpu.load[percpu,avg5]': '0.08', 'vm.memory.size[available]': '6.90'}}
sql = "select groupid from groups where name='%s'" % groupname
sql = "select hostid from hosts_groups where groupid='%s'" % groupid
sql = "select host from hosts where status=0 and flags=0 and hostid = %s" % hostid
sql = "select itemid from items where hostid='%s' and key_='%s'" % (hostid, itemname)
sql = "select avg(value_%s)/%s result from %s where itemid=%s and clock<=%d and clock>=%d" % (value, ratio, table, itemid, startime, stoptime)
将关注超过阀值的ip的cpu、内存、磁盘单独放在一个sheet中,以邮件的形式定期发送到邮箱。目前只是实现了各种功能,但是代码还很是粗糙,有些重复冗余的函数,尤其是生成excel和阀值计算这块,后续会继续改进,同时也存在很多bug,一点点找吧

大体思路是抄袭别人的,但是后续在此基础上进行了修改,站在巨人的肩膀上。

zabbix用的是zabbix3.2,同事愿意用新的东西,没办法,就升级了咯,这段代码只提供大体思路,不能保证能在其他环境下运行,这次写的不太成功,移植性太差,看看就行了













代码部分
#! /usr/bin/env python
# _*_ coding: utf-8 _*_
# Author:wangpengtai
# date:2017/7/10
import sys
import time, datetime
import MySQLdb.cursors
import xlsxwriter
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
reload(sys)
sys.setdefaultencoding('utf-8')
zbx_host = '10.1.xxx.xxx'
zbx_port = 3306
zbx_username = 'zabbix'
zbx_password = 'xxxx'
zbx_dbname = 'zabbix'
#需要查询的服务器所在组名
groupname = 'xxx_xxx_Linux_Servers'
#文件产生日期
date = time.strftime("%Y%m%d", time.localtime())
#文件名称
fname = 'Zabbix_Report_weekly_%s.xls' % date
# groupname = 'Templates'
keys = [
[u'CPU平均空闲值', 'trends', 'system.cpu.util[,idle]', 'avg', '%.2f', 1, ''],
[u'CPU最小空闲值', 'trends', 'system.cpu.util[,idle]', 'min', '%.2f', 1, ''],
[u'CPU5分钟负载', 'trends', 'system.cpu.load[percpu,avg5]', 'avg', '%.2f', 1, ''],
[u'物理内存大小(单位G)', 'trends_uint', 'vm.memory.size[total]', 'avg', '', 1073741824, 'G'],
[u'物理内存可用(单位G)', 'trends_uint', 'vm.memory.size[available]', 'avg', '', 1073741824, 'G'],
[u'物理内存已使用(单位G)', 'trends_uint', 'vm.memory.size[used]', 'avg', '', 1073741824, 'G'],
[u'swap总大小(单位G)', 'trends_uint', 'system.swap.size[,total]', 'avg', '', 1073741824, 'G'],
[u'swap平均剩余(单位G)', 'trends_uint', 'system.swap.size[,free]', 'avg', '', 1073741824, 'G'],
[u'根分区总大小(单位G)', 'trends_uint', 'vfs.fs.size[/,total]', 'avg', '', 1073741824, 'G'],
[u'根分区剩余(单位G)', 'trends_uint', 'vfs.fs.size[/,free]', 'avg', '', 1073741824, 'G'],
[u'网卡进口流量(单位Kbps)', 'trends_uint', 'net.if.in[eth0]', 'avg', '', 1024, 'Kbps'],
[u'网卡进口流量(单位Kbps)', 'trends_uint', 'net.if.in[em1]', 'avg', '', 1024, 'Kbps'],
[u'网卡出口流量(单位Kbps)', 'trends_uint', 'net.if.out[eth0]', 'avg', '', 1024, 'Kbps'],
[u'网卡出口流量(单位Kbps)', 'trends_uint', 'net.if.out[em1]', 'avg', '', 1024, 'Kbps'],
]
Title = [
u'CPU5分钟负载',
u'CPU平均空闲值',
u'CPU最小空闲值',
u'swap平均剩余(单位G)',
u'swap总大小(单位G)',
u'根分区剩余(单位G)',
u'根分区总大小(单位G)',
u'物理内存可用(单位G)',
u'物理内存大小(单位G)',
u'物理内存已使用(单位G)',
u'网卡出口流量(单位Kbps)',
u'网卡进口流量(单位Kbps)',
u'硬盘剩余率(单位%)',
u'Swap剩余率(单位%)',
u'内存使用率(单位%)'
]
Title_dict = {
u'CPU5分钟负载': 1,
u'CPU平均空闲值': 2,
u'CPU最小空闲值': 3,
u'swap平均剩余(单位G)': 4,
u'swap总大小(单位G)': 5,
u'根分区剩余(单位G)': 6,
u'根分区总大小(单位G)': 7,
u'物理内存可用(单位G)': 8,
u'物理内存大小(单位G)': 9,
u'物理内存已使用(单位G)': 10,
u'网卡出口流量(单位Kbps)': 11,
u'网卡进口流量(单位Kbps)': 12,
u'硬盘剩余率(单位%)': 13,
u'Swap剩余率(单位%)': 14,
u'内存使用率(单位%)': 15
}
disk_full = Title[6]
disk_free = Title[5]
swap_full = Title[4]
swap_free = Title[3]
mem_full = Title[8]
mem_used = Title[9]
keys_disk = Title[12]
keys_swap = Title[13]
keys_mem = Title[14]
keys_cpu= Title[0]
class Report(object):
def __init__(self):
self.conn = MySQLdb.connect(host=zbx_host, port=zbx_port, user=zbx_username, passwd=zbx_password, db=zbx_dbname,
charset="utf8", cursorclass=MySQLdb.cursors.DictCursor)
self.cursor = self.conn.cursor()
def getgroupid(self):
sql = "select groupid from groups where name='%s'" % groupname
self.cursor.execute(sql)
groupid = self.cursor.fetchone()['groupid']
# print 'groupid is %s' % groupid
return groupid
def gethostid(self):
# sql = '''select hostid from hosts_groups where groupid=(select groupid from groups where name='%s') ''' %groupname
groupid = self.getgroupid()
# print groupid
sql = "select hostid from hosts_groups where groupid='%s'" % groupid
self.cursor.execute(sql)
hostid_list = self.cursor.fetchall()
# print 'hostid_list:',hostid_list
return hostid_list
# 元组格式:({'hostid': 10322L}, {'hostid': 10323L}, {'hostid': 10324L})
def gethostlist(self):
host_list = {}
hostid_list = self.gethostid()
# print hostid_list
for item in hostid_list:
# print item
hostid = item['hostid']
# print hostid
sql = "select host from hosts where status=0 and flags=0 and hostid = %s" % hostid
self.cursor.execute(sql)
host_ip = self.cursor.fetchone()
# print host_ip
# print host_ip['host']
#!!!判断如果主机被zabbix改成disable的状态时,hosts表格里面host变为空后,字典空键赋值报错《TypeError: 'NoneType' object has no attribute '__getitem__'》
if host_ip is None:
continue
host_list[host_ip['host']] = {'hostid': hostid}
# print host_list
return host_list
# 字典格式:{u'10.1.12.32': {'hostid': 10175L}, u'10.1.12.33': {'hostid': 10176L}}
def getitemid(self):
hostid_list = self.gethostlist()
# print hostid_list.items()
keys_dict = {}
for hostitem in hostid_list.items():
hostip = hostitem[0]
hostid = hostitem[1]['hostid']
# print hostitem
host_info = []
for item in keys:
keys_list = []
keys_list.append({'title': item[0]})
keys_list.append({'table': item[1]})
keys_list.append({'itemname': item[2]})
keys_list.append({'value': item[3]})
keys_list.append({'form': item[4]})
keys_list.append({'ratio': item[5]})
keys_list.append({'unit': item[6]})
itemname = item[2]
sql = "select itemid from items where hostid='%s' and key_='%s'" % (hostid, itemname)
self.cursor.execute(sql)
itemid = self.cursor.fetchone()
if itemid is None:
continue
keys_list.append(itemid)
# keys_dict['itemid'] = itemid['itemid']
# print hostip,keys_dict
host_info.append(tuple(keys_list))
# print host_info
keys_dict[hostip] = host_info
# print keys_dict
return keys_dict
def getvalue(self):
# 时间区间为7天内
stoptime = time.time() - 7*3600
startime = time.time()
host_info_list = self.getitemid()
# print host_info_list
host_dict = {}
for ip in host_info_list:
host_info = host_info_list[ip]
length = len(host_info)
host_item = {}
for i in range(length):
value = host_info[i][3]['value']
ratio = host_info[i][5]['ratio']
table = host_info[i][1]['table']
itemid = host_info[i][7]['itemid']
# itemname = host_info[i][2]['itemname']
unit = host_info[i][6]['unit']
title = host_info[i][0]['title']
sql = "select avg(value_%s)/%s result from %s where itemid=%s and clock<=%d and clock>=%d" % (
value, ratio, table, itemid, startime, stoptime)
self.cursor.execute(sql)
result = self.cursor.fetchone()['result']
if result is None:
continue
else:
host_item[title] = '%.2f%s' % (result, unit)
# 硬盘剩余率
if disk_full in host_item and disk_free in host_item:
# print "Disk_percent:%.2f%%" %(float(host_item[disk_free].strip("GKbps"))/float(host_item[disk_full].strip("GKbps"))*100)
host_item[keys_disk] = "%.2f" % (
float(host_item[disk_free].strip("GKbps")) / float(host_item[disk_full].strip("GKbps")) * 100)
# Swap剩余率
if swap_full in host_item and swap_free in host_item:
# print "Swap_percent:%.2f%%" %(float(host_item[swap_full].strip("GKbps"))/float(host_item[swap_full].strip("GKbps"))*100)
host_item[keys_swap] = "%.2f" % (
float(host_item[swap_full].strip("GKbps")) / float(host_item[swap_full].strip("GKbps")) * 100)
# 内存使用率
if mem_used in host_item and mem_full in host_item:
# print "Mem_percent:%.2f%%" %(float(host_item[mem_used].strip("GKbps")) / float(host_item[mem_full].strip("GKbps")) * 100)
host_item[keys_mem] = "%.2f" % (
float(host_item[mem_used].strip("GKbps")) / float(host_item[mem_full].strip("GKbps")) * 100)
host_dict[ip] = host_item
return host_dict
# 返回格式:{u'10.1.12.33': {'vfs.fs.size[/,total]': '188.65', 'vm.memory.size[total]': '7.69', 'system.swap.size[,total]': '8.00', 'net.if.out[eth0]': '69.96', 'system.cpu.util[,idle]': '99.72', 'net.if.in[eth0]': '65.26', 'system.swap.size[,free]': '8.00', 'vfs.fs.size[/,free]': '177.47', 'vm.memory.size[used]': '1.30', 'system.cpu.load[percpu,avg5]': '0.08', 'vm.memory.size[available]': '6.90'}}
def dispalyvalue(self):
value = self.getvalue()
for ip in value:
print "\n\rip:%s\n\r获取服务器信息:" % (ip)
for key in value[ip]:
print "%s:%s" %(key,value[ip][key])
def __del__(self):
#关闭数据库连接
self.cursor.close()
self.conn.close()
def createreport(self):
host_info = self.getvalue()
# 创建一个excel表格
workbook = xlsxwriter.Workbook(fname)
# 设置第一行标题格式
format_title = workbook.add_format()
format_title.set_border(1)  # 边框
format_title.set_bg_color('#1ac6c0')  # 背景颜色
format_title.set_align('center')  # 左右居中
format_title.set_bold()  # 字体加粗
format_title.set_valign('vcenter')  # 上下居中
format_title.set_font_size(12)
# 设置返回值的格式
format_value = workbook.add_format()
format_value.set_border(1)
format_value.set_align('center')
format_value.set_valign('vcenter')
format_value.set_font_size(12)
# 创建一个名为Report的工作表
worksheet1 = workbook.add_worksheet("总览表格")
# 设置列宽
worksheet1.set_column('A:D', 15)
worksheet1.set_column('E:J', 23)
worksheet1.set_column('K:P', 25)
# 设置行高
worksheet1.set_default_row(25)
# 冻结首行首列
worksheet1.freeze_panes(1, 1)
# 将标题写入第一行
i = 1
for title in Title:
worksheet1.write(0, i, title.decode('utf-8'), format_title)
i += 1
# 写入第一列、第一行
worksheet1.write(0, 0, "主机".decode('utf-8'), format_title)
# 根据每个ip写入相应的数值
j = 1
for ip in host_info:
keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
host_value = host_info[ip]  # 取出没有排序的键值
if len(host_value) != 0:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
worksheet1.write(j, 0, ip, format_value)
else:
continue
# k = 1
for item in keys_ip:
# worksheet1.write(j,k,host_value[item],format_value)
worksheet1.write(j, Title_dict[item], host_value[item], format_value)
# k += 1
j += 1
##########################性能报表#############################
worksheet2 = workbook.add_worksheet("性能报表")
# 设置列宽
worksheet2.set_column('A:E', 25)
# 设置行高
worksheet2.set_default_row(25)
# 冻结首行首列
worksheet2.freeze_panes(1, 1)
# 写入第一列、第一行
worksheet2.write(0, 0, "主机".decode('utf-8'), format_title)
worksheet2.write(0, 1, keys_cpu, format_title)
worksheet2.write(0, 2, keys_mem, format_title)
worksheet2.write(0, 3, keys_swap, format_title)
worksheet2.write(0, 4, keys_disk, format_title)
j = 1
for ip in host_info:
keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
host_value = host_info[ip]  # 取出没有排序的键值
#Title[12]=硬盘剩余率(单位%)
if len(host_value) != 0 and keys_disk in host_value and keys_swap in host_value and keys_mem in host_value and keys_cpu in host_value:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
worksheet2.write(j, 0, ip, format_value)
worksheet2.write(j, 1, host_value[keys_cpu], format_value)
worksheet2.write(j, 2, host_value[keys_mem], format_value)
worksheet2.write(j, 3, host_value[keys_swap], format_value)
worksheet2.write(j, 4, host_value[keys_disk], format_value)
#keys_mem in host_value: # or keys_swap in host_value
else:
continue
j += 1
###############制作内存大于90%的服务器表格########################
worksheet3 = workbook.add_worksheet("内存大于90%")
# 设置列宽
worksheet3.set_column('A:B', 25)
# 设置行高
worksheet3.set_default_row(25)
# 冻结首行首列
worksheet3.freeze_panes(1, 1)
# 写入第一列、第一行
worksheet3.write(0, 0, "主机".decode('utf-8'), format_title)
worksheet3.write(0, 1, keys_mem, format_title)
j = 1
for ip in host_info:
keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
host_value = host_info[ip]  # 取出没有排序的键值
if len(host_value) != 0 and keys_mem in host_value and float(host_value[keys_mem]) > 90.0:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
#print type(float(host_value[keys_mem]))
#if float(host_value[keys_mem]) < 20.0:
worksheet3.write(j, 0, ip, format_value)
worksheet3.write(j, 1, host_value[keys_mem], format_value)
else:
continue
j += 1
#######################制作硬盘空间小于20%的服务器表格#########################
# 制作硬盘空间小于20%的服务器表格
worksheet4 = workbook.add_worksheet("磁盘空间低于20%")
# 设置列宽
worksheet4.set_column('A:B', 25)
# 设置行高
worksheet4.set_default_row(25)
# 冻结首行首列
worksheet4.freeze_panes(1, 1)
# 写入第一列、第一行
worksheet4.write(0, 0, "主机".decode('utf-8'), format_title)
worksheet4.write(0, 1, keys_disk, format_title)
j = 1
for ip in host_info:
keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
host_value = host_info[ip]  # 取出没有排序的键值)
if len(host_value) != 0 and keys_disk in host_value and float(
host_value[keys_disk]) < 20.0:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
# print type(float(host_value[keys_disk]))
# if float(host_value[keys_disk]) < 20.0:
worksheet4.write(j, 0, ip, format_value)
worksheet4.write(j, 1, host_value[keys_disk], format_value)
else:
continue
j += 1

#######################制作CPU负载大于8的服务器表格#########################
# 制作CPU负载大于8的服务器表格
worksheet5 = workbook.add_worksheet("CPU负载大于8")
# 设置列宽
worksheet5.set_column('A:B', 25)
# 设置行高
worksheet5.set_default_row(25)
# 冻结首行首列
worksheet5.freeze_panes(1, 1)
# 写入第一列、第一行
worksheet5.write(0, 0, "主机".decode('utf-8'), format_title)
worksheet5.write(0, 1, keys_cpu, format_title)
j = 1
for ip in host_info:
keys_ip = sorted(host_info[ip])  # 取出每个ip的键值,并把键值进行排序
host_value = host_info[ip]  # 取出没有排序的键值
if len(host_value) != 0 and keys_cpu in host_value and float(
host_value[keys_cpu]) > 8:  # 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
# print type(float(host_value[keys_cpu]))
# if float(host_value[keys_cpu]) < 20.0:
worksheet5.write(j, 0, ip, format_value)
worksheet5.write(j, 1, host_value[keys_cpu], format_value)
else:
continue
j += 1
workbook.close()
def sendreport(self):
# 发件服务器地址
mail_host = 'smtp.163.com'
# 发件邮箱地址
sender_user = 'xxxx_monitor@163.com'
# mail_pass = 'xxxx'#登录密码
# 邮箱授权码,不是登录密码
sender_pass = 'xxxxx'
# 收件邮箱地址
receivers = ['wangpengtai@xxx.com', 'wangpeng@xxx.cn']
# 创建带附件实例
message = MIMEMultipart()
# 邮件内容
# message = MIMEText('Python 邮件测试发送','plain','utf-8')
# 发送邮箱地址
message['From'] = sender_user
# 群发邮件时会报错message['To']不支持列表,使用join函数把地址合成字符串
message['To'] = ",".join(receivers)
# 邮件主题
subject = '一周服务器资源使用情况报表'
message['Subject'] = subject.decode('utf-8')
# 邮件正文内容
message.attach(MIMEText('一周服务器资源使用情况报表', 'plain', 'utf-8'))
# 构造附件1,传送当前目录下
excel = MIMEApplication(open(fname, 'rb').read(), 'utf-8')
excel.add_header('Content-Disposition', 'attachment', filename=fname)
message.attach(excel)
try:
smtpobj = smtplib.SMTP()
# smtpobj.set_debuglevel(1)
smtpobj.connect(mail_host, 25)
smtpobj.login(sender_user, sender_pass)
smtpobj.sendmail(sender_user, receivers, message.as_string())
smtpobj.close()
print '邮件发送成功'
except:
print "邮件发送失败"
if __name__ == "__main__":
zabbix = Report()
zabbix.dispalyvalue()
zabbix.createreport()
zabbix.sendreport()
参考大神: http://www.roncoo.com/article/detail/126748
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  邮件 报表 python