Skip to content

Commit 3f9d644

Browse files
author
geekwolf
committed
add zabbix_report_email
1 parent 29c0c4d commit 3f9d644

File tree

6 files changed

+284
-0
lines changed

6 files changed

+284
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#### 安装依赖
2+
pip install -r requirements.txt
3+
#### 使用说明
4+
1. 邮件图文告警
5+
在Zabbix配置邮件发送告警脚本
6+
2. 报表
7+
在config.ini中graph配置info(要出报表的主机及对应的graphid)
8+
python report.py report
9+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[monitor]
2+
zbx_url = http://zbx.simlinux.com/
3+
graph_url = chart2.php
4+
item_graph_url = chart.php
5+
username = geekwolf
6+
password = geekwolf
7+
temp_dir = tmp
8+
log_file = zbx.log
9+
10+
[graph]
11+
#显示执行时前一天的数据,报表使用
12+
period = 86400
13+
width = 580
14+
height = 230
15+
info = [{"name":"HOST1","graphids":[1304,1306,1301,1302]},{"name":"HOST2","graphids":[1296,1298,1293,1294]},{"name":"HOST3","graphids":[1247,1263,1251,1267]}]
16+
17+
[ftp]
18+
host = 1.1.1.1
19+
port = 21
20+
username = ftpuser
21+
password = ftpuser
22+
23+
[email]
24+
smtpserver = email.simlinux.com
25+
username = geekwolf@simlinux.com
26+
password = test
27+
port = 25
28+
Binary file not shown.
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
# @Author: Geekwolf
4+
# @Date: 2018-05-07 13:26:12
5+
# @Last Modified by: Geekwolf
6+
# @Last Modified time: 2018-07-11 10:52:39
7+
8+
import ConfigParser
9+
import cookielib
10+
import urllib2
11+
import urllib
12+
import ast
13+
import datetime,time
14+
from docx import Document
15+
from docx.shared import Pt, RGBColor
16+
from docx.enum.text import WD_ALIGN_PARAGRAPH
17+
from docx.oxml.ns import qn
18+
from docx.enum.style import WD_STYLE_TYPE
19+
from docx.shared import Inches
20+
from io import BytesIO
21+
import collections
22+
from ftplib import FTP
23+
import os
24+
import mimetypes
25+
import sys
26+
import smtplib
27+
from email.header import Header
28+
from email.mime.text import MIMEText
29+
from email.mime.image import MIMEImage
30+
from email.mime.multipart import MIMEMultipart
31+
from email.utils import parseaddr, formataddr
32+
33+
config = ConfigParser.RawConfigParser()
34+
config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)),'./config.ini'))
35+
36+
class ZabbixGraph(object):
37+
38+
def __init__(self):
39+
40+
self.url = config.get('monitor', 'zbx_url')
41+
self.username = config.get('monitor', 'username')
42+
self.password = config.get('monitor', 'password')
43+
self.graph_url = self.url + config.get('monitor', 'graph_url')
44+
self.item_graph_url = self.url + config.get('monitor', 'item_graph_url')
45+
self.width = config.get('graph', 'width')
46+
self.height = config.get('graph', 'height')
47+
self.period = config.get('graph', 'period')
48+
self.temp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),config.get('monitor', 'temp_dir'))
49+
self.log_file = os.path.join(os.path.dirname(os.path.abspath(__file__)),config.get('monitor','log_file'))
50+
if not os.path.exists(self.temp_dir):
51+
os.makedirs(self.temp_dir)
52+
self.urlOpener = self.GetSession()
53+
54+
def GetSession(self):
55+
56+
cookiejar = cookielib.CookieJar()
57+
urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))
58+
values = {"name": self.username, 'password': self.password, 'autologin': 1, "enter": 'Sign in'}
59+
data = urllib.urlencode(values)
60+
request = urllib2.Request(self.url, data)
61+
try:
62+
urlOpener.open(request, timeout=10)
63+
self.urlOpener = urlOpener
64+
except urllib2.HTTPError, e:
65+
print e
66+
return urlOpener
67+
68+
def Log(self,rec):
69+
t = time.strftime('%Y-%m-%d %H:%M:%S')
70+
with open(self.log_file,'a') as f:
71+
f.write('{} {}'.format(str(t),str(rec)))
72+
73+
74+
def GetRequest(self,values,url,id):
75+
76+
_data = urllib.urlencode(values)
77+
request = urllib2.Request(url, _data)
78+
url = self.urlOpener.open(request)
79+
ext = mimetypes.guess_extension(url.headers['content-type'])
80+
imagename = '{}/{}{}'.format(self.temp_dir, str(id), ext)
81+
with open(imagename, 'wb') as f:
82+
f.write(url.read())
83+
return imagename
84+
85+
def GetItemGraph(self,id):
86+
87+
values = {'itemids': id, 'width': self.width, 'height': self.height, 'period': self.period}
88+
imagename = self.GetRequest(values,self.item_graph_url,id)
89+
return imagename
90+
91+
def GetGraph(self):
92+
93+
info = ast.literal_eval(config.get('graph', 'info'))
94+
data = collections.defaultdict(list)
95+
for i in info:
96+
values = {}
97+
for j in i['graphids']:
98+
values = {'graphid': j, 'width': self.width, 'height': self.height, 'period': self.period}
99+
imagename = self.GetRequest(values,self.graph_url,j)
100+
# image = BytesIO()
101+
# image.write(url.read())
102+
data[i['name']].append(imagename)
103+
# imagename = "%s/%s.png" % (self.temp_dir, str(j) + i['name'])
104+
# f = open(imagename, 'wb')
105+
# f.write(image)
106+
self.WriteDoc(data)
107+
108+
def GetStyles(self):
109+
110+
# doc = Document()
111+
# 在脚本打包成二进制时,需要指定default.docx路径,否则会报错
112+
doc = Document(docx=os.path.join(os.getcwd(), 'default.docx'))
113+
style_head = doc.styles.add_style('style_head', WD_STYLE_TYPE.PARAGRAPH)
114+
style_head.font.size = Pt(25)
115+
style_head.font.name = u'微软雅黑'
116+
style_head.font.bold = True
117+
style_head._element.rPr.rFonts.set(qn('w:eastAsia'), u'微软雅黑')
118+
style_head.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
119+
120+
style_title = doc.styles.add_style('style_title', WD_STYLE_TYPE.PARAGRAPH)
121+
style_title.font.size = Pt(15)
122+
style_title.font.name = u'微软雅黑'
123+
style_title.font.bold = True
124+
style_title._element.rPr.rFonts.set(qn('w:eastAsia'), u'微软雅黑')
125+
126+
sub_title = doc.styles.add_style('sub_title', WD_STYLE_TYPE.PARAGRAPH)
127+
sub_title.font.size = Pt(10)
128+
sub_title.font.name = u'微软雅黑'
129+
sub_title.font.bold = True
130+
sub_title._element.rPr.rFonts.set(qn('w:eastAsia'), u'微软雅黑')
131+
132+
return doc, style_head, style_title, sub_title
133+
134+
@staticmethod
135+
def GetYesterdayTime():
136+
137+
_time = datetime.date.today() - datetime.timedelta(days=1)
138+
return str(_time)
139+
140+
def WriteDoc(self, data):
141+
142+
doc, style_head, style_title, sub_title = self.GetStyles()
143+
_dict = {0: '一', 1: '二', 2: '三'}
144+
_time = ZabbixGraph.GetYesterdayTime()
145+
head = doc.add_paragraph(u'zbx监控报表', style='style_head')
146+
sub_head = doc.add_paragraph(_time)
147+
sub_head.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
148+
for d in enumerate(data):
149+
title = '{}、{}'.format(_dict[d[0]], d[1])
150+
doc.add_paragraph(title.decode('utf8'), style='style_title')
151+
for idx, val in enumerate(data[d[1]]):
152+
#sub_title = u'内存' if idx%2 == 1 else u'CPU'
153+
if idx >=2:
154+
sub_title = u'内存'
155+
else:
156+
sub_title = u'CPU'
157+
if idx%2 != 1:
158+
doc.add_paragraph(sub_title, style='sub_title')
159+
doc.add_picture(val, width=Inches(6.5), height=Inches(3))
160+
file = 'report-{}.docx'.format(('').join(_time.split('-')))
161+
doc.save(file)
162+
#如果将报表上传ftp,可以去掉注释
163+
#self.FtpUpload(file)
164+
165+
def DelTemp(self):
166+
167+
os.system('rm -rf report-* {}'.format(self.temp_dir))
168+
169+
def FtpUpload(self, file):
170+
171+
host = config.get('ftp', 'host')
172+
port = config.get('ftp', 'port')
173+
username = config.get('ftp', 'username')
174+
password = config.get('ftp', 'password')
175+
ftp = FTP(host=host)
176+
ftp.login(user=username, passwd=password)
177+
ftp.storbinary('STOR ' + file, open(file, 'rb'))
178+
ftp.quit()
179+
self.DelTemp()
180+
181+
class AlarmInfo(ZabbixGraph):
182+
183+
def format(content):
184+
185+
name, addr = parseaddr(content)
186+
return formataddr((Header(name, 'utf-8').encode(), addr))
187+
188+
def Email(self):
189+
190+
smtpserver = config.get('email', 'smtpserver')
191+
username = config.get('email','username')
192+
password = config.get('email','password')
193+
port = config.get('email','password')
194+
try:
195+
smtp = smtplib.SMTP()
196+
smtp.connect(smtpserver)
197+
smtp.login(username,password)
198+
return smtp
199+
except Exception as e:
200+
self.Log(str(e))
201+
202+
def SendEmail(self,_info):
203+
204+
itemid = _info[2].split('|')[0]
205+
imagename = self.GetItemGraph(itemid)
206+
fro = config.get('email','username')
207+
_content = (':').join(_info[3].split('|')[1:])
208+
content = '{}<br><img src="cid:image1"/>'.format(_content)
209+
msg = MIMEMultipart()
210+
#msg['From'] = '监控告警<{}>'.format(fro).decode('utf-8')
211+
msg['From'] = "%s<%s>" % (Header("监控告警","utf-8"),fro)
212+
msg['Subject'] = Header((': ').join(_info[2].split('|')[-2:]),'utf-8')
213+
msg['To'] = _info[1]
214+
msg.attach(MIMEText(content,'html','utf-8'))
215+
216+
with open(imagename,'rb') as f:
217+
img = MIMEImage(f.read())
218+
img.add_header('Content-ID', '<image1>')
219+
msg.attach(img)
220+
221+
try:
222+
email = self.Email()
223+
email.sendmail(fro,_info[1],msg.as_string())
224+
email.quit()
225+
except Exception as e:
226+
self.Log(str(e))
227+
228+
def main(self,_info):
229+
try:
230+
if len(_info) == 4:
231+
rec = '{}\t{}\n{}\n'.format(_info[1],_info[2],_info[3])
232+
self.Log(rec)
233+
self.SendEmail(_info)
234+
elif len(_info) == 2 and _info[1] == 'report':
235+
print 'tt'
236+
self.GetGraph()
237+
except Exception as e:
238+
self.Log(str(e))
239+
240+
241+
if __name__ == '__main__':
242+
243+
ins = AlarmInfo()
244+
ins.main(sys.argv)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ConfigParser
2+
python-docx
3+
email

0 commit comments

Comments
 (0)