Мониторинг Linksys SPA8000 через Zabbix |
# Hostname шлюза. Его же надо как-то называть.
spa8000.name = SPA8000
# Серийный номер. Это больше для инвентаризации.
spa8000.serial = CFH01N704858
# Версия ПО.
spa8000.software = 6.1.12(XU)
# Версия платы, насколько я понимаю.
spa8000.hardware = 1.0.0
# MAC-адрес сетевого интерфейса. Без него никуда.
spa8000.mac = D0C789784BE4
# Есть ли сертификат.
spa8000.cert = Installed
# Открыт ли шлюз для изменения конфигурации.
spa8000.customization = Open
# Время и аптайм. Не забывайте про NTP, товарищи.
spa8000.time = 1/12/2003 14:15:42
spa8000.system.uptime = 11 days and 02:15:42
# Средства для рисования красивых графиков, разнообразные счетчики
# сообщений, пакетов и байт.
spa8000.rtp.packets.sent = 3463097
spa8000.rtp.bytes.sent = 646834968
spa8000.rtp.packets.recv = 3435569
spa8000.rtp.bytes.recv = 641524220
spa8000.sip.msg.sent = 76279
spa8000.sip.bytes.sent = 36830167
spa8000.sip.msg.recv = 73969
spa8000.sip.bytes.recv = 30078139
# Autodiscovery линии.
# Статус линии.
spa8000.line{#LINE}.hook.state = On
# Статус регистрации линии.
spa8000.line{#LINE}.reg.state = Registered
# Дата и время последней регистрации.
spa8000.line{#LINE}.reg.time = 1/12/2003 14:08:01
# Количество секунд до перерегистрации.
spa8000.line{#LINE}.reg.next = 1321 s
# Состояние уведомления о голосовой почте.
spa8000.line{#LINE}.mvi = No
# Состояние уведомления о callback.
spa8000.line{#LINE}.callback = No
# Последний номер, на который звонили с этой линии.
spa8000.line{#LINE}.last.called = 8965ХХХХХХХ
# Последний номер с которого звонили на линию.
spa8000.line{#LINE}.last.caller = +7911ХХХХХХХ
"info","SPA8000","CFH01N704858","6.1.12(XU)","1.0.0","D0C789784BE4","Installed","Open","1/12/2003 14:15:42","11 days and 02:15:42",3463097,646834968,3435569,641524220,76279,36830167,73969,30078139
"line1","On","Registered","1/12/2003 14:08:01",1321,"No","No","8965ХХХХХХХ","+7911ХХХХХХХ"
"line2",
. . .
#!/usr/bin/python
# Get Cisco SPA status for Zabbix.
# codecs импортируется, если происходит отладка скрипта с открытием локального Файла.
#import codecs
import csv
import datetime
import os.path
import re
import sys
import tempfile
import time
import urllib
# Ссылка на интерфейс.
url = 'http:///voice/'
# Путь до файла кэша.
temp = tempfile.gettempdir()
base = temp + '/spa.csv'
# Генератор кэша.
# Если файл кэша не существует или старее 30 секунд, то получаем данные из web-интерфейса.
# Кэш проверяется и создается всегда самым первым, потому что все данные возвращаются
# на основе выборок из файла кэша, то есть напрямую со страницы данные читаются только
# в кэш.
if(not(os.path.exists(base)) or ((int(time.time()) - os.path.getmtime(base)) > 30)):
# Читаем HTML страницу.
html = urllib.urlopen(url).read()
# Отладочная секция - читает файл с диска.
#f = codecs.open("text.html", 'r', "utf-8")
#html = f.read()
#f.close()
# Нормализуем и парсим HTML.
# Приводим текст к одной строке.
html = re.sub(r"\n+", " ", html)
# Убираем пробелы между тегами.
html = re.sub(r">\s+<", "><", html)
# Страница очень длинная - там все вкладки интерфейса. Чтобы уменьшить вероятность
# выборки не того отрезаем нужный нам кусок страницы.
html = re.search(r".+?Trunk", html).group(0)
# Получаем количество линий.
count = len(re.findall(r"]+>]+>Line\s(\d+)\sStatus",html))
# Извлекаем все данные вперемешку. Так как в HTML формат всех полей с данными
# одинаковый, то просто ищем все совпавшие кусочки данных и считаем их по
# умолчанию значениями. дальше разберутся.
data = re.findall(r"([^<:>]+):.+?]+>([^<]*)",html)
# Создаем CSV файл.
number = 0
rows = []
# Создаем заголовки строк.
rows.append(['info'])
count += 1
for i in range (1, count):
rows.append(['line' + str(i)])
count -= 1
# Заполняем строки. Выбираем из собранных данных все по одному и внимательно
# присматриваемся. Так как данные лежат в массиве в том порядке, в котором
# они отображаются на странице, то можем считать, что все значения до определенного
# относятся к общей информации, а все что дальше, относится к линиям. Так все и устроено
# первое значение каждой линии - это Hook State. Все что находится до первого такого значения
# относится к общей информации, все что после - к линиям.
# Цикл по извлеченным данным.
for entry in data:
# Значение, по которому разделяются данные общей информации и линий.
if(entry[0] == 'Hook State'):
number += 1
# Обрабатываем все нужные данные, кроме всяких Call 1 Forward и иже с ними.
if(not(re.match(r'Call\s\d+\s', entry[0]))):
value = entry[1]
# Преобразуем время в соответствующих полях. В Zabbix время уходит в виде unixtime.
if(((entry[0] == 'Current Time') or (entry[0] == 'Last Registration At')) and (value)): # 1/13/2003 14:03:52
if(value != '0/0/0 00:00:00'):
value = int(time.mktime(datetime.datetime.strptime(entry[1], "%m/%d/%Y %H:%M:%S").timetuple()))
else:
value = 0
# Извлекаем количество секунд.
if((entry[0] == 'Next Registration In') and (value)): # 1263 s
value = int(entry[1].split()[0])
# Сохраняем значение в соответствующей строке массива.
rows[number].extend([value])
# Сохраняем кэш.
with open(base, 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(rows)
csvfile.close()
# Ну вот, кэш сохранен, можно теперь его использовать для вывода данных. Проверяем
# наличие параметров. Если они переданы, значит мы хотим чего-то конкретного.
if(len(sys.argv) > 1):
# Открываем файл кэша и ищем строку, которую мы запрашиваем первым параметром.
with open(base, 'rb') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
# TODO: Прерывание цикла, если строка нашлась.
if(row[0] == sys.argv[1]):
line = row
csvfile.close()
# Проверяем, что запрошенная строка вообще есть в кэше.
if('line' in locals()):
# Определяем, что у нас спрашивают вторым параметром, и что вообще возвращать.
# Блок общей информации.
if(line[0] == 'info'):
try:
print({
'name': line[1],
'serial': line[2],
'software': line[3],
'hardware': line[4],
'mac': line[5],
'cert': line[6],
'customization': line[7],
'time': line[8],
'uptime': line[9],
'rtp.packets.sent': line[10],
'rtp.bytes.sent': line[11],
'rtp.packets.recv': line[12],
'rtp.bytes.recv': line[13],
'sip.msg.sent': line[14],
'sip.bytes.sent': line[15],
'sip.msg.recv': line[16],
'sip.bytes.recv': line[17]
}.get(sys.argv[2]))
# Если запрошенного поля не нашлось, так и говорим.
except IndexError as e:
print('ZBX_UNSUPPORTED')
# Блок линий.
else:
try:
print({
'hook.state': line[1],
'reg.state': line[2],
'reg.time': line[3],
'reg.next': line[4],
'mvi': line[5],
'callback': line[6],
'last.called': line[7],
'last.caller': line[8],
}.get(sys.argv[2]))
except IndexError as e:
print('ZBX_UNSUPPORTED')
# Если запрашиваемая строка не нашлась в кэше, то тоже возвращаем ошибку.
# Это позволяет не смущать Zabbix пустым результатом.
else:
print('ZBX_UNSUPPORTED')
else:
# Получаем autodiscovery для линий.
# Выходная строка.
s = ""
# Открываем файл кэша и читаем его, формируя выходную строку.
with open(base, 'rb') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
# Проставляем разделители.
if(len(s) > 0):
s = s + ","
# Формируем JSON строку вручную.
if(row[0] != 'info'):
s = s + '{"{#LINE}":"' + str(row[0]) + '"}'
csvfile.close()
# Выводим сформированную строку.
print('{"data":[' + s + ']}')
# Завершаем работу скрипта.
quit()
sudo chmod +x /share/zabbix/externalscripts/zabbix_spa8000.py
/share/zabbix/externalscripts/zabbix_spa8000.py
{"data":[{"{#LINE}":"line1"},{"{#LINE}":"line2"},{"{#LINE}":"line3"},{"{#LINE}":"line4"},{"{#LINE}":"line5"},{"{#LINE}":"line6"},{"{#LINE}":"line7"},{"{#LINE}":"line8"}]}
/share/zabbix/externalscripts/zabbix_spa8000.py info serial
CFH01N704858
/etc/zabbix_agentd.conf.d/spa8000.conf
UserParameter=spa[],/share/zabbix/externalscripts/zabbix_spa.py $1 $2
UserParameter=spa.lines,/share/zabbix/externalscripts/zabbix_spa.py
sudo service zabbix-agent restart
zabbix_agentd -t spa.lines
spa.lines [t|{"data":[{"{#LINE}":"line1"},{"{#LINE}":"line2"},{"{#LINE}":"line3"},{"{#LINE}":"line4"},{"{#LINE}":"line5"},{"{#LINE}":"line6"},{"{#LINE}":"line7"},{"{#LINE}":"line8"}]}]
zabbix_agentd -t spa[info,serial]
spa[info,serial] [t|CFH01N70
4858]
3.0
2016-09-09T11:04:05Z
Шаблоны общие
Template_Cisco_Linksys_SPA
Template Cisco(Linksys) SPA
Шаблон мониторинга Cisco(Linksys) SPA.
Шаблоны общие
RTP
SIP
Информация
Линии
-
Сертификат
0
0
spa[info,cert]
3600
10
0
0
4
0
0
0
0
1
0
0
Наличие сертификата SPA.
0
Информация
-
Блокировка
0
0
spa[info,customization]
3600
10
0
0
4
0
0
0
0
1
0
0
Блокировка конфигурации SPA от изменения.
0
Информация
-
Аппаратное обеспечение
0
0
spa[info,hardware]
3600
10
0
0
4
0
0
0
0
1
0
0
Версия аппаратного обеспечения SPA.
0
Информация
-
MAC-адрес
0
0
spa[info,mac]
3600
10
0
0
4
0
0
0
0
1
0
0
МАС-адрес SPA.
0
Информация
-
Имя
0
0
spa[info,name]
3600
10
0
0
4
0
0
0
0
1
0
0
Hostname SPA.
0
Информация
-
Получено байт RTP
0
0
spa[info,rtp.bytes.recv]
30
30
60
0
3
B
0
0
0
0
1
0
0
Количество полученных байт RTP.
0
RTP
-
Отправлено байт RTP
0
0
spa[info,rtp.bytes.sent]
30
30
60
0
3
B
0
0
0
0
1
0
0
Количество отправленных байт RTP.
0
RTP
-
Получено пакетов RTP
0
0
spa[info,rtp.packets.recv]
30
30
60
0
3
0
0
0
0
1
0
0
Количество полученных пакетов RTP.
0
RTP
-
Отправлено пакетов RTP
0
0
spa[info,rtp.packets.sent]
30
30
60
0
3
0
0
0
0
1
0
0
Количество отправленных пакетов RTP.
0
RTP
-
Серийный номер
0
0
spa[info,serial]
3600
10
0
0
4
0
0
0
0
1
0
0
Серийный номер SPA.
0
Информация
-
Получено байт SIP
0
0
spa[info,sip.bytes.recv]
30
30
60
0
3
B
0
0
0
0
1
0
0
Количество полученных байт SIP.
0
SIP
-
Отправлено байт SIP
0
0
spa[info,sip.bytes.sent]
30
30
60
0
3
B
0
0
0
0
1
0
0
Количество отправленных байт SIP.
0
SIP
-
Получено сообщений SIP
0
0
spa[info,sip.msg.recv]
30
30
60
0
3
0
0
0
0
1
0
0
Количество полученных сообщений SIP.
0
SIP
-
Отправлено сообщений SIP
0
0
spa[info,sip.msg.sent]
30
30
60
0
3
0
0
0
0
1
0
0
Количество отправленных сообщений SIP.
0
SIP
-
Программное обеспечение
0
0
spa[info,software]
3600
10
0
0
4
0
0
0
0
1
0
0
Версия программного обеспечения SPA.
0
Информация
-
Локальное время
0
0
spa[info,time]
60
30
60
0
3
unixtime
0
0
0
0
1
0
0
Локальное время SPA.
0
Информация
-
Аптайм
0
0
spa[info,uptime]
60
30
60
0
3
uptime
0
0
0
0
1
0
0
Время непрерывной работы SPA.
0
Информация
Линии
0
spa.lines
3600
0
0
0
0
0
0
30
Линии SPA.
Статус callback линии {#LINE}
0
0
spa[{#LINE},callback]
30
10
0
0
4
0
0
0
0
1
0
0
Статус callback линии {#LINE}.
0
Линии
Статус Hook линии {#LINE}
0
0
spa[{#LINE},hook.state]
30
10
0
0
4
0
0
0
0
1
0
0
Статус Hook линии {#LINE}.
0
Линии
Последний исходящий с линии {#LINE}
0
0
spa[{#LINE},last.called]
30
5
0
0
4
0
0
0
0
1
0
0
Последний исходящий с линии {#LINE}.
0
Линии
Последний входящий на линию {#LINE}
0
0
spa[{#LINE},last.caller]
30
5
0
0
4
0
0
0
0
1
0
0
Последний входящий на линию {#LINE}.
0
Линии
Статус MVI линии {#LINE}
0
0
spa[{#LINE},mvi]
30
10
0
0
4
0
0
0
0
1
0
0
Статус MVI линии {#LINE}.
0
Линии
Интервал регистрации линии {#LINE}
0
0
spa[{#LINE},reg.next]
30
30
60
0
3
uptime
0
0
0
0
1
0
0
Время до следующей регистрации линии {#LINE}.
0
Линии
Статус регистрации линии {#LINE}
0
0
spa[{#LINE},reg.state]
30
10
0
0
4
0
0
0
0
1
0
0
Статус регистрации линии {#LINE}.
0
Линии
Локальное время регистрации линии {#LINE}
0
0
spa[{#LINE},reg.time]
30
30
60
0
3
unixtime
0
0
0
0
1
0
0
Локальное время регистрации линии {#LINE}.
0
Линии
{Template_Cisco_Linksys_SPA:spa[{#LINE},reg.state].count(#2,Registered,eq,0)}<2
Ошибка регистрации линии {#LINE}
0
4
Линия {#LINE} не может зарегистрироваться в течение 1 минуты.
0
{Template_Cisco_Linksys_SPA:spa[info,uptime].last()}<180
SPA перезагружен
0
2
Время работы SPA менее 3 минут.
0
Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |