zabbix如何批量更新错误图表

背景

最近业务同事发现一个比较扯淡的事情,在查看交换机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: 0
show_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: 0
1 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 python
import MySQLdb
import time
import os
import logging
from 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])

没啥可说的,就这样~

Leave a Reply

Your email address will not be published. Required fields are marked *


To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax