Получение графиков из zabbix в telegram

    Всем привет. Предположим, мы настроили связку https://github.com/ableev/Zabbix-in-Telegram . Получаем в telegram события с графиками по событиям триггеров, классно. Можно чуть развить идею и самим заставить ботa telegram отправлять нам графики из заббикса.

Схема пусть будет следующая:

 

 

 

Распишем, что у нас уже изначально есть и настроено:

  • настроенный zabbix сервер, бд находится на этом же сервере
  • настроенный пользователь веб-интерфейса zabbix сервера, которому хватает прав на чтение
  • созданный пользователь БД, который имеет права только на чтение из mysql
  • созданный бот

 

Схема работы скрипта следующая:

    Мы добавили созданного бота к себе в телеграм. Отправляем ему управляющие команды  с целью найти нужный график,  делаем по полученным данным запросы в БД zabbix для получения graphid. Формируем url графика на основе graphid. Далее авторизуемся в веб-интерфейсе zabbix и "забираем" нужный график, потом его отправляем пользователю телеграма.

 Сам скрипт:

 

#!/usr/bin/env python
# coding: utf-8

import sys
import os
import time
import random
import requests
import json
import re
import stat
import MySQLdb

import telebot
bot = telebot.TeleBot("API_KEY_of_theBOT")


zbx_server = "https://zabbix.test.ru" 
zbx_api_user = "zabbix_read"
zbx_api_pass = "1234"


available_commands = { '/z ARG1 ARG2: ': " отправить команду заббиксу"}
available_arguments = { 'ARG1: ': "Имя сервера телефонии, которое указано в Zabbix)", 'ARG2: ': "Какую информацию получить с хоста"}
avalaible_data = ['calls', 'cpu', 'memory']
allowed_uid = ['12345678', '23541335', '987654321']


#Функция для получения url нужного графика
def get_zabbix_url(host,needed_data):
    global zbx_img_url
    db = MySQLdb.connect(host="localhost", user="read", passwd="read", db="zabbix", charset='utf8')
    cursor = db.cursor() # формируем курсор, с помощью которого можно исполнять SQL-запросыa

    sql = "select hostid,host from hosts where host = '" + str(host) + "'";
    cursor.execute(sql)
    data =  cursor.fetchall()
    if len(data) == 0: 
        print "Host " + str(host) + " not found in Zabbix database, exit..."
        zbx_img_url = ""
        return  zbx_img_url

    hostid= data[0][0]

    if needed_data ==  "calls":
        sql="select itemid,hostid,name from items where hostid=" + str(hostid) + " and name ='Calls count'";
        cursor.execute(sql)
        data =  cursor.fetchall()

    elif needed_data ==  "cpu":
        sql="select itemid,hostid,name from items where hostid=" + str(hostid) + " and name ='Processor load (15 min average per core)'";
        cursor.execute(sql)
        data =  cursor.fetchall()

    elif needed_data ==  "memory":
        sql="select itemid,hostid,name from items where hostid=" + str(hostid) + " and name ='Available memory'";
        cursor.execute(sql)
        data =  cursor.fetchall()

    else:
        print "Host " + str(host) + " found in Zabbix database, but itemid not found, may be ARG2 is wrong? "
        zbx_img_url = ""
        return  zbx_img_url
    itemid=data[0][0]

    sql="select * from graphs_items where itemid=" + str(itemid);
    cursor.execute(sql)
    data =  cursor.fetchall()
    graphid = data[0][1]

    zbx_img_url =  "https://zabbix.test.ru/chart2.php?fullscreen=0&graphid=" + str(graphid) + "&width=1138&period=43300"

    return zbx_img_url


@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):

    message_zabbix = ""

    msg = bot.send_message(message.chat.id, 'Привет! Я бот telephone company! Список доступных команд: ')
    for i in available_commands:
        message_zabbix = message_zabbix + i + "\t" + available_commands[i] + "\n\n"

    for i in available_arguments:
        message_zabbix = message_zabbix + i + "\t" + available_arguments[i] + "\n\n"

    message_zabbix = message_zabbix + "Список возможных значений аргумента ARG2:  " + str(avalaible_data) + "\n\n"

    bot.send_message(message.chat.id, message_zabbix )
    #message.from_user.id  - user id

#Получаем какой-то текст от пользователя
@bot.message_handler(content_types=["text"]) 
def get_info(message): 

    uid = message.from_user.id
    if str(uid) in  allowed_uid:

        text = message.text
        l = message.text.split()
        if len(l) != 3:
            bot.send_message(message.chat.id, "Wrong length of arguments" )
            exit(1)
        host = l[1]
        needed_data = l[2]

        data_api = {"name": zbx_api_user, "password": zbx_api_pass, "enter": "Sign in"}
        req_cookie = requests.post(zbx_server + "/", data=data_api)
        cookie = req_cookie.cookies

        #делаем запрос для получения графика
        file_img = "asterisk.png"
        get_zabbix_url(host,needed_data)

        if len(zbx_img_url) != 0:   #если хост найден в БД заббикса
            res = requests.get(zbx_img_url,cookies=cookie)
            res_code = res.status_code
        else:  # в бд не нашли, шлем сообщение
            bot.send_message(message.chat.id, "Host " + host + " not found in Zabbix database or maybe ARG2 is wrong?" )
            exit(1)

        res_img = res.content
        with open(file_img, 'wb') as fp:
            fp.write(res_img)

        photo = open('asterisk.png', 'rb') #for sending photo to telegram
        msg = bot.send_photo(message.chat.id, photo, reply_to_message_id=message.message_id)

    else: 
        bot.send_message(message.chat.id, "You don't allow access to this chat")

bot.polling()

 

    Скрипт "наколеночный". В даннном варианте он принимает при отправке команд боту имя хоста и параметры calls, memory, cpu. Имя хоста - это то, как хост называется в базе заббикса (select hostid,host from hosts),  параметр calls - соответствует элементу данных заббикса "Calls count" (select itemid,hostid,name from items where hostid=" + str(hostid) + " and name ='Calls count'"). Приведу несколько картинок, чтобы было немного яснее:

 

 

 Это элемент данных, на основе которого мы будем запрашивать графики.

 

 Приветственное сообщение.

 

Запросили данные, но нет прав (не прописан uid пользователя телеграма в списке allowed_uid скрипта). Свой uid можно узнать, отправив сообщение боту @MyTelegramID_bot.

 

 

 Прописали uid в список, перезапустили скрипт, получили в телеграм график.

 

 

 Для скрипта можно написать systemd service:

cat /etc/systemd/system/telegram_telebot.service

[Unit]
Description=Run script for receiving and sending messages from/to telegram  from zabbix
Requires=network.target   
After=network.target 
 
[Service]
#Type=oneshot
#RemainAfterExit=True
ExecStart=/root/scripts/telegram/telegram_telebot.py 
Restart=always
RestartSec=10m
 
[Install]
WantedBy=multi-user.targe

    Сервера nginx телеграма иногда выдают 500-е ошибки и чтобы наш скрипт не падал из-за них, указываем параметры Restart и RestartSec (назначил интервал 10 мин в виду того, что когда отдаются 500 ошибки, скрипт падает -> systemd сразу его пытается перезапускать, снова падает и т.д, в нашем варианте достаточно не сразу перезапускать, а выждав некоторое время, пока с бОльшей вероятностью все не починится)

systemctl enable telegram_telebot.service
systemctl start telegram_telebot.service

Please publish modules in offcanvas position.