4591566 发表于 2019-1-20 11:03:24

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

使用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': '7.69', 'system.swap.size[,total]': '8.00', 'net.if.out': '69.96', 'system.cpu.util[,idle]': '99.72', 'net.if.in': '65.26', 'system.swap.size[,free]': '8.00', 'vfs.fs.size[/,free]': '177.47', 'vm.memory.size': '1.30', 'system.cpu.load': '0.08', 'vm.memory.size': '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" % (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 = [
    ', 'avg', '%.2f', 1, ''],
    ', 'min', '%.2f', 1, ''],
    ', 'avg', '%.2f', 1, ''],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1073741824, 'G'],
    ', 'avg', '', 1024, 'Kbps'],
    ', 'avg', '', 1024, 'Kbps'],
    ', 'avg', '', 1024, 'Kbps'],
    ', '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
disk_free = Title
swap_full = Title
swap_free = Title
mem_full = Title
mem_used = Title
keys_disk = Title
keys_swap = Title
keys_mem = Title
keys_cpu= Title
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] = {'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
            hostid = hostitem['hostid']
            # print hostitem
            host_info = []
            for item in keys:
                keys_list = []
                keys_list.append({'title': item})
                keys_list.append({'table': item})
                keys_list.append({'itemname': item})
                keys_list.append({'value': item})
                keys_list.append({'form': item})
                keys_list.append({'ratio': item})
                keys_list.append({'unit': item})
                itemname = item
                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 = 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
            length = len(host_info)
            host_item = {}
            for i in range(length):
                value = host_info['value']
                ratio = host_info['ratio']
                table = host_info['table']
                itemid = host_info['itemid']
                # itemname = host_info['itemname']
                unit = host_info['unit']
                title = host_info['title']
                sql = "select avg(value_%s)/%s result from %s where itemid=%s 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 = '%.2f%s' % (result, unit)
            # 硬盘剩余率
            if disk_full in host_item and disk_free in host_item:
                # print "Disk_percent:%.2f%%" %(float(host_item.strip("GKbps"))/float(host_item.strip("GKbps"))*100)
                host_item = "%.2f" % (
                  float(host_item.strip("GKbps")) / float(host_item.strip("GKbps")) * 100)
            # Swap剩余率
            if swap_full in host_item and swap_free in host_item:
                # print "Swap_percent:%.2f%%" %(float(host_item.strip("GKbps"))/float(host_item.strip("GKbps"))*100)
                host_item = "%.2f" % (
                  float(host_item.strip("GKbps")) / float(host_item.strip("GKbps")) * 100)
            # 内存使用率
            if mem_used in host_item and mem_full in host_item:
                # print "Mem_percent:%.2f%%" %(float(host_item.strip("GKbps")) / float(host_item.strip("GKbps")) * 100)
                host_item = "%.2f" % (
                  float(host_item.strip("GKbps")) / float(host_item.strip("GKbps")) * 100)
            host_dict = host_item
      return host_dict
      # 返回格式:{u'10.1.12.33': {'vfs.fs.size[/,total]': '188.65', 'vm.memory.size': '7.69', 'system.swap.size[,total]': '8.00', 'net.if.out': '69.96', 'system.cpu.util[,idle]': '99.72', 'net.if.in': '65.26', 'system.swap.size[,free]': '8.00', 'vfs.fs.size[/,free]': '177.47', 'vm.memory.size': '1.30', 'system.cpu.load': '0.08', 'vm.memory.size': '6.90'}}
    def dispalyvalue(self):
      value = self.getvalue()
      for ip in value:
            print "\n\rip:%s\n\r获取服务器信息:" % (ip)
            for key in value:
                print "%s:%s" %(key,value)
    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的键值,并把键值进行排序
            host_value = host_info# 取出没有排序的键值
            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,format_value)
                worksheet1.write(j, Title_dict, host_value, 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的键值,并把键值进行排序
            host_value = host_info# 取出没有排序的键值
            #Title=硬盘剩余率(单位%)
            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, format_value)
                worksheet2.write(j, 2, host_value, format_value)
                worksheet2.write(j, 3, host_value, format_value)
                worksheet2.write(j, 4, host_value, 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的键值,并把键值进行排序
            host_value = host_info# 取出没有排序的键值
            if len(host_value) != 0 and keys_mem in host_value and float(host_value) > 90.0:# 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                #print type(float(host_value))
                #if float(host_value) < 20.0:
                worksheet3.write(j, 0, ip, format_value)
                worksheet3.write(j, 1, host_value, 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的键值,并把键值进行排序
            host_value = host_info# 取出没有排序的键值)
            if len(host_value) != 0 and keys_disk in host_value and float(
                  host_value) < 20.0:# 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                # print type(float(host_value))
                # if float(host_value) < 20.0:
                worksheet4.write(j, 0, ip, format_value)
                worksheet4.write(j, 1, host_value, 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的键值,并把键值进行排序
                host_value = host_info# 取出没有排序的键值
                if len(host_value) != 0 and keys_cpu in host_value and float(
                        host_value) > 8:# 如果出现{'10.1.12.1':{}}这种情况的时候,需要跳过,不将其写入表格中
                  # print type(float(host_value))
                  # if float(host_value) < 20.0:
                  worksheet5.write(j, 0, ip, format_value)
                  worksheet5.write(j, 1, host_value, 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



页: [1]
查看完整版本: zabbix生成资源性能报表+邮件自动发送