Monitoreo de habitaciones Zadarma Zabbix

Ofrezco una plantilla preparada para Zabbix y un script de Python para detectar automáticamente nuevos números de proveedores de Zadarma (nuevos, en el sentido de los números que compró).

La plantilla tiene varios disparadores e información básica sobre las habitaciones. El script funciona con la API de Zadarma o la base de datos MySQL.

Para trabajar con MySQL, es necesario poner los datos allí con anticipación en la corona o directamente desde el plan de marcado usando un script separado.

Ambos guiones debajo del corte.

zadarma_number.py
El script debe colocarse en el directorio con scripts para el agente zabbiz, lo tengo

/etc/zabbix/scripts/ 

Además, dele el derecho de ejecutar y, por si acaso, cambie el propietario y el grupo de zabbix:

 chmod +x /etc/zabbix/scripts/zadarma_number.py chown zabbix:zabbix /etc/zabbix/scripts/zadarma_number.py 

 #! /usr/bin/env python3 import json import pymysql import argparse import sys import base64 import hmac import requests from hashlib import sha1, md5 from collections import OrderedDict from urllib.parse import urlencode api_key = '222c2fd22c2d2222a2b2' secret_key = '2a2f2222cee2222f2222' database_address = '192.168.10.18' database_name = 'asterisk' database_user = 'asterisk' database_password = 'dFgXuasfvgas45hAkEb2' zadarma_api_url = 'http://api.zadarma.com' monthly_fee_all = 0 def sql_result(sql): cursor.execute(sql) data = cursor.fetchall() return data def str_for_json(data): json_data = [] for result in data: json_data.append(dict(zip(['{#NUMBER}'], result))) json_data = ({"data":json_data}) return json.dumps(json_data) # return json.dumps(json_data) def createParser(): parser = argparse.ArgumentParser( prog='Zadarma for Zabbix', description='''       Zadarma       zabbiz .''', epilog='''(c)  2018.  ,  ,       .''' ) parser.add_argument('-l', '--allnumbers', action='store_true', help='"Show all found phone numbers in a format suitable for zabbix. ' ' Running a script without parameters (or with the -f option) leads to the same result."') parser.add_argument('-n', '--number', help = '"Phone number and -s or -S or -g or -e or -d or -m or -a "', metavar = 'phone number') parser.add_argument('-S', '--status', action='store_true') parser.add_argument('-g', '--start_date', action='store_true') parser.add_argument('-e', '--stop_date', action='store_true') parser.add_argument('-d', '--description', action='store_true') parser.add_argument('-s', '--sip', action='store_true', help='"can be used in combination with "-c""') parser.add_argument('-m', '--monthly_fee', action='store_true', help='"The amount required to renew a phone number or all phone numbers"') parser.add_argument('-a', '--autorenew', action='store_true') parser.add_argument('-b', '--balance', action='store_true', help='All balance numbers') parser.add_argument('-f', '--force_API', action='store_true',default=False, help = '"Force the use of api, the database is ignored"') parser.add_argument('-c', '--cut', type=int, default=0, help='''Used only in conjunction with "-s" 0 - The whole line, 1- Part of the string before "@", 2 - Part of the line after "@"''', metavar='[0,1,2] or none') return parser def api_zapros(method,data): if not data: data = {'format': 'json'} sorted_dict_params = OrderedDict(sorted(data.items())) query_string = urlencode(sorted_dict_params) h = md5(query_string.encode('utf8')).hexdigest() data = method + query_string + h hashed = hmac.new(secret_key.encode('utf8'), data.encode('utf8'), sha1) auth = api_key + ':' + base64.b64encode(bytes(hashed.hexdigest(), 'utf8')).decode() headers = {'User-Agent': '-', 'Authorization': auth} url = zadarma_api_url + method + '?' + query_string; r = requests.get(url, headers=headers) r.raise_for_status() return json.loads(r.text) def no_sql(*args): number = args[0] parametr = args[1] for number_string in numbers_result['info']: if number_string['number'] == number: if number_string[parametr] == 'true' or number_string[parametr] == 'on': return '0' elif number_string[parametr] == 'false' or number_string[parametr] == 'off': return '1' else: return number_string[parametr] def zapros(*args): if namespace.force_API: return no_sql(namespace.number,args[0]) else: return sql_result(sql)[0][0] parser = createParser() namespace = parser.parse_args(sys.argv[1:]) if not namespace.force_API: try: db = pymysql.connect(database_address, database_user, database_password, database_name) cursor = db.cursor() except pymysql.Error as e: print('\n\t!!!!!!!!!!!SQL no connect!!!!!!!!!!!\n') print(e) exit(1) else: try: numbers_result = api_zapros('/v1/direct_numbers/', '') balance_info = api_zapros('/v1/info/balance/', '') except Exception as e: print('Error connect API zadarma') exit(1) # print('namespace', namespace) if namespace.number and namespace.status: sql = "SELECT status FROM zadarma_numbers WHERE number = %s;" % (namespace.number) print(zapros('status')) elif namespace.number and namespace.start_date: sql = "SELECT start_date FROM zadarma_numbers WHERE number = %s;" % (namespace.number) print(zapros('start_date')) elif namespace.number and namespace.stop_date: sql = "SELECT stop_date FROM zadarma_numbers WHERE number = %s;" % (namespace.number) print(zapros('stop_date')) elif namespace.number and namespace.autorenew: sql = "SELECT autorenew FROM zadarma_numbers WHERE number = %s;" % (namespace.number) print(zapros('autorenew')) elif namespace.number and namespace.description: sql = "SELECT description FROM zadarma_numbers WHERE number = %s;" % (namespace.number) print(zapros('description')) elif namespace.number and namespace.sip: sql = "SELECT sip FROM zadarma_numbers WHERE number = %s;" % (namespace.number) if namespace.cut == 0: print(zapros('sip')) if namespace.cut == 1: try: print(zapros('sip').split('@')[0]) except IndexError: print(zapros('sip')) if namespace.cut == 2: try: print(zapros('sip').split('@')[1]) except IndexError: print(zapros('sip')) elif namespace.number and namespace.monthly_fee: sql = "SELECT monthly_fee FROM zadarma_numbers WHERE number = %s;" % (namespace.number) print(zapros('monthly_fee')) else: if namespace.number: # sql = "SELECT * FROM zadarma_numbers WHERE number = %s;" % (namespace.number) # print(zapros(namespace.number)) print(namespace.number, 'there are not enough arguments or incorrect combination of arguments') sys.exit(1) elif namespace.balance: if namespace.force_API: balance = balance_info['balance'] print(balance) else: print(sql_result('SELECT balance FROM zadarma_balance;')[0][0]) elif namespace.monthly_fee: if namespace.force_API: for result in numbers_result['info']: monthly_fee_all = monthly_fee_all + result['monthly_fee'] print(monthly_fee_all) else: print(sql_result('SELECT monthly_fee FROM zadarma_balance;')[0][0]) elif namespace.allnumbers: if namespace.force_API: json_data = [] for result in numbers_result['info']: print(result['number']) json_data.append(dict(zip(['{#NUMBER}'], [result['number']]))) json_data = ({"data": json_data}) print('jkgkgliuui',json.dumps(json_data)) else: data = sql_result('SELECT number FROM zadarma_numbers WHERE stop_date > date') print(str_for_json(data)) else: if namespace.force_API: json_data = [] for result in numbers_result['info']: json_data.append(dict(zip(['{#NUMBER}'], [result['number']]))) json_data = ({"data": json_data}) print(json.dumps(json_data)) else: data = sql_result('SELECT number FROM zadarma_numbers WHERE stop_date > date') print(str_for_json(data)) if not namespace.force_API: db.close() 


Teóricamente, trabajar con una base de datos dada puede resultar más relevante, ya que se puede ejecutar un script para agregar información después de cada llamada. Por lo tanto, la información en la base de datos puede resultar un poco más relevante que el trabajo directo con la API directamente desde Zabbix.

En la plantilla de Zabbix, la macro {$ FORCE_API} obliga al script a trabajar con la API de Zadarma.
La macro {$ CUT} se usa para dividir la cadena de solicitud SIP-URI en partes antes de "@" y después.

El script tiene varias teclas para ejecutar.

Sin las teclas o con el modificador -l, el script devolverá una lista de números en formato json, que es adecuada para la detección automática de números en zabbix.

Ayuda para las teclas de script:
uso: Zadarma para Zabbix [-h] [-l] [-n número de teléfono] [-S] [-g] [-e] [-d] [-s]
[-m] [-a] [-b] [-f] [-c [0,1,2] o ninguno]

Este programa está diseñado para monitorear los números de proveedores de Zadarma y
originalmente concebido como un guión para el agente zabbiz.

 optional arguments: -h, --help show this help message and exit -l, --allnumbers "Show all found phone numbers in a format suitable for zabbix. Running a script without parameters (or with the -f option) leads to the same result." -n phone number, --number phone number "Phone number and -s or -S or -g or -e or -d or -m or -a " -S, --status -g, --start_date -e, --stop_date -d, --description -s, --sip "can be used in combination with "-c"" -m, --monthly_fee "The amount required to renew a phone number or all phone numbers" -a, --autorenew -b, --balance All balance numbers -f, --force_API "Force the use of api, the database is ignored" -c [0,1,2] or none, --cut [0,1,2] or none Used only in conjunction with "-s" 0 - The whole line, 1- Part of the string before "@", 2 - Part of the line after "@" 


Las teclas "-S, -s, -g, -e, -d, -a" se usan solo en combinación con un número
El modificador -m se puede usar con o sin un número
Clave -b, solo sin número
El modificador -c solo con el modificador -s
El modificador -f fuerza el uso de la API; sin ella, se envía una solicitud a la base de datos y se puede utilizar con cualquier modificador.

Segundo guion:

Script API_to_MySql
Así que dale el derecho de correr:

 chmod +x ./main.py 

Cómo llamar al guión y dónde ponerlo, decídalo usted mismo.

 #! /usr/bin/env python3 from hashlib import sha1, md5 from collections import OrderedDict from urllib.parse import urlencode import hmac import requests import base64 import json import pymysql api_key = '222c2fd22c2d2222a2b2' secret_key = '2a2f2222cee2222f2222' database_address = '192.168.10.18' database_name = 'asterisk' database_user = 'asterisk' database_password = 'dFgXuasfvgas45hAkEb2' zadarma_api_url = 'http://api.zadarma.com' monthly_fee_all = 0 debug = True # debug = False db = pymysql.connect(database_address, database_user, database_password, database_name) cursor = db.cursor() def sql_insert(): sql = "REPLACE zadarma_numbers (id, date, number, number_name, description, sip, start_date, stop_date, monthly_fee, status, channels, autorenew) \ VALUES (NULL, UTC_TIMESTAMP(), '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');" % \ (number,number_name, description, sip, start_date, stop_date, monthly_fee, status, channels, autorenew) try: # Execute the SQL command cursor.execute(sql) # Commit your changes in the database db.commit() except: # Rollback in case there is any error db.rollback() def zapros(method,data): if not data: data = {'format': 'json'} sorted_dict_params = OrderedDict(sorted(data.items())) query_string = urlencode(sorted_dict_params) h = md5(query_string.encode('utf8')).hexdigest() data = method + query_string + h hashed = hmac.new(secret_key.encode('utf8'), data.encode('utf8'), sha1) auth = api_key + ':' + base64.b64encode(bytes(hashed.hexdigest(), 'utf8')).decode() headers = {'User-Agent': '-', 'Authorization': auth} url = zadarma_api_url + method + '?' + query_string; r = requests.get(url, headers=headers) return json.loads(r.text) # print(r.text) numbers = zapros('/v1/direct_numbers/', '') if debug: print(numbers['info']) for res in numbers['info']: description = res['description'] number = res['number'] number_name = res['number_name'] start_date = res['start_date'] stop_date = res['stop_date'] sip = res['sip'] if res['autorenew'] == 'true': autorenew = 0 else: autorenew = 1 monthly_fee = res['monthly_fee'] if res['status'] == 'on': status = 0 else: status = 1 channels = res['channels'] monthly_fee_all = monthly_fee_all + monthly_fee if debug: print('number', number) print('description', description) print('sip',sip) print('number_name', number_name) print('start_date', start_date) print('stop_date', stop_date) print('monthly_fee',monthly_fee) print('status', status) # print('monthly_fee_all',monthly_fee_all) if autorenew != 0: if debug: print('!!!!!!!!!!!!!!!\nautorenew OFF\n!!!!!!!!!!!!!!!\n') if debug: print() sql_insert() balance_info = zapros('/v1/info/balance/','') balance = balance_info['balance'] if debug: print('balance', balance) print('monthly_fee_all',monthly_fee_all) sql = "REPLACE zadarma_balance (id, date, balance, monthly_fee) VALUES (NULL, UTC_TIMESTAMP(), '%s', '%s');" % (balance, monthly_fee_all) try: cursor.execute(sql) db.commit() except: db.rollback() if debug: print('doplata -->', balance - monthly_fee_all ) print('monthly_fee_all', monthly_fee_all) db.close() <spoiler title="  MySQL  "> 

Para deshabilitar la salida de información a la consola, descomente la línea
depuración = falso


Para que ambos scripts funcionen, lo más probable es que necesite instalar "solicitudes"

 pip install requests 

Tabla de números
 CREATE TABLE IF NOT EXISTS `zadarma_numbers` ( `id` int(10) NOT NULL, `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `number` varchar(12) DEFAULT NULL, `number_name` varchar(60) DEFAULT NULL, `description` varchar(60) NOT NULL DEFAULT '', `sip` varchar(80) DEFAULT NULL, `start_date` datetime NOT NULL, `stop_date` datetime NOT NULL, `monthly_fee` int(5) DEFAULT NULL, `status` int(1) DEFAULT NULL, `channels` int(3) DEFAULT NULL, `autorenew` int(1) DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=205 DEFAULT CHARSET=utf8; ALTER TABLE `zadarma_numbers` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `number` (`number`), ADD KEY `calldate` (`date`), ADD KEY `accountcode` (`monthly_fee`); ALTER TABLE `zadarma_numbers` MODIFY `id` int(10) NOT NULL AUTO_INCREMENT; 


Mesa para el equilibrio
 CREATE TABLE IF NOT EXISTS `zadarma_balance` ( `id` int(10) NOT NULL, `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `balance` int(10) DEFAULT NULL, `monthly_fee` int(10) DEFAULT NULL ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8; ALTER TABLE `zadarma_balance` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `balance` (`balance`), ADD KEY `calldate` (`date`); ALTER TABLE `zadarma_balance` MODIFY `id` int(10) NOT NULL AUTO_INCREMENT; 


Repositorio con plantilla mysql, scripts y volcados.

Source: https://habr.com/ru/post/es416231/


All Articles