No artigo anterior Eu expliquei como obter uma sessão de autorização e inseri-la no macro local do host. Neste artigo, vou mostrar como integrar o Zabbix com o Asterisk sem scripts e softwares externos.
A ideia de 'integrar' esses dois sistemas surgiu há muito tempo, sem a necessidade de instalar software e scripts adicionais. Uma busca rápida no Google mostrava várias opções de soluções, todas resumindo-se a colocar scripts (em PHP, Bash, Python, etc.) no servidor e tudo ficaria resolvido. No entanto, eu queria implementar a monitoração 'pronta para uso' — sem scripts externos e instalações adicionais de software no servidor de monitoramento e na central telefônica.
Eu trabalhei nisso por um total de 4 dias úteis, mas o resultado valeu a pena. O trabalho através da interface AMI, a detecção de baixo nível, os gatilhos, e o principal, a conexão da central telefônica e todas as outras configurações agora levam apenas 15 minutos.
Em uso está o Zabbix 4.4, com cerca de 100 Asterisks versão 13. Algumas centrais telefônicas vêm com a interface web FreePBX, outras com um console simples, muitas artimanhas e integração via plano de discagem.
Obtendo dados da central telefônica
O primeiro e mais importante aspecto a ser resolvido é a obtenção de dados sobre pares e registros SIP. Para isso, existem interfaces AGI, AMI, ARI e console SSH na central telefônica. Não considerei módulos adicionais por razões óbvias.
Para começar, precisamos entender o que são esses AGI, AMI, ARI...
- AGI — uso de scripts no plano de discagem. É principalmente utilizado para gerenciar chamadas.
- AMI — consegue fornecer todas as informações necessárias, funciona através da porta 5038, de forma semelhante ao Telnet. Isso nos serve!
- ARI — moderno, na moda, em JSON. Muitas possibilidades, formato de dados em um visual compreensível para o Zabbix, mas para mim falta o principal: não é possível controlar o registro SIP. Outro ponto negativo é que para pares há apenas dois estados: online/offline, embora existam mais estados e considerá-los é útil ao diagnosticar.
- SSH — pode tudo, mas às vezes não é proporcionado por razões de 'segurança'. As razões podem ser variadas, não vou detalhá-las.
Apesar de todas as suas limitações, o ARI atende 90% de todas as necessidades de monitoramento.
Zabbix e Telnet — minha decepção
Conheço bem o AMI, na minha época implementei rastreamento de perdas em chamadas com divisão por escritórios remotos, gerenciamento de chamadas e assim por diante. Com Telnet também está tudo claro: abra a conexão, envie comandos e leia a resposta. E foi isso que fiz, mas o resultado me decepcionou.
O Telnet do Zabbix não é como o do console Linux, é um pouco mais simples e adaptado para a autenticação padrão tipo login/senha. Se a lógica de autenticação for diferente, e não houver solicitação do par login/senha, um erro aparece. Depois de várias tentativas infrutíferas de contornar a exigência de autenticação, fui olhar a fonte do módulo Telnet.
Entendi que, enquanto não houvesse a solicitação tradicional de login com senha, não conseguiria avançar. Por curiosidade, removi do código tudo que diz respeito à autenticação, recompilhei tudo. Funciona! Mas não atende aos requisitos. Vamos em frente…
Voltando à busca
Li novamente a documentação sobre ARI, fiz testes adicionais - não há registros SIP aqui. Existem pares, existem chamadas, existem bridges, mas não há registros. Em um determinado momento, até pensei, será que realmente precisamos de registros SIP?
Por uma curiosidade engraçada, nesse momento chega outra solicitação de um usuário, com um problema de chamadas de saída. O problema estava na suspensão do registro SIP e foi resolvido com uma simples reinicialização do módulo.
asterisk -rx "sip reload"Seria ótimo acessar o AMI pela web: isso resolveria todos os problemas, pensei. Começo a investigar nessa direção, e literalmente a primeira linha de pesquisa leva à documentação oficial do Asterisk, onde diz que para minhas tarefas há uma opção webenabled no arquivo /etc/asterisk/manager.conf, que precisa ser definida como YES, na seção [general]
Depois disso, através de uma solicitação web comum do tipo recebemos todas as informações necessárias.
Ao usar a interface FreePBX, não é possível ativar essa opção pela web, deve-se ativá-la pelo console, fazendo alterações no arquivo manager.conf. O FreePBX não a apaga ao alterar a configuração pela web.
Desde que trabalhei com diversos tipos de integrações Asterisk, nunca vi essa função mencionada em lugar algum. Fiquei surpreso que ninguém descreve esse método de interação com a PABX. Até busquei informações especificamente sobre esse tema: praticamente não há nada ou foi usado para tarefas completamente diferentes.
WEB AMI - que bicho é esse?
Adicionando a opção webenabled . Isso facilitará a configuração e o uso do armazenamento HashiCorp com o GitLab. manager.conf abriu o acesso completo ao gerenciamento da central telefônica via web. Todos os comandos disponíveis através do AMI normal agora estão na web, e é possível ouvir eventos da central através de um socket. O princípio de funcionamento não difere do AMI de console. Após a ativação dessa opção, a central pode ser acessada pelos seguintes endereços:
— página web com uma interface simples, para testes e envio manual de solicitações. Todas as respostas são formatadas em um visual HTML legível. Não é muito adequada para monitoramento.
— apenas saída de texto, formato semelhante ao AMI de console
— apenas saída de texto, no formato XML. Isso nos serve!

Aqui eu pensei: "É isso – a solução! Agora tudo estará pronto! Facinho, facinho", mas era cedo para comemorar. Para obter as informações que precisamos, é suficiente usar uma solicitação GET com a ação desejada, ação, que retorna um XML com a lista de todos os registros e seus estados. Isso é ótimo, mas requer autenticação com recuperação de sessão de cookies. Quando você testa no navegador, não pensa muito sobre esse processo.
Um pouco mais detalhado e por etapas:
No início, nos dirigimos ao endereço , em resposta, o servidor nos envia um cookie com a sessão de autenticação. Assim é como fica a solicitação 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: pt-BR,pt;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: 1Resposta:
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 Para funcionamento lá é necessário mansession_id="6f5de42c", ou seja, o próprio cookie de autenticação.
O conteúdo precisa apenas verificar a presença da resposta "Autenticação aceita". Em seguida, em todas as solicitações ao servidor da central, precisaremos adicionar o cookie de autenticação à solicitação.
https://ats:8089/mxml?action=SIPpeers
Host: ats:8089
Connection: close
Cookie: mansession_id="6f5de42c"Como obter o cookie de autenticação e usá-lo em outras solicitações, leia aqui: "»
Para criar elementos de monitoramento no Zabbix, utilizarei a auto descoberta.
Auto descoberta
Para a auto descoberta de registros e monitoramento de estados dos peers, é necessário acessar o endereço: ou
Em resposta, a central retorna um XML:
...
... A resposta está cheia de lixo, por isso filtramos no pré-processamento de acordo com o padrão XPath: //response/generic[@host]
A partir daqui, as coisas ficam realmente interessantes. Para trabalhar com a detecção e criar elementos dinamicamente, a resposta precisa estar no formato JSON. XML não é suportado para auto detecção.
Para converter XML em JSON, tive que brincar um pouco com a substituição automática, para isso fiz um script em JS

Um ponto interessante é que na resposta da central todos os parâmetros são envoltos em aspas simples, e depois de aplicar o padrão //response/generic[@host] são substituídos por aspas duplas.
Para criar elementos, usamos variáveis da resposta XML (agora JSON).

Registro SIP
Para registros SIP, usamos três variáveis: nome de usuário, host, port. Eu estava satisfeito com o nome do elemento 111111@login.mtt.ru:5060, não encontrei situações que precisassem usar as cinco variáveis.
O elemento principal que recebe informações sobre todos os registros, Asterisk — AMI SIPshowregistry. A cada minuto, ele faz uma solicitação GET para , após o que os dados da resposta XML são enviados a todos os elementos dependentes para análise. Crio um elemento para cada registro que é dependente dele. Isso é conveniente, pois obtemos informações atualizadas em uma única solicitação, e não para cada um separadamente. Esta implementação tem uma desvantagem significativa — carga no processador.
Durante o teste com até 100 elementos dependentes, não percebi carga, mas com 1700 elementos, isso causava uma carga de 15 segundos perceptível no processador. Tenha isso em mente se você tiver um grande número de elementos dependentes.
Uma opção para 'espalhar' a carga ou estabelecer diferentes frequências de polling do elemento é extrair a lógica de processamento em cada elemento separadamente.
Não mantenho as informações recebidas no elemento principal. Em primeiro lugar, não vejo necessidade nisso, e em segundo lugar, se a resposta for maior que 64K, o Zabbix a corta.
Como usamos a resposta XML completa para o elemento dependente, precisamos obter o valor desse elemento no pré-processamento. Através de XPath isso é feito assim:
string(//response/generic[@event="RegistryEntry"][@username="{#SIP_REGISTRY_USERNAME}"][@host="{#SIP_REGISTRY_HOST}"][@port="{#SIP_REGISTRY_PORT}"]/@state)
Para os status de registros, não usei status textuais, mas os converti para formato numérico usando JavaScript:
switch(value) {
case 'Registered':
return 1;
case 'Unregistered':
return 0;
default:
return -1;
}
SIP Peers
Assim como nas注册 SIP, há o elemento principal Asterisk — AMI SIPshowregistry, ao qual elementos dependentes são adicionados.
Aqui estão criados dois elementos dependentes:
- Status do peer em formato textual
- O tempo de resposta do dispositivo — se o status for OK, o tempo de resposta do dispositivo é registrado, caso contrário, "-1"
O caminho até o elemento já é um pouco mais simples XPath:
string(//response/generic[@objectname="{#SIP_PEER_OBEJECTNAME}"]/@status)
Para o segundo elemento, usei JavaScript para separar o tempo de resposta do status do peer, uma vez que eles são armazenados juntos:
if(value.substring(0,2) == 'OK'){
return value.match(/(d+)/gm);
}
else {
return -1;
}Conclusão
A solução "pronta para uso" pode ser complexa e não imediatamente clara. A flexibilidade e a portabilidade entre diferentes sistemas aumentam.
A todos uma integração agradável e fácil! O modelo e o guia de configuração em .
Fonte: habr.com
