У папярэднім артыкуле я распавёў як атрымліваць сесію аўтарызацыі і падстаўляць яе ў лакальны макрас хаста. У гэтым артыкуле я распавяду як пасябраваць Zabbix з Asterisk без вонкавых скрыптоў і ПА.
Ідэя "здружыць" гэтыя дзве сістэмы нарадзілася даўно, прычым без усталёўкі дадатковага софту і скрыптоў. Хуткае гугленне выдавала мноства варыянтаў рашэнняў, усё зводзілася да таго, што закіньце скрыпты (на пыху, вежы, пітон і т. п.) на сервер, і будзе вам шчасце. Мне ж хацелася рэалізаваць маніторынг "са скрынкі" – без знешніх скрыптоў і ўстаноўкі дадатковага софту на сервер з маніторынгам і АТС.
Правозіўся я з гэтым у суме 4 працоўныя дні, але вынік каштаваў таго. Праца праз інтэрфейс AMI, нізкаўзроўневыя выяўленне, трыгеры, а галоўнае, на падлучэнне АТС і ўсе астатнія налады зараз сыходзіць хвілін 15.
У наяўнасці заббікс 4.4, каля 100 штук Астэрыскаў 13 версіі. Нейкія АТС ідуць з вэб інтэрфейсам FreePBX, нейкія з голай кансоллю, кучай хітрасцяў і інтэграцыяй праз диалплан.
Атрымліваем дадзеныя з АТС
Першы і асноўны момант, які трэба вырашыць - атрыманне дадзеных аб балях і сип рэгістрацыях. Для гэтага ў АТС існуюць інтэрфейсы AGI, AMI, ARI і SSH кансоль. Дадатковыя модулі па зразумелых прычынах не разглядаў.
Для пачатку трэба разабрацца, што з сябе ўяўляюць гэтыя агі, амі, ары….
- AGI - выкарыстанне скрыптоў у диалплане. Галоўным чынам выкарыстоўваецца для кіравання выклікамі.
- AMI – умее аддаваць усю неабходную інфармацыю, працуе праз порт 5038 па аналогіі з Telnet. Нам падыходзіць!
- ARI - сучасна, модна, JSONна. Шмат магчымасцяў, фармат дадзеных у зразумелым выглядзе для Zabbix, але для мяне няма галоўнага: нельга кантраляваць сип рэгістрацыю. Яшчэ адзін мінус, для баляў ёсць толькі два станы online/offline, хоць станаў больш і іх улічваць карысна пры дыягностыцы.
- SSH можа ўсё, але часам яго не даюць з-за «меркаванняў бяспекі». Меркаванні могуць быць рознымі, разбіраць іх не буду.
Тым не менш, пры ўсіх сваіх недахопах ARI закрывае 90% усіх запатрабаванняў па маніторынгу.
Zabbix і Telnet – маё расчараванне
AMI ведаю добра, у свой час рэалізоўваў адсочванне страт у гутарках з дзяленнем па выдаленых офісах, кіраванне званкамі і да т.п. З Telnet таксама ўсё лімітава ясна: адчыняй падлучэнне, ішлі каманды і чытай адказ. Што я і зрабіў, але вынік мяне расчараваў.
Telnet у заббікса не такі як у кансолі Linux, ён крыху прасцейшы і заменчаны пад стандартную аўтарызацыю тыпу лагін/пароль. Калі логіка аўтарызацыі іншая, і няма запыту пары лагін/пароль, вылятае памылка. Пасля марных спроб абыйсці патрабаванне аўтарызацыі палез глядзець зыходнікі модуля Telnet.
Я зразумеў, што пакуль не будзе традыцыйнага запыту лагіна з паролем, далей не прасунуся. Дзеля цікавасці, выкінуў з кода ўсё, што да аўтарызацыі, перасабраў усё. Працуе! Але пад патрабаванні не падыходзіць. Ідзем далей…
Вяртаемся да пошуку
Перачытаў яшчэ раз дакументацыю па ARI, правёў дадатковыя тэсты - няма тут сіп рэгістрацый. Піры ёсць, размовы ёсць, брыджы ёсць, рэгістрацый няма. У нейкі момант нават задумаўся, ці так патрэбны нам сіп рэгістрацыі?
Па пацешным збегу абставінаў, у гэты момант прылятае чарговы запыт ад карыстальніка, з праблемай выходных званкоў. Праблема была ў падвісанні сип рэгістрацыі і вырашалася звычайнай перазагрузкай модуля.
asterisk -rx "sip reload"Было б выдатна па вэбе звяртацца да AMI: гэта б вырашыла ўсе праблемы, падумаў я. Пачынаю капаць у гэтым кірунку, і літаральна першы радок пошуку вядзе на афіцыйную дакументацыю Asterisk, у якой гаворыцца, што для маіх задач ёсць опцыя. webenabled у файле /etc/asterisk/manager.conf, якую трэба ўсталяваць у значэнне YES, у секцыі [general]
Пасля гэтага, праз звычайны вэб запыт выгляду атрымліваем усю неабходную інфармацыю.
Пры выкарыстанні інтэрфейсу FreePBX, праз вэб нельга ўключыць дадзеную опцыю, уключаць трэба праз кансоль, уносячы праўкі ў файл manager.conf. FreePBX не сцірае яе пры зменах канфігурацыі праз вэб.
Колькі працаваў з рознага роду інтэграцыямі Asterisk, ніколі не бачыў, каб недзе згадвалася гэтая функцыя. Мяне здзівіла, што ніхто не апісвае гэты метад узаемадзеяння з АТС. Нават спецыяльна палез шукаць інфармацыю па дадзенай тэме: практычна нічога няма ці выкарыстоўвалася для зусім іншых задач.
WEB AMI - што за звер?
Даданне опцыі webenabled у файл manager.conf адкрывала паўнавартасны доступ да кіравання АТСкай праз вэб. Усе каманды, даступныя праз звычайны AMI, зараз ёсць у вэбе, можна слухаць падзеі ад АТС праз сокет. Прынцып працы нічым не адрозніваецца ад кансольнага AMI. Пасля актывацыі дадзенай опцыі, да АТС можна звярнуцца па наступных адрасах:
- вэб старонка з простым інтэрфейсам, для тэстаў і ручной адпраўкі запытаў. Усе адказы фарматуюцца ў чытэльны HTML выгляд. Для маніторынгу не надта падыходзіць.
- толькі тэкставы вывад, фармат аналагічны кансольнаму AMI
- толькі тэкставы вывад, у фармаце XML. Нам падыходзіць!

Тут я было падумаў: «Вось яно - рашэнне! Цяпер усё будзе гатова! Ізі-пізі лямон сквізі», але радавацца было пакуль рана. Для атрымання патрэбнай нам інфармацыі дастаткова выкарыстоўваць GET запыт з патрэбнымі дзеяннем дзеянне, які ў адказ вяртае xml са спісам усіх рэгістрацый і іх станам. Гэта ўсё выдатна, але патрэбна аўтарызацыя з запамінаннем сесіі з кукі. Калі тэстуеш у браўзэры, не задумваешся пра гэты працэс.
Працэс аўтарызацыі
Спачатку мы звяртаемся на адрас , у адказ нам сервер дасылае куку з сесіяй аўтарызацыі. Вось так выглядае HTTP запыт:
https://ats:8089/mxml?action=login&username=zabbix&secret=zabbix
Host: ats:8089
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1Адказ:
GET: HTTP/1.1 200 OK
Server: Asterisk/13.29.2
Date: Thu, 18 Jun 2020 17:41:19 GMT
Cache-Control: no-cache, no-store
Content-type: text/xml
Set-Cookie: mansession_id="6f5de42c"; Version=1; Max-Age=600
Pragma: SuppressEvents
Content-Length: 146
<ajax-response>
<response type="object" id="unknown">
<generic response="Success" message="Authentication accepted"/>
</response>
</ajax-response> Для працы тамака трэба mansession_id="6f5de42c"г.зн. сама кука аўтарызацыі.
Кантэнт трэба толькі праверыць наяўнасць адказу.Authentication accepted». Далей, пры ўсіх зваротах да сервера АТС нам неабходна будзе дадаваць у запыт куку аўтарызацыі.
https://ats:8089/mxml?action=SIPpeers
Host: ats:8089
Connection: close
Cookie: mansession_id="6f5de42c"Як атрымліваць куку аўтарызацыі і выкарыстоўваць у іншых запытах чытайце тут: «»
Для стварэння элементаў адсочвання ў заббіксе буду выкарыстоўваць аўта выяўленне.
Аўта выяўленне
Для аўто выяўлення рэгістрацый і адсочвання станаў баляў неабходна звяртацца да адрасу: або
У адказ АТС вяртае нам XML адказ:
<ajax-response>
<response type="object" id="unknown">
<generic response="Success" eventlist="start" message="Registrations will follow"/>
</response>
...
<response type="object" id="unknown">
<generic event="RegistryEntry" host="login.mtt.ru" port="5060" username="111111" domain="login.mtt.ru" domainport="5060" refresh="105" state="Registered" registrationtime="1592502142"/>
</response>
<response type="object" id="unknown">
<generic event="RegistryEntry" host="voip.uiscom.ru" port="5060" username="222222" domain="voip.uiscom.ru" domainport="5060" refresh="105" state="Registered" registrationtime="1592502142"/>
</response>
<response type="object" id="unknown">
<generic event="RegistryEntry" host="voip.uiscom.ru" port="5060" username="333333" domain="voip.uiscom.ru" domainport="5060" refresh="105" state="Registered" registrationtime="1592502142"/>
</response>
...
</ajax-response> У адказе шмат смецця, таму ў прэпрацэсінгу мы яго фільтруем па шаблоне. XPath: //response/generic[@host]
Далей пачынаецца самае цікавае. Каб працаваць з выяўленнем і дынамічна ствараць элементы, трэба, каб адказ быў у JSON фармаце. XML пры аўта выяўленнях не падтрымліваецца.
Для пераўтварэння XML у JSON прыйшлося крыху пагуляцца з аўта заменай, для чаго я зрабіў скрыпт на JS

Цікавы момант, у адказе АТС усе параметры апраўляюцца адзінарнымі двукоссямі, а пасля прымянення шаблону //response/generic[@host] яны замяняюцца на падвойныя.
Для стварэння элементаў выкарыстоўваем зменныя з XML адказу (цяпер JSON).

SIP Registry
Для сіп рэгістрацый выкарыстоўваем тры зменныя: імя карыстальніка, гаспадар, порт. Мяне задавальняла назва элемента 111111@login.mtt.ru:5060, Сітуацый калі трэба выкарыстоўваць усе пяць зменных я не знайшоў.
Галоўны элемент, які атрымлівае інфармацыю аб усіх рэгістрацыях, Asterisk - AMI SIPshowregistry. Раз у хвіліну ён звяртаецца GET запытам да , пасля чаго дадзеныя XML адказу перадаюцца ўсім залежным элементам для аналізу. Элемент па кожнай рэгістрацыі ствараю залежнымі ад яго. Гэта зручна, бо актуальную інфармацыю мы атрымліваем за адзін запыт, а не для кожнага асобна. У дадзенай рэалізацыі ёсць істотны мінус - нагрузка на працэсар.
Пры тэсціраванні да 100 залежных элементаў, нагрузку не заўважыў, але пры 1700 элементаў, гэта давала прыкметную 15 секундную нагрузку на працэсар. Майце гэта на ўвазе, калі ў вас вялікая колькасць залежных элементаў.
Як варыянт для «размазвання» нагрузкі ці ўсталёўкі рознай частаты апытання элемента, можна вынесці логіку апрацоўкі ў кожны элемент асобна.
Атрыманую інфармацыю я не захоўваю ў галоўным элеменце. Па-першае, не бачу ў гэтым неабходнасці, а па-другое, калі адказ больш за 64К, то заббікс яго абразае.
Паколькі для залежнага элемента ў нас выкарыстоўваецца поўны XML адказ, нам трэба ў прэпрацэсінг атрымаць значэнне дадзенага элемента. Праз XPath гэта робіцца так:
string(//response/generic[@event=«RegistryEntry»]][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@ state)
Для статутаў рэгістрацый не стаў выкарыстоўваць тэкставыя статуты, а перавёў іх у лікавы выгляд з дапамогай JavaScript:
switch(value) {
case 'Registered':
return 1;
case 'Unregistered':
return 0;
default:
return -1;
}
SIP Peers
Па аналогіі з сип рэгістрацыямі, ёсць галоўны элемент Asterisk - AMI SIPshowregistry, да якога дадаюцца залежныя.
Тут ствараюцца два залежныя элементы:
- Статус балю ў тэкставым выглядзе
- Час водгуку прылады - калі статус ОК, то пішацца час адказу прылады, інакш "-1"
Сам шлях да элемента ўжо крыху прасцей XPath:
string(//response/generic[@objectname="{#SIP_PEER_OBEJECTNAME}"]/@status)
Для другога элемента выкарыстоўваў JavaScript, каб аддзяліць час водгуку ад статусу балю, паколькі захоўваюцца яны разам:
if(value.substring(0,2) == 'OK'){
return value.match(/(d+)/gm);
}
else {
return -1;
}Заключэнне
Рашэнне са скрынкі можа быць складаным і не адразу зразумелым. Узрастае гнуткасць і пераноснасць паміж рознымі сістэмамі
Усім прыемнай і лёгкай інтэграцыі! Шаблон і інструкцыя па наладзе на .
Крыніца: habr.com
