背景
最近业务同事发现一个比较扯淡的事情,在查看交换机qos队列发包的时候,
发现所有的交换机qos队列发包的图表都是错的。
可见应当是qos4发包的曲线错加成了丢包的曲线了,得改呀。
于是蛋疼了,扫了遍数据库发现有800+个图表均是类似的错误。。。
如何去做
这么大的量,一个个手动去改正肯定是不现实的。只能写脚本去跑。能有api什么的
是最好的,翻了下1.8的文档,发现添加、删除的图表并不是特别的完善。
只能自己动手、丰衣足食了,从数据库表结构之间入手!
具体方法
大致思路是这个样子:
* 扫描所有的图表,找出那些是具有交换机端口发包图表的图表列表* 再次查询具体的某个图表是由那些item组成的,同时进行联表 查询对应的hostid等信息,一个item其实图表 上的一条线,看是否错误,即description带有丢包等字眼* 如果有的话,将description的丢包字样修改为发包字样,根据 hostid等做条件扫描item表,找出对应的item,这个即是正确的 的item* 利用查询的新的item的itemid进行更新操作;
难点graphs表
我们第一步的扫描就是扫描该张表,查找所有name 包含端口队列发包量的图表。
其实逻辑大致还算清楚,唯一的麻烦就是数据库这块的对应关系,例如
某个图表上现在绘出了三条曲线,graphs表只是记录了这个图表的名称、坐标等
信息,但没有记录具体构成这个图表的三条曲线的信息。
mysql> select * from graphs where graphid = 287242 \G*************************** 1. row *************************** graphid: 287242 name: xe-3/3/7端口队列发包量 width: 900 height: 200 yaxismin: 0.0000 yaxismax: 100.0000 templateid: 0show_work_period: 1 show_triggers: 1 graphtype: 0 show_legend: 0 show_3d: 0 percent_left: 0.0000 percent_right: 0.0000 ymin_type: 0 ymax_type: 0 ymin_itemid: 0 ymax_itemid: 01 row in set (0.01 sec)
graphs_items表
找了大半天才弄清楚这部分信息其实是保存在graphs_items表的。
mysql> select * from graphs_items where graphid = 287242;+---------+---------+---------+----------+-----------+--------+-----------+----------+------+-------------+| gitemid | graphid | itemid | drawtype | sortorder | color | yaxisside | calc_fnc | type | periods_cnt |+---------+---------+---------+----------+-----------+--------+-----------+----------+------+-------------+| 1087773 | 287242 | 2497388 | 2 | 0 | 000000 | 0 | 2 | 0 | 5 || 1087774 | 287242 | 2497387 | 2 | 1 | 770000 | 0 | 2 | 0 | 5 || 1087775 | 287242 | 2497386 | 2 | 2 | 0000DD | 0 | 2 | 0 | 5 || 1087776 | 287242 | 2497385 | 2 | 3 | DD0000 | 0 | 2 | 0 | 5 || 1087777 | 287242 | 2497384 | 2 | 4 | DDDD00 | 0 | 2 | 0 | 5 || 1087778 | 287242 | 2497383 | 2 | 5 | DD00DD | 0 | 2 | 0 | 5 || 1087779 | 287242 | 2497382 | 2 | 6 | 00DDDD | 0 | 2 | 0 | 5 || 1087780 | 287242 | 2497381 | 2 | 7 | 00DD00 | 0 | 2 | 0 | 5 |+---------+---------+---------+----------+-----------+--------+-----------+----------+------+-------------+8 rows in set (0.00 sec)
每一行记录对应的itemid都是图表上的一条曲线。 这一步使我们操作的核心,查询某个图表
的所有曲线对应的item,同时联表查询hosts表、items表,先检查当前的八个item是否有description
为丢包量的情况。如果有的话进行替换为发现,同时利用之前拿到的hostid进行查询对应的发包量的
item,取回itemdid留作一下步的更新使用。
更新当然就没什么好说的。
代码
思路清晰了,脚本就是水到渠成的事了。
#encoding:utf-8#!/usr/bin/env pythonimport MySQLdbimport timeimport osimport loggingfrom configure import *#日志配置logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', filename='graphs_update-' + time.strftime('%Y-%m',time.localtime(time.time())) +'.log', filemode='a+')try: conn=MySQLdb.connect(host=host_wr,user=user,passwd=passwd,port=port) cur=conn.cursor() conn.select_db('zabbix') cur.execute('set names utf8') #获取 端口队列发包量 的图表列表 graphs_sql = " select graphid , name from graphs where name like '%端口队列发包量' " graphs=cur.execute(graphs_sql) graphs=cur.fetchall() for graph in graphs: graphid = graph[0] #获取graphid 对应的itemid ,同时description如果为队列的丢包量则查找对应的发包量的itemid items_sql = " select i.hostid ,g.gitemid,i.itemid ,i.description from items as i left join graphs_items g on i.itemid = g.itemid where g.graphid= %s" % graphid items=cur.execute(items_sql) items=cur.fetchall() for item in items: hostid = item[0] gitemid = item[1] itemid = item[2] description = item[3] if description.find('丢包量') > -1: description_new = description.replace('丢包','发包') old_value ='graphid %s,hostid %r,gitemid %s, itemid %r, description %s' %(graphid,hostid,gitemid, itemid, description) logging.info("old value is : %s",old_value) new_itemid_sql = "select hostid ,itemid,description from items where hostid=%d and description='%s'" %(hostid, description_new) item_new=cur.execute(new_itemid_sql) item_new=cur.fetchone() #获取description为发包量的itemid itemid_new = item_new[1] #将原有的丢包量的itemid更新为发包量的itemid_new sql_update = "update graphs_items set itemid=%d where graphid = %d and gitemid=%d " %(itemid_new,graphid, gitemid) logging.info("update sql: %s",sql_update) result = cur.execute(sql_update) conn.commit() result = cur.fetchall() logging.info("update result: %s",result) cur.close() conn.close()except MySQLdb.Error,e: print "Mysql Error %d: %s" % (e.args[0], e.args[1])
没啥可说的,就这样~
原文地址:zabbix如何批量更新错误图表, 感谢原作者分享。 累死累活不说,走马观花反而少了真实体验,